Merge pull request #540 from johnny-smitherson/bevy-0.11

update bevy 0.11 - fix compile errors
This commit is contained in:
Sébastien Crozet
2023-11-04 18:32:55 +01:00
committed by GitHub
19 changed files with 124 additions and 917 deletions

View File

@@ -10,6 +10,7 @@
- Make `Wheel::friction_slip` public to customize the front friction applied to the vehicle controllers wheels.
- Add the `DebugRenderBackend::filter_object` predicate that can be implemented to apply custom filtering rules
on the objects being rendered.
- Switch the testbed to `bevy 0.11` and use its new Gizmos API for rendering lines.
## v0.17.2 (26 Feb. 2023)
### Fix

View File

@@ -40,21 +40,24 @@ bincode = "1"
Inflector = "0.11"
md5 = "0.7"
bevy_egui = "0.18"
bevy_ecs = "0.9"
bevy_egui = "0.22"
bevy_ecs = "0.11"
bevy_core_pipeline = "0.11"
bevy_pbr = "0.11"
bevy_sprite = "0.11"
#bevy_prototype_debug_lines = "0.7"
# Dependencies for native only.
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
bevy = {version = "0.9", default-features = false, features = ["bevy_winit", "render", "x11"]}
bevy = {version = "0.11", default-features = false, features = ["bevy_asset", "bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]}
# Dependencies for WASM only.
[target.'cfg(target_arch = "wasm32")'.dependencies]
bevy = {version = "0.9", default-features = false, features = ["bevy_winit", "render"]}
bevy = {version = "0.11", default-features = false, features = ["bevy_asset", "bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]}
#bevy_webgl2 = "0.5"
[dependencies.rapier]
package = "rapier2d-f64"
path = "../rapier2d-f64"
version = "0.17.0"
version = "0.17.2"
features = [ "serde-serialize", "debug-render", "profiler" ]

View File

@@ -40,21 +40,24 @@ bincode = "1"
Inflector = "0.11"
md5 = "0.7"
bevy_egui = "0.18"
bevy_ecs = "0.9"
bevy_egui = "0.22"
bevy_ecs = "0.11"
bevy_core_pipeline = "0.11"
bevy_pbr = "0.11"
bevy_sprite = "0.11"
#bevy_prototype_debug_lines = "0.7"
# Dependencies for native only.
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
bevy = {version = "0.9", default-features = false, features = ["bevy_winit", "render", "x11"]}
bevy = {version = "0.11", default-features = false, features = ["bevy_sprite", "bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]}
# Dependencies for WASM only.
[target.'cfg(target_arch = "wasm32")'.dependencies]
bevy = {version = "0.9", default-features = false, features = ["bevy_winit", "render"]}
bevy = {version = "0.11", default-features = false, features = ["bevy_sprite", "bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]}
#bevy_webgl2 = "0.5"
[dependencies.rapier]
package = "rapier2d"
path = "../rapier2d"
version = "0.17.0"
version = "0.17.2"
features = [ "serde-serialize", "debug-render", "profiler" ]

View File

@@ -39,21 +39,24 @@ md5 = "0.7"
Inflector = "0.11"
serde = { version = "1", features = [ "derive" ] }
bevy_egui = "0.18"
bevy_ecs = "0.9"
bevy_egui = "0.22"
bevy_ecs = "0.11"
bevy_core_pipeline = "0.11"
bevy_pbr = "0.11"
bevy_sprite = "0.11"
#bevy_prototype_debug_lines = { version = "0.7", features = [ "3d" ] }
# Dependencies for native only.
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
bevy = {version = "0.9", default-features = false, features = ["bevy_winit", "render", "x11"]}
bevy = {version = "0.11", default-features = false, features = ["bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]}
# Dependencies for WASM only.
[target.'cfg(target_arch = "wasm32")'.dependencies]
bevy = {version = "0.9", default-features = false, features = ["bevy_winit", "render"]}
bevy = {version = "0.11", default-features = false, features = ["bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]}
#bevy_webgl2 = "0.5"
[dependencies.rapier]
package = "rapier3d-f64"
path = "../rapier3d-f64"
version = "0.17.0"
version = "0.17.2"
features = [ "serde-serialize", "debug-render", "profiler" ]

View File

@@ -33,31 +33,34 @@ rand = "0.8"
rand_pcg = "0.3"
instant = { version = "0.1", features = [ "web-sys", "now" ]}
bitflags = "1"
glam = { version = "0.20", optional = true } # For Physx
glam = { version = "0.24", optional = true } # For Physx
num_cpus = { version = "1", optional = true }
physx = { version = "0.16", features = [ "glam" ], optional = true }
physx-sys = { version = "0.8", optional = true }
physx = { version = "0.19", features = [ "glam" ], optional = true }
physx-sys = { version = "0.11", optional = true }
crossbeam = "0.8"
bincode = "1"
md5 = "0.7"
Inflector = "0.11"
serde = { version = "1", features = [ "derive" ] }
bevy_egui = "0.18"
bevy_ecs = "0.9"
bevy_egui = "0.22"
bevy_ecs = "0.11"
bevy_core_pipeline = "0.11"
bevy_pbr = "0.11"
bevy_sprite = "0.11"
#bevy_prototype_debug_lines = { version = "0.7", features = [ "3d" ] }
# Dependencies for native only.
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
bevy = {version = "0.9", default-features = false, features = ["bevy_winit", "render", "x11"]}
bevy = {version = "0.11", default-features = false, features = ["bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]}
# Dependencies for WASM only.
[target.'cfg(target_arch = "wasm32")'.dependencies]
bevy = {version = "0.9", default-features = false, features = ["bevy_winit", "render"]}
bevy = {version = "0.11", default-features = false, features = ["bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]}
#bevy_webgl2 = "0.5"
[dependencies.rapier]
package = "rapier3d"
path = "../rapier3d"
version = "0.17.0"
version = "0.17.2"
features = [ "serde-serialize", "debug-render", "profiler" ]

View File

@@ -16,7 +16,7 @@ rand = "0.8"
getrandom = { version = "0.2", features = [ "js" ] }
Inflector = "0.11"
wasm-bindgen = "0.2"
obj-rs = { version = "0.6", default-features = false }
obj-rs = { version = "0.7", default-features = false }
bincode = "1"
serde = "1"

View File

@@ -17,7 +17,7 @@ rand = "0.8"
getrandom = { version = "0.2", features = [ "js" ] }
Inflector = "0.11"
wasm-bindgen = "0.2"
obj-rs = { version = "0.6", default-features = false }
obj-rs = { version = "0.7", default-features = false }
serde = "1"
bincode = "1"

View File

@@ -87,8 +87,8 @@ impl OrbitCameraPlugin {
}
impl Plugin for OrbitCameraPlugin {
fn build(&self, app: &mut App) {
app.add_system(Self::mouse_motion_system)
.add_system(Self::zoom_system)
.add_system(Self::update_transform_system);
app.add_systems(Update, Self::mouse_motion_system)
.add_systems(Update, Self::zoom_system)
.add_systems(Update, Self::update_transform_system);
}
}

View File

@@ -113,8 +113,8 @@ impl OrbitCameraPlugin {
}
impl Plugin for OrbitCameraPlugin {
fn build(&self, app: &mut App) {
app.add_system(Self::mouse_motion_system)
.add_system(Self::zoom_system)
.add_system(Self::update_transform_system);
app.add_systems(Update, Self::mouse_motion_system)
.add_systems(Update, Self::zoom_system)
.add_systems(Update, Self::update_transform_system);
}
}

View File

@@ -1,5 +1,5 @@
use crate::harness::Harness;
use crate::lines::DebugLines;
use bevy::gizmos::gizmos::Gizmos;
use bevy::prelude::*;
use rapier::math::{Point, Real};
use rapier::pipeline::{
@@ -7,70 +7,64 @@ use rapier::pipeline::{
};
#[derive(Resource)]
pub struct DebugRenderPipelineResource(pub DebugRenderPipeline);
pub struct RapierDebugRenderPlugin {
depth_test: bool,
pub struct DebugRenderPipelineResource {
pub pipeline: DebugRenderPipeline,
pub enabled: bool,
}
impl Default for RapierDebugRenderPlugin {
fn default() -> Self {
Self {
depth_test: cfg!(feature = "dim3"),
}
}
}
#[derive(Default)]
pub struct RapierDebugRenderPlugin {}
impl Plugin for RapierDebugRenderPlugin {
fn build(&self, app: &mut App) {
app.add_plugin(crate::lines::DebugLinesPlugin::with_depth_test(
self.depth_test,
))
.insert_resource(DebugRenderPipelineResource(DebugRenderPipeline::new(
Default::default(),
!DebugRenderMode::RIGID_BODY_AXES & !DebugRenderMode::COLLIDER_AABBS,
)))
.add_system_to_stage(CoreStage::Update, debug_render_scene);
app.insert_resource(DebugRenderPipelineResource {
pipeline: DebugRenderPipeline::new(
Default::default(),
!DebugRenderMode::RIGID_BODY_AXES & !DebugRenderMode::COLLIDER_AABBS,
),
enabled: false,
})
.add_systems(Update, debug_render_scene);
}
}
struct BevyLinesRenderBackend<'a> {
lines: &'a mut DebugLines,
gizmos: Gizmos<'a>,
}
impl<'a> DebugRenderBackend for BevyLinesRenderBackend<'a> {
#[cfg(feature = "dim2")]
fn draw_line(&mut self, _: DebugRenderObject, a: Point<Real>, b: Point<Real>, color: [f32; 4]) {
self.lines.line_colored(
self.gizmos.line(
[a.x as f32, a.y as f32, 1.0e-8 as f32].into(),
[b.x as f32, b.y as f32, 1.0e-8 as f32].into(),
0.0,
Color::hsla(color[0], color[1], color[2], color[3]),
)
}
#[cfg(feature = "dim3")]
fn draw_line(&mut self, _: DebugRenderObject, a: Point<Real>, b: Point<Real>, color: [f32; 4]) {
self.lines.line_colored(
self.gizmos.line(
[a.x as f32, a.y as f32, a.z as f32].into(),
[b.x as f32, b.y as f32, b.z as f32].into(),
0.0,
Color::hsla(color[0], color[1], color[2], color[3]),
)
}
}
fn debug_render_scene(
mut pipeline: ResMut<DebugRenderPipelineResource>,
mut debug_render: ResMut<DebugRenderPipelineResource>,
harness: NonSend<Harness>,
mut lines: ResMut<DebugLines>,
gizmos: Gizmos,
) {
let mut backend = BevyLinesRenderBackend { lines: &mut *lines };
pipeline.0.render(
&mut backend,
&harness.physics.bodies,
&harness.physics.colliders,
&harness.physics.impulse_joints,
&harness.physics.multibody_joints,
&harness.physics.narrow_phase,
);
if debug_render.enabled {
let mut backend = BevyLinesRenderBackend { gizmos };
debug_render.pipeline.render(
&mut backend,
&harness.physics.bodies,
&harness.physics.colliders,
&harness.physics.impulse_joints,
&harness.physics.multibody_joints,
&harness.physics.narrow_phase,
);
}
}

View File

@@ -22,7 +22,6 @@ mod camera3d;
mod debug_render;
mod graphics;
pub mod harness;
mod lines;
pub mod objects;
pub mod physics;
#[cfg(all(feature = "dim3", feature = "other-backends"))]

View File

@@ -1,53 +0,0 @@
// This should work, but it's bugged right now so we have to use 2 shaders: https://github.com/bevyengine/bevy/issues/4011
#ifdef LINES_3D
#import bevy_pbr::mesh_view_bind_group
//#import bevy_pbr::mesh_struct
#else
//#import bevy_sprite::mesh2d_view_bind_group
#endif
struct Vertex {
[[location(0)]] pos: vec3<f32>;
[[location(1)]] color: u32;
};
struct VertexOutput {
[[builtin(position)]] clip_position: vec4<f32>;
[[location(0)]] color: vec4<f32>;
};
struct FragmentOutput {
[[builtin(frag_depth)]] depth: f32;
[[location(0)]] color: vec4<f32>;
};
[[stage(vertex)]]
fn vertex(vertex: Vertex) -> VertexOutput {
var out: VertexOutput;
out.clip_position = view.view_proj * vec4<f32>(vertex.pos, 1.0);
// https://github.com/bevyengine/bevy/blob/328c26d02c50de0bc77f0d24a376f43ba89517b1/examples/2d/mesh2d_manual.rs#L234
// ... except the above doesn't seem to work in 3d. Not sure what's going on there.
var r = f32(vertex.color & 255u) / 255.0;
var g = f32(vertex.color >> 8u & 255u) / 255.0;
var b = f32(vertex.color >> 16u & 255u) / 255.0;
var a = f32(vertex.color >> 24u & 255u) / 255.0;
out.color = vec4<f32>(r, g, b, a);
return out;
}
[[stage(fragment)]]
fn fragment(in: VertexOutput) -> FragmentOutput {
var out: FragmentOutput;
// This should be #ifdef DEPTH_TEST_ENABLED && LINES_3D, but the
// preprocessor doesn't support that yet.
// Luckily, DEPTH_TEST_ENABLED isn't set in 2d anyway.
#ifdef DEPTH_TEST_ENABLED
out.depth = in.clip_position.z;
#else
out.depth = 1.0;
#endif
out.color = in.color;
return out;
}

View File

@@ -1,32 +0,0 @@
#import bevy_sprite::mesh2d_view_bind_group
[[group(0), binding(0)]]
var<uniform> view: View;
struct Vertex {
//[[location(0)]] color: vec4<f32>;
[[location(0)]] place: vec3<f32>;
[[location(1)]] color: u32;
};
struct VertexOutput {
[[builtin(position)]] clip_position: vec4<f32>;
[[location(0)]] color: vec4<f32>;
};
[[stage(vertex)]]
fn vertex(vertex: Vertex) -> VertexOutput {
var out: VertexOutput;
out.clip_position = view.view_proj * vec4<f32>(vertex.place, 1.0);
var r = f32(vertex.color & 255u) / 255.0;
var g = f32(vertex.color >> 8u & 255u) / 255.0;
var b = f32(vertex.color >> 16u & 255u) / 255.0;
var a = f32(vertex.color >> 24u & 255u) / 255.0;
out.color = vec4<f32>(r, g, b, a);
return out;
}
[[stage(fragment)]]
fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
return in.color;
}

View File

@@ -1,381 +0,0 @@
#![allow(warnings)]
use bevy::render::mesh::MeshVertexAttribute;
use bevy::render::render_resource::VertexFormat;
use bevy::render::view::NoFrustumCulling;
use bevy::render::MainWorld;
/**
*
* NOTE: this module and its submodules are only temporary. It is a copy-paste of the bevy-debug-lines
* crate: https://github.com/Toqozz/bevy_debug_lines (MIT license)
* It has been partially updated to work with bevy 0.7, but hasnt been released yet.
* So, in the mean time, we are keeping a version here that we will replace by the
* upstream dependency once:
* 1. The version compatible with bevy 0.7 is released to crates.io.
* 2. We find a way to make the 2D version work with our examples. The problem
* only happens when running our own examples because cargos unification of
* features will enable the `3d` feature of `bevy_debug_lines` when running
* a `2d` example.
*
*/
use bevy::{
asset::{Assets, HandleUntyped},
pbr::{NotShadowCaster, NotShadowReceiver},
prelude::*,
reflect::TypeUuid,
render::{
mesh::{/*Indices,*/ Mesh, VertexAttributeValues},
render_phase::AddRenderCommand,
render_resource::PrimitiveTopology,
render_resource::Shader,
},
};
mod render_dim;
// This module exists to "isolate" the `#[cfg]` attributes to this part of the
// code. Otherwise, we would pollute the code with a lot of feature
// gates-specific code.
#[cfg(feature = "dim3")]
mod dim {
pub(crate) use super::render_dim::r3d::{queue, DebugLinePipeline, DrawDebugLines};
pub(crate) use bevy::core_pipeline::core_3d::Opaque3d as Phase;
use bevy::{asset::Handle, render::mesh::Mesh};
pub(crate) type MeshHandle = Handle<Mesh>;
pub(crate) fn from_handle(from: &MeshHandle) -> &Handle<Mesh> {
from
}
pub(crate) fn into_handle(from: Handle<Mesh>) -> MeshHandle {
from
}
pub(crate) const SHADER_FILE: &str = include_str!("debuglines.wgsl");
pub(crate) const DIMMENSION: &str = "3d";
}
#[cfg(feature = "dim2")]
mod dim {
pub(crate) use super::render_dim::r2d::{queue, DebugLinePipeline, DrawDebugLines};
pub(crate) use bevy::core_pipeline::core_2d::Transparent2d as Phase;
use bevy::{asset::Handle, render::mesh::Mesh, sprite::Mesh2dHandle};
pub(crate) type MeshHandle = Mesh2dHandle;
pub(crate) fn from_handle(from: &MeshHandle) -> &Handle<Mesh> {
&from.0
}
pub(crate) fn into_handle(from: Handle<Mesh>) -> MeshHandle {
Mesh2dHandle(from)
}
pub(crate) const SHADER_FILE: &str = include_str!("debuglines2d.wgsl");
pub(crate) const DIMMENSION: &str = "2d";
}
// See debuglines.wgsl for explanation on 2 shaders.
//pub(crate) const SHADER_FILE: &str = include_str!("debuglines.wgsl");
pub(crate) const DEBUG_LINES_SHADER_HANDLE: HandleUntyped =
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 17477439189930443325);
#[derive(Resource)]
pub(crate) struct DebugLinesConfig {
depth_test: bool,
}
/// Bevy plugin, for initializing stuff.
///
/// # Usage
///
/// ```.ignore
/// use bevy::prelude::*;
/// use bevy_prototype_debug_lines::*;
///
/// App::new()
/// .add_plugins(DefaultPlugins)
/// .add_plugin(DebugLinesPlugin::default())
/// .run();
/// ```
///
/// Alternatively, you can initialize the plugin with depth testing, so that
/// debug lines cut through geometry. To do this, use [`DebugLinesPlugin::with_depth_test(true)`].
/// ```.ignore
/// use bevy::prelude::*;
/// use bevy_prototype_debug_lines::*;
///
/// App::new()
/// .add_plugins(DefaultPlugins)
/// .add_plugin(DebugLinesPlugin::with_depth_test(true))
/// .run();
/// ```
#[derive(Debug, Default, Clone)]
pub struct DebugLinesPlugin {
depth_test: bool,
}
impl DebugLinesPlugin {
/// Controls whether debug lines should be drawn with depth testing enabled
/// or disabled.
///
/// # Arguments
///
/// * `val` - True if lines should intersect with other geometry, or false
/// if lines should always draw on top be drawn on top (the default).
pub fn with_depth_test(val: bool) -> Self {
Self { depth_test: val }
}
}
impl Plugin for DebugLinesPlugin {
fn build(&self, app: &mut App) {
use bevy::render::{render_resource::SpecializedMeshPipelines, RenderApp, RenderStage};
let mut shaders = app.world.get_resource_mut::<Assets<Shader>>().unwrap();
shaders.set_untracked(
DEBUG_LINES_SHADER_HANDLE,
Shader::from_wgsl(dim::SHADER_FILE),
);
app.init_resource::<DebugLines>();
app.add_startup_system(setup)
.add_system_to_stage(CoreStage::PostUpdate, update.label("draw_lines"));
app.sub_app_mut(RenderApp)
.add_render_command::<dim::Phase, dim::DrawDebugLines>()
.insert_resource(DebugLinesConfig {
depth_test: self.depth_test,
})
.init_resource::<dim::DebugLinePipeline>()
.init_resource::<SpecializedMeshPipelines<dim::DebugLinePipeline>>()
.add_system_to_stage(RenderStage::Extract, extract)
.add_system_to_stage(RenderStage::Queue, dim::queue);
info!("Loaded {} debug lines plugin.", dim::DIMMENSION);
}
}
// Number of meshes to separate line buffers into.
// We don't really do culling currently but this is a gateway to that.
const MESH_COUNT: usize = 4;
// Maximum number of points for each individual mesh.
const MAX_POINTS_PER_MESH: usize = 2_usize.pow(16);
const _MAX_LINES_PER_MESH: usize = MAX_POINTS_PER_MESH / 2;
/// Maximum number of points.
pub const MAX_POINTS: usize = MAX_POINTS_PER_MESH * MESH_COUNT;
/// Maximum number of unique lines to draw at once.
pub const MAX_LINES: usize = MAX_POINTS / 2;
const ATTRIBUTE_COLOR: MeshVertexAttribute =
MeshVertexAttribute::new("Vertex_Color", 1, VertexFormat::Uint32);
fn setup(mut cmds: Commands, mut meshes: ResMut<Assets<Mesh>>) {
// Spawn a bunch of meshes to use for lines.
for i in 0..MESH_COUNT {
// Create a new mesh with the number of vertices we need.
let mut mesh = Mesh::new(PrimitiveTopology::LineList);
mesh.insert_attribute(
Mesh::ATTRIBUTE_POSITION,
VertexAttributeValues::Float32x3(Vec::with_capacity(MAX_POINTS_PER_MESH)),
);
mesh.insert_attribute(
ATTRIBUTE_COLOR,
VertexAttributeValues::Uint32(Vec::with_capacity(MAX_POINTS_PER_MESH)),
);
// https://github.com/Toqozz/bevy_debug_lines/issues/16
//mesh.set_indices(Some(Indices::U16(Vec::with_capacity(MAX_POINTS_PER_MESH))));
cmds.spawn_bundle((
dim::into_handle(meshes.add(mesh)),
NotShadowCaster,
NotShadowReceiver,
NoFrustumCulling,
Transform::default(),
GlobalTransform::default(),
Visibility::default(),
ComputedVisibility::default(),
DebugLinesMesh(i),
));
}
}
fn update(
debug_line_meshes: Query<(&dim::MeshHandle, &DebugLinesMesh)>,
time: Res<Time>,
mut meshes: ResMut<Assets<Mesh>>,
mut lines: ResMut<DebugLines>,
) {
// For each debug line mesh, fill its buffers with the relevant positions/colors chunks.
for (mesh_handle, debug_lines_idx) in debug_line_meshes.iter() {
let mesh = meshes.get_mut(dim::from_handle(mesh_handle)).unwrap();
use VertexAttributeValues::{Float32x3, Uint32};
if let Some(Float32x3(vbuffer)) = mesh.attribute_mut(Mesh::ATTRIBUTE_POSITION) {
vbuffer.clear();
if let Some(new_content) = lines
.positions
.chunks(MAX_POINTS_PER_MESH)
.nth(debug_lines_idx.0)
{
vbuffer.extend(new_content);
}
}
if let Some(Uint32(cbuffer)) = mesh.attribute_mut(ATTRIBUTE_COLOR) {
cbuffer.clear();
if let Some(new_content) = lines
.colors
.chunks(MAX_POINTS_PER_MESH)
.nth(debug_lines_idx.0)
{
cbuffer.extend(new_content);
}
}
/*
// https://github.com/Toqozz/bevy_debug_lines/issues/16
if let Some(Indices::U16(indices)) = mesh.indices_mut() {
indices.clear();
if let Some(new_content) = lines.durations.chunks(_MAX_LINES_PER_MESH).nth(debug_lines_idx.0) {
indices.extend(
new_content.iter().enumerate().map(|(i, _)| i as u16).flat_map(|i| [i * 2, i*2 + 1])
);
}
}
*/
}
// Processes stuff like getting rid of expired lines and stuff.
lines.update(time.delta_seconds());
}
/// Move the DebugLinesMesh marker Component to the render context.
fn extract(mut commands: Commands, query: Query<Entity, With<DebugLinesMesh>>, _: Res<MainWorld>) {
for entity in query.iter() {
commands.get_or_spawn(entity).insert(RenderDebugLinesMesh);
}
}
#[derive(Component)]
pub(crate) struct DebugLinesMesh(usize);
#[derive(Component)]
pub(crate) struct RenderDebugLinesMesh;
/// Bevy resource providing facilities to draw lines.
///
/// # Usage
/// ```.ignore
/// use bevy::prelude::*;
/// use bevy_prototype_debug_lines::*;
///
/// // Draws 3 horizontal lines, which disappear after 1 frame.
/// fn some_system(mut lines: ResMut<DebugLines>) {
/// lines.line(Vec3::new(-1.0, 1.0, 0.0), Vec3::new(1.0, 1.0, 0.0), 0.0);
/// lines.line_colored(
/// Vec3::new(-1.0, 0.0, 0.0),
/// Vec3::new(1.0, 0.0, 0.0),
/// 0.0,
/// Color::WHITE
/// );
/// lines.line_gradient(
/// Vec3::new(-1.0, -1.0, 0.0),
/// Vec3::new(1.0, -1.0, 0.0),
/// 0.0,
/// Color::WHITE, Color::PINK
/// );
/// }
/// ```
#[derive(Default, Resource)]
pub struct DebugLines {
pub positions: Vec<[f32; 3]>,
//pub colors: Vec<[f32; 4]>,
pub colors: Vec<u32>,
pub durations: Vec<f32>,
}
impl DebugLines {
/// Draw a line in world space, or update an existing line
///
/// # Arguments
///
/// * `start` - The start of the line in world space
/// * `end` - The end of the line in world space
/// * `duration` - Duration (in seconds) that the line should show for -- a value of
/// zero will show the line for 1 frame.
pub fn line(&mut self, start: Vec3, end: Vec3, duration: f32) {
self.line_colored(start, end, duration, Color::WHITE);
}
/// Draw a line in world space with a specified color, or update an existing line
///
/// # Arguments
///
/// * `start` - The start of the line in world space
/// * `end` - The end of the line in world space
/// * `duration` - Duration (in seconds) that the line should show for -- a value of
/// zero will show the line for 1 frame.
/// * `color` - Line color
pub fn line_colored(&mut self, start: Vec3, end: Vec3, duration: f32, color: Color) {
self.line_gradient(start, end, duration, color, color);
}
/// Draw a line in world space with a specified gradient color, or update an existing line
///
/// # Arguments
///
/// * `start` - The start of the line in world space
/// * `end` - The end of the line in world space
/// * `duration` - Duration (in seconds) that the line should show for -- a value of
/// zero will show the line for 1 frame.
/// * `start_color` - Line color
/// * `end_color` - Line color
pub fn line_gradient(
&mut self,
start: Vec3,
end: Vec3,
duration: f32,
start_color: Color,
end_color: Color,
) {
if self.positions.len() >= MAX_POINTS {
return;
}
self.positions.push(start.into());
self.positions.push(end.into());
//self.colors.push(start_color.into());
//self.colors.push(end_color.into());
self.colors.push(start_color.as_rgba_u32());
self.colors.push(end_color.as_rgba_u32());
self.durations.push(duration);
}
// Returns the indices of the start and end positions of the nth line.
// The indices can also be used to access color data.
fn nth(&self, idx: usize) -> (usize, usize) {
let i = idx * 2;
(i, i + 1)
}
// Prepare [`ImmediateLinesStorage`] and [`RetainedLinesStorage`] for next
// frame.
// This clears the immediate mod buffers and tells the retained mode
// buffers to recompute expired lines list.
fn update(&mut self, dt: f32) {
// TODO: an actual line counter wouldn't hurt.
let mut i = 0;
let mut len = self.durations.len();
while i != len {
self.durations[i] -= dt;
// <= instead of < is fine here because this is always called AFTER sending the
// data to the mesh, so we're guaranteed at least a frame here.
if self.durations[i] <= 0.0 {
let (cur_s, cur_e) = self.nth(i);
let (last_s, last_e) = self.nth(len - 1);
self.positions.swap(cur_s, last_s);
self.positions.swap(cur_e, last_e);
self.colors.swap(cur_s, last_s);
self.colors.swap(cur_e, last_e);
self.durations.swap(i, len - 1);
len -= 1;
} else {
i += 1;
}
}
self.positions.truncate(len * 2);
self.colors.truncate(len * 2);
self.durations.truncate(len);
}
}

View File

@@ -1,337 +0,0 @@
pub mod r3d {
use bevy::{
core_pipeline::core_3d::Opaque3d,
pbr::{
DrawMesh, MeshPipeline, MeshPipelineKey, MeshUniform, SetMeshBindGroup,
SetMeshViewBindGroup,
},
prelude::*,
render::{
mesh::MeshVertexBufferLayout,
render_asset::RenderAssets,
render_phase::{DrawFunctions, RenderPhase, SetItemPipeline},
render_resource::{
BlendState, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState,
DepthStencilState, FragmentState, FrontFace, MultisampleState, PipelineCache,
PolygonMode, PrimitiveState, PrimitiveTopology, RenderPipelineDescriptor,
SpecializedMeshPipeline, SpecializedMeshPipelineError, SpecializedMeshPipelines,
StencilFaceState, StencilState, TextureFormat, VertexAttribute, VertexBufferLayout,
VertexFormat, VertexState, VertexStepMode,
},
texture::BevyDefault,
view::{ExtractedView, Msaa},
},
utils::Hashed,
};
use crate::lines::{DebugLinesConfig, RenderDebugLinesMesh, DEBUG_LINES_SHADER_HANDLE};
#[derive(Resource)]
pub(crate) struct DebugLinePipeline {
mesh_pipeline: MeshPipeline,
shader: Handle<Shader>,
//always_in_front: bool,
}
impl FromWorld for DebugLinePipeline {
fn from_world(render_world: &mut World) -> Self {
//let config = render_world.get_resource::<DebugLinesConfig>().unwrap();
DebugLinePipeline {
mesh_pipeline: render_world.get_resource::<MeshPipeline>().unwrap().clone(),
shader: DEBUG_LINES_SHADER_HANDLE.typed(),
//always_in_front: config.always_in_front,
}
}
}
impl SpecializedMeshPipeline for DebugLinePipeline {
type Key = (bool, MeshPipelineKey);
fn specialize(
&self,
(depth_test, key): Self::Key,
layout: &MeshVertexBufferLayout,
) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> {
//use VertexFormat::{Float32x3, Float32x4};
let mut shader_defs = Vec::new();
shader_defs.push("LINES_3D".to_string());
if depth_test {
shader_defs.push("DEPTH_TEST_ENABLED".to_string());
}
let vertex_buffer_layout = layout.get_layout(&[
Mesh::ATTRIBUTE_POSITION.at_shader_location(0),
Mesh::ATTRIBUTE_COLOR.at_shader_location(1),
])?;
let (label, blend, depth_write_enabled);
if key.contains(MeshPipelineKey::TRANSPARENT_MAIN_PASS) {
label = "transparent_mesh_pipeline".into();
blend = Some(BlendState::ALPHA_BLENDING);
// For the transparent pass, fragments that are closer will be alpha
// blended but their depth is not written to the depth buffer.
depth_write_enabled = false;
} else {
label = "opaque_mesh_pipeline".into();
blend = Some(BlendState::REPLACE);
// For the opaque and alpha mask passes, fragments that are closer
// will replace the current fragment value in the output and the depth is
// written to the depth buffer.
depth_write_enabled = true;
}
Ok(RenderPipelineDescriptor {
vertex: VertexState {
shader: self.shader.clone_weak(),
entry_point: "vertex".into(),
shader_defs: shader_defs.clone(),
buffers: vec![vertex_buffer_layout],
},
fragment: Some(FragmentState {
shader: self.shader.clone_weak(),
shader_defs,
entry_point: "fragment".into(),
targets: vec![Some(ColorTargetState {
format: TextureFormat::bevy_default(),
blend,
write_mask: ColorWrites::ALL,
})],
}),
layout: Some(vec![self.mesh_pipeline.view_layout.clone()]),
primitive: PrimitiveState {
front_face: FrontFace::Ccw,
cull_mode: None,
unclipped_depth: false,
polygon_mode: PolygonMode::Fill,
conservative: false,
topology: PrimitiveTopology::LineList,
strip_index_format: None,
},
depth_stencil: Some(DepthStencilState {
format: TextureFormat::Depth32Float,
depth_write_enabled,
depth_compare: CompareFunction::Greater,
stencil: StencilState {
front: StencilFaceState::IGNORE,
back: StencilFaceState::IGNORE,
read_mask: 0,
write_mask: 0,
},
bias: DepthBiasState {
constant: 0,
slope_scale: 0.0,
clamp: 0.0,
},
}),
multisample: MultisampleState {
count: key.msaa_samples(),
mask: !0,
alpha_to_coverage_enabled: false,
},
label: Some(label),
})
}
}
pub(crate) fn queue(
opaque_3d_draw_functions: Res<DrawFunctions<Opaque3d>>,
debug_line_pipeline: Res<DebugLinePipeline>,
mut pipelines: ResMut<SpecializedMeshPipelines<DebugLinePipeline>>,
mut pipeline_cache: ResMut<PipelineCache>,
render_meshes: Res<RenderAssets<Mesh>>,
msaa: Res<Msaa>,
material_meshes: Query<(Entity, &MeshUniform, &Handle<Mesh>), With<RenderDebugLinesMesh>>,
config: Res<DebugLinesConfig>,
mut views: Query<(&ExtractedView, &mut RenderPhase<Opaque3d>)>,
) {
let draw_custom = opaque_3d_draw_functions
.read()
.get_id::<DrawDebugLines>()
.unwrap();
let key = MeshPipelineKey::from_msaa_samples(msaa.samples);
for (view, mut transparent_phase) in views.iter_mut() {
let view_matrix = view.transform.compute_matrix();
let view_row_2 = view_matrix.row(2);
for (entity, mesh_uniform, mesh_handle) in material_meshes.iter() {
if let Some(mesh) = render_meshes.get(mesh_handle) {
let pipeline = pipelines
.specialize(
&mut pipeline_cache,
&debug_line_pipeline,
(config.depth_test, key),
&mesh.layout,
)
.unwrap();
transparent_phase.add(Opaque3d {
entity,
pipeline,
draw_function: draw_custom,
distance: view_row_2.dot(mesh_uniform.transform.col(3)),
});
}
}
}
}
pub(crate) type DrawDebugLines = (
SetItemPipeline,
SetMeshViewBindGroup<0>,
SetMeshBindGroup<1>,
DrawMesh,
);
}
pub mod r2d {
use bevy::{
asset::Handle,
core_pipeline::core_2d::Transparent2d,
prelude::*,
render::{
mesh::MeshVertexBufferLayout,
render_asset::RenderAssets,
render_phase::{DrawFunctions, RenderPhase, SetItemPipeline},
render_resource::{
BlendState, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState,
DepthStencilState, FragmentState, FrontFace, MultisampleState, PipelineCache,
PolygonMode, PrimitiveState, PrimitiveTopology, RenderPipelineDescriptor, Shader,
SpecializedMeshPipeline, SpecializedMeshPipelineError, SpecializedMeshPipelines,
StencilFaceState, StencilState, TextureFormat, VertexAttribute, VertexBufferLayout,
VertexFormat, VertexState, VertexStepMode,
},
texture::BevyDefault,
view::{Msaa, VisibleEntities},
},
sprite::{
DrawMesh2d, Mesh2dHandle, Mesh2dPipeline, Mesh2dPipelineKey, Mesh2dUniform,
SetMesh2dBindGroup, SetMesh2dViewBindGroup,
},
utils::FloatOrd,
};
use crate::lines::{RenderDebugLinesMesh, DEBUG_LINES_SHADER_HANDLE};
#[derive(Resource)]
pub(crate) struct DebugLinePipeline {
mesh_pipeline: Mesh2dPipeline,
shader: Handle<Shader>,
}
impl FromWorld for DebugLinePipeline {
fn from_world(render_world: &mut World) -> Self {
DebugLinePipeline {
mesh_pipeline: render_world
.get_resource::<Mesh2dPipeline>()
.unwrap()
.clone(),
shader: DEBUG_LINES_SHADER_HANDLE.typed(),
}
}
}
impl SpecializedMeshPipeline for DebugLinePipeline {
type Key = Mesh2dPipelineKey;
fn specialize(
&self,
key: Self::Key,
layout: &MeshVertexBufferLayout,
) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> {
/*
let mut shader_defs = Vec::new();
shader_defs.push("LINES_3D".to_string());
if depth_test {
shader_defs.push("DEPTH_TEST_ENABLED".to_string());
}
*/
let vertex_buffer_layout = layout.get_layout(&[
Mesh::ATTRIBUTE_POSITION.at_shader_location(0),
Mesh::ATTRIBUTE_COLOR.at_shader_location(1),
])?;
Ok(RenderPipelineDescriptor {
vertex: VertexState {
shader: self.shader.clone_weak(),
entry_point: "vertex".into(),
shader_defs: vec![],
buffers: vec![vertex_buffer_layout],
},
fragment: Some(FragmentState {
shader: self.shader.clone_weak(),
shader_defs: vec![],
entry_point: "fragment".into(),
targets: vec![Some(ColorTargetState {
format: TextureFormat::bevy_default(),
blend: Some(BlendState::ALPHA_BLENDING),
write_mask: ColorWrites::ALL,
})],
}),
layout: Some(vec![self.mesh_pipeline.view_layout.clone()]),
primitive: PrimitiveState {
front_face: FrontFace::Ccw,
cull_mode: None,
unclipped_depth: false,
polygon_mode: PolygonMode::Fill,
conservative: false,
topology: PrimitiveTopology::LineList,
strip_index_format: None,
},
depth_stencil: None,
multisample: MultisampleState {
count: key.msaa_samples(),
mask: !0,
alpha_to_coverage_enabled: false,
},
label: None,
})
}
}
pub(crate) fn queue(
draw2d_functions: Res<DrawFunctions<Transparent2d>>,
debug_line_pipeline: Res<DebugLinePipeline>,
mut pipeline_cache: ResMut<PipelineCache>,
mut specialized_pipelines: ResMut<SpecializedMeshPipelines<DebugLinePipeline>>,
render_meshes: Res<RenderAssets<Mesh>>,
msaa: Res<Msaa>,
material_meshes: Query<(&Mesh2dUniform, &Mesh2dHandle), With<RenderDebugLinesMesh>>,
mut views: Query<(&VisibleEntities, &mut RenderPhase<Transparent2d>)>,
) {
for (view, mut phase) in views.iter_mut() {
let draw_mesh2d = draw2d_functions.read().get_id::<DrawDebugLines>().unwrap();
let msaa_key = Mesh2dPipelineKey::from_msaa_samples(msaa.samples);
for visible_entity in &view.entities {
if let Ok((uniform, mesh_handle)) = material_meshes.get(*visible_entity) {
if let Some(mesh) = render_meshes.get(&mesh_handle.0) {
let mesh_key = msaa_key
| Mesh2dPipelineKey::from_primitive_topology(
PrimitiveTopology::LineList,
);
let mesh_z = uniform.transform.w_axis.z;
let pipeline = specialized_pipelines
.specialize(
&mut pipeline_cache,
&debug_line_pipeline,
mesh_key,
&mesh.layout,
)
.unwrap();
phase.add(Transparent2d {
entity: *visible_entity,
draw_function: draw_mesh2d,
pipeline,
sort_key: FloatOrd(mesh_z),
batch_range: None,
});
}
}
}
}
}
pub(crate) type DrawDebugLines = (
SetItemPipeline,
SetMesh2dViewBindGroup<0>,
SetMesh2dBindGroup<1>,
DrawMesh2d,
);
}

View File

@@ -5,8 +5,8 @@ use bevy::render::mesh::{Indices, VertexAttributeValues};
use na::{point, Point3, Vector3};
use std::collections::HashMap;
use bevy::pbr::wireframe::Wireframe;
use bevy::render::render_resource::PrimitiveTopology;
use bevy_pbr::wireframe::Wireframe;
use rapier::geometry::{ColliderHandle, ColliderSet, Shape, ShapeType};
#[cfg(feature = "dim3")]
use rapier::geometry::{Cone, Cylinder};
@@ -15,7 +15,7 @@ use rapier::math::{Isometry, Real, Vector};
use crate::graphics::BevyMaterial;
#[cfg(feature = "dim2")]
use {
bevy::sprite::MaterialMesh2dBundle,
bevy_sprite::MaterialMesh2dBundle,
na::{Point2, Vector2},
rapier::geometry::{Ball, Cuboid},
};
@@ -235,10 +235,11 @@ impl EntityWithGraphics {
//
// Ball mesh
//
let ball = Mesh::from(shape::Icosphere {
let ball = Mesh::try_from(shape::Icosphere {
subdivisions: 2,
radius: 1.0,
});
})
.unwrap();
out.insert(ShapeType::Ball, meshes.add(ball));
//

View File

@@ -4,7 +4,7 @@ use crate::physics::PhysicsState;
use crate::GraphicsManager;
use bevy::prelude::*;
// use bevy::render::render_resource::RenderPipelineDescriptor;
use bevy_egui::EguiContext;
use bevy_egui::EguiContexts;
pub trait TestbedPlugin {
fn init_plugin(&mut self);
@@ -31,7 +31,7 @@ pub trait TestbedPlugin {
);
fn update_ui(
&mut self,
ui_context: &EguiContext,
ui_context: &EguiContexts,
harness: &mut Harness,
graphics: &mut GraphicsManager,
commands: &mut Commands,

View File

@@ -3,9 +3,10 @@ use std::mem;
use bevy::prelude::*;
use crate::debug_render::{DebugRenderPipelineResource, RapierDebugRenderPlugin};
use crate::physics::{PhysicsEvents, PhysicsSnapshot, PhysicsState};
use crate::plugin::TestbedPlugin;
use crate::{debug_render, ui};
use crate::ui;
use crate::{graphics::GraphicsManager, harness::RunState};
use na::{self, Point2, Point3, Vector3};
@@ -27,9 +28,11 @@ use crate::box2d_backend::Box2dWorld;
use crate::harness::Harness;
#[cfg(all(feature = "dim3", feature = "other-backends"))]
use crate::physx_backend::PhysxWorld;
use bevy::pbr::wireframe::WireframePlugin;
use bevy::render::camera::Camera;
use bevy_egui::EguiContext;
use bevy_core_pipeline::prelude::ClearColor;
use bevy_egui::EguiContexts;
use bevy_pbr::wireframe::WireframePlugin;
use bevy_pbr::AmbientLight;
#[cfg(feature = "dim2")]
use crate::camera2d::{OrbitCamera, OrbitCameraPlugin};
@@ -372,25 +375,25 @@ impl TestbedApp {
};
let window_plugin = WindowPlugin {
window: WindowDescriptor {
primary_window: Some(Window {
title,
..Default::default()
},
}),
..Default::default()
};
let mut app = App::new();
app.insert_resource(ClearColor(Color::rgb(0.15, 0.15, 0.15)))
.insert_resource(Msaa { samples: 4 })
.insert_resource(Msaa::Sample4)
.insert_resource(AmbientLight {
brightness: 0.3,
..Default::default()
})
.add_plugins(DefaultPlugins.set(window_plugin))
.add_plugin(OrbitCameraPlugin)
.add_plugin(WireframePlugin)
.add_plugin(bevy_egui::EguiPlugin)
.add_plugin(debug_render::RapierDebugRenderPlugin::default());
.add_plugins(OrbitCameraPlugin)
.add_plugins(WireframePlugin)
.add_plugins(RapierDebugRenderPlugin::default())
.add_plugins(bevy_egui::EguiPlugin);
#[cfg(target_arch = "wasm32")]
app.add_plugin(bevy_webgl2::WebGL2Plugin);
@@ -398,15 +401,14 @@ impl TestbedApp {
#[cfg(feature = "other-backends")]
app.insert_non_send_resource(self.other_backends);
app.add_startup_system(setup_graphics_environment)
app.add_systems(Startup, setup_graphics_environment)
.insert_non_send_resource(self.graphics)
.insert_resource(self.state)
.insert_non_send_resource(self.harness)
.insert_resource(self.builders)
.insert_non_send_resource(self.plugins)
.add_stage_before(CoreStage::Update, "physics", SystemStage::single_threaded())
.add_system_to_stage("physics", update_testbed)
.add_system(egui_focus);
.add_systems(Update, update_testbed)
.add_systems(Update, egui_focus);
init(&mut app);
app.run();
}
@@ -709,10 +711,10 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> Testbed<'a, 'b, 'c, 'd, 'e, 'f> {
KeyCode::Space => {
desired_movement += Vector::y() * 2.0;
}
KeyCode::RControl => {
KeyCode::ControlRight => {
desired_movement -= Vector::y();
}
KeyCode::RShift => {
KeyCode::ShiftRight => {
speed /= 10.0;
}
_ => {}
@@ -750,10 +752,10 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> Testbed<'a, 'b, 'c, 'd, 'e, 'f> {
KeyCode::Space => {
desired_movement += Vector::y() * 2.0;
}
KeyCode::RControl => {
KeyCode::ControlRight => {
desired_movement -= Vector::y();
}
KeyCode::RShift => {
KeyCode::ShiftLeft => {
speed /= 10.0;
}
_ => {}
@@ -998,21 +1000,9 @@ fn draw_contacts(_nf: &NarrowPhase, _colliders: &ColliderSet) {
#[cfg(feature = "dim3")]
fn setup_graphics_environment(mut commands: Commands) {
const HALF_SIZE: f32 = 100.0;
commands.spawn(DirectionalLightBundle {
directional_light: DirectionalLight {
illuminance: 10000.0,
// Configure the projection to better fit the scene
shadow_projection: OrthographicProjection {
left: -HALF_SIZE,
right: HALF_SIZE,
bottom: -HALF_SIZE,
top: HALF_SIZE,
near: -10.0 * HALF_SIZE,
far: 100.0 * HALF_SIZE,
..Default::default()
},
shadows_enabled: true,
..Default::default()
},
@@ -1073,7 +1063,7 @@ fn setup_graphics_environment(mut commands: Commands) {
});
}
fn egui_focus(mut ui_context: ResMut<EguiContext>, mut cameras: Query<&mut OrbitCamera>) {
fn egui_focus(mut ui_context: EguiContexts, mut cameras: Query<&mut OrbitCamera>) {
let mut camera_enabled = true;
if ui_context.ctx_mut().wants_pointer_input() {
camera_enabled = false;
@@ -1083,19 +1073,22 @@ fn egui_focus(mut ui_context: ResMut<EguiContext>, mut cameras: Query<&mut Orbit
}
}
use bevy::window::PrimaryWindow;
fn update_testbed(
mut commands: Commands,
windows: Res<Windows>,
windows: Query<&Window, With<PrimaryWindow>>,
// mut pipelines: ResMut<Assets<RenderPipelineDescriptor>>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<BevyMaterial>>,
builders: NonSendMut<SceneBuilders>,
builders: ResMut<SceneBuilders>,
mut graphics: NonSendMut<GraphicsManager>,
mut state: ResMut<TestbedState>,
mut debug_render: ResMut<DebugRenderPipelineResource>,
mut harness: NonSendMut<Harness>,
#[cfg(feature = "other-backends")] mut other_backends: NonSendMut<OtherBackends>,
mut plugins: NonSendMut<Plugins>,
mut ui_context: ResMut<EguiContext>,
mut ui_context: EguiContexts,
mut gfx_components: Query<(&mut Transform,)>,
mut cameras: Query<(&Camera, &GlobalTransform, &mut OrbitCamera)>,
keys: Res<Input<KeyCode>>,
@@ -1136,7 +1129,7 @@ fn update_testbed(
// Update UI
{
let harness = &mut *harness;
ui::update_ui(&mut ui_context, &mut state, harness);
ui::update_ui(&mut ui_context, &mut state, harness, &mut debug_render);
for plugin in &mut plugins.0 {
plugin.update_ui(
@@ -1407,7 +1400,7 @@ fn update_testbed(
}
}
if let Some(window) = windows.get_primary() {
if let Ok(window) = windows.get_single() {
for (camera, camera_pos, _) in cameras.iter_mut() {
highlight_hovered_body(
&mut *materials,
@@ -1419,7 +1412,7 @@ fn update_testbed(
camera_pos,
);
}
}
};
graphics.draw(
&harness.physics.bodies,
@@ -1494,7 +1487,10 @@ fn highlight_hovered_body(
}
if let Some(cursor) = window.cursor_position() {
let ndc_cursor = (cursor / Vec2::new(window.width(), window.height()) * 2.0) - Vec2::ONE;
let ndc_cursor = Vec2::new(
cursor.x / window.width() * 2.0 - 1.0,
1.0 - cursor.y / window.height() * 2.0,
);
let ndc_to_world = camera_transform.compute_matrix() * camera.projection_matrix().inverse();
let ray_pt1 = ndc_to_world.project_point3(Vec3::new(ndc_cursor.x, ndc_cursor.y, -1.0));
let ray_pt2 = ndc_to_world.project_point3(Vec3::new(ndc_cursor.x, ndc_cursor.y, 1.0));

View File

@@ -1,6 +1,7 @@
use rapier::counters::Counters;
use rapier::math::Real;
use crate::debug_render::DebugRenderPipelineResource;
use crate::harness::Harness;
use crate::testbed::{
RunMode, TestbedActionFlags, TestbedState, TestbedStateFlags, PHYSX_BACKEND_PATCH_FRICTION,
@@ -9,9 +10,14 @@ use crate::testbed::{
use crate::PhysicsState;
use bevy_egui::egui::Slider;
use bevy_egui::{egui, EguiContext};
use bevy_egui::{egui, EguiContexts};
pub fn update_ui(ui_context: &mut EguiContext, state: &mut TestbedState, harness: &mut Harness) {
pub fn update_ui(
ui_context: &mut EguiContexts,
state: &mut TestbedState,
harness: &mut Harness,
debug_render: &mut DebugRenderPipelineResource,
) {
egui::Window::new("Parameters").show(ui_context.ctx_mut(), |ui| {
if state.backend_names.len() > 1 && !state.example_names.is_empty() {
let mut changed = false;
@@ -157,6 +163,7 @@ pub fn update_ui(ui_context: &mut EguiContext, state: &mut TestbedState, harness
ui.checkbox(&mut sleep, "sleep enabled");
// ui.checkbox(&mut contact_points, "draw contacts");
// ui.checkbox(&mut wireframe, "draw wireframes");
ui.checkbox(&mut debug_render.enabled, "debug render enabled");
state.flags.set(TestbedStateFlags::SLEEP, sleep);
// state