mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-11 22:50:08 +00:00
clean up path straightening + navmesh dev example improvement
This commit is contained in:
Binary file not shown.
+5
-41
@@ -1,12 +1,3 @@
|
||||
//! Example 01. Simple scene.
|
||||
//!
|
||||
//! Difficulty: Easy.
|
||||
//!
|
||||
//! This example shows how to create simple scene with animated model.
|
||||
|
||||
use fyrox::event_loop::EventLoop;
|
||||
use fyrox::scene::camera::CameraBuilder;
|
||||
use fyrox::scene::node::NodeTrait;
|
||||
use fyrox::{
|
||||
asset::manager::ResourceManager,
|
||||
core::{
|
||||
@@ -19,25 +10,21 @@ use fyrox::{
|
||||
dpi::LogicalPosition,
|
||||
engine::{executor::Executor, GraphicsContext, GraphicsContextParams},
|
||||
event::{ElementState, Event, WindowEvent},
|
||||
gui::{
|
||||
message::MessageDirection,
|
||||
text::{TextBuilder, TextMessage},
|
||||
widget::WidgetBuilder,
|
||||
BuildContext, UiNode,
|
||||
},
|
||||
event_loop::EventLoop,
|
||||
keyboard::KeyCode,
|
||||
material::{Material, PropertyValue, SharedMaterial},
|
||||
plugin::{Plugin, PluginConstructor, PluginContext},
|
||||
resource::model::{Model, ModelResourceExtension},
|
||||
scene::{
|
||||
base::BaseBuilder,
|
||||
camera::CameraBuilder,
|
||||
debug::Line,
|
||||
graph::physics::{Intersection, RayCastOptions},
|
||||
mesh::{
|
||||
surface::{SurfaceBuilder, SurfaceData, SurfaceSharedData},
|
||||
MeshBuilder,
|
||||
},
|
||||
node::Node,
|
||||
node::{Node, NodeTrait},
|
||||
transform::TransformBuilder,
|
||||
Scene,
|
||||
},
|
||||
@@ -45,10 +32,6 @@ use fyrox::{
|
||||
};
|
||||
use winit::keyboard::PhysicalKey;
|
||||
|
||||
fn create_ui(ctx: &mut BuildContext) -> Handle<UiNode> {
|
||||
TextBuilder::new(WidgetBuilder::new()).build(ctx)
|
||||
}
|
||||
|
||||
struct GameScene {
|
||||
scene: Scene,
|
||||
agent: Handle<Node>,
|
||||
@@ -77,7 +60,7 @@ async fn create_scene(resource_manager: ResourceManager) -> GameScene {
|
||||
));
|
||||
|
||||
resource_manager
|
||||
.request::<Model, _>("examples/data/navmesh_scene2.rgs")
|
||||
.request::<Model, _>("examples/data/navmesh_scene.rgs")
|
||||
.await
|
||||
.unwrap()
|
||||
.instantiate(&mut scene);
|
||||
@@ -143,7 +126,6 @@ struct Game {
|
||||
target_position: Vector3<f32>,
|
||||
mouse_position: Vector2<f32>,
|
||||
navmesh_agent: NavmeshAgent,
|
||||
debug_text: Handle<UiNode>,
|
||||
}
|
||||
|
||||
impl Plugin for Game {
|
||||
@@ -180,15 +162,13 @@ impl Plugin for Game {
|
||||
}
|
||||
}
|
||||
|
||||
let navmesh_handle = scene.graph.find_by_name_from_root("Navmesh0").unwrap().0;
|
||||
let navmesh_handle = scene.graph.find_by_name_from_root("Navmesh").unwrap().0;
|
||||
let navmesh_node = scene.graph[navmesh_handle].as_navigational_mesh_mut();
|
||||
navmesh_node.debug_draw(&mut scene.drawing_context);
|
||||
let navmesh = navmesh_node.navmesh_mut();
|
||||
|
||||
let last = std::time::Instant::now();
|
||||
self.navmesh_agent.set_target(self.target_position);
|
||||
let _ = self.navmesh_agent.update(context.dt, navmesh);
|
||||
let agent_time = std::time::Instant::now() - last;
|
||||
|
||||
scene.graph[self.agent]
|
||||
.local_transform_mut()
|
||||
@@ -201,19 +181,6 @@ impl Plugin for Game {
|
||||
color: Color::opaque(255, 0, 0),
|
||||
});
|
||||
}
|
||||
|
||||
if let GraphicsContext::Initialized(ref graphics_context) = context.graphics_context {
|
||||
let fps = graphics_context.renderer.get_statistics().frames_per_second;
|
||||
let text = format!(
|
||||
"Example 12 - Navigation Mesh\nFPS: {}\nAgent time: {:?}",
|
||||
fps, agent_time
|
||||
);
|
||||
context.user_interface.send_message(TextMessage::text(
|
||||
self.debug_text,
|
||||
MessageDirection::ToWidget,
|
||||
text,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
fn on_os_event(&mut self, event: &Event<()>, context: PluginContext) {
|
||||
@@ -251,8 +218,6 @@ impl PluginConstructor for GameConstructor {
|
||||
_override_scene: Option<&str>,
|
||||
context: PluginContext,
|
||||
) -> Box<dyn Plugin> {
|
||||
let debug_text = create_ui(&mut context.user_interface.build_ctx());
|
||||
|
||||
// Create test scene.
|
||||
let GameScene {
|
||||
scene,
|
||||
@@ -280,7 +245,6 @@ impl PluginConstructor for GameConstructor {
|
||||
target_position: Default::default(),
|
||||
mouse_position: Default::default(),
|
||||
navmesh_agent,
|
||||
debug_text,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+40
-52
@@ -121,7 +121,7 @@ struct Portal {
|
||||
left: usize,
|
||||
right: usize,
|
||||
}
|
||||
fn signed_triangle_area_2d(a: Vector3<f32>, b: Vector3<f32>, c: Vector3<f32>) -> f32 {
|
||||
fn triangle_area_2d(a: Vector3<f32>, b: Vector3<f32>, c: Vector3<f32>) -> f32 {
|
||||
let abx = b[0] - a[0];
|
||||
let abz = b[2] - a[2];
|
||||
let acx = c[0] - a[0];
|
||||
@@ -136,7 +136,7 @@ enum Winding {
|
||||
}
|
||||
|
||||
fn winding(a: Vector3<f32>, b: Vector3<f32>, c: Vector3<f32>) -> Winding {
|
||||
if signed_triangle_area_2d(a, b, c) > 0.0 {
|
||||
if triangle_area_2d(a, b, c) > 0.0 {
|
||||
Winding::Clockwise
|
||||
} else {
|
||||
Winding::CounterClockwise
|
||||
@@ -669,16 +669,14 @@ impl NavmeshAgent {
|
||||
self.path.push(src_position);
|
||||
|
||||
if path_triangles.len() > 1 {
|
||||
let mut portal_apex = src_position;
|
||||
let mut portal_left = src_position;
|
||||
let mut portal_right = src_position;
|
||||
|
||||
let mut left_index = 0;
|
||||
let mut right_index = 0;
|
||||
let mut funnel_apex = src_position;
|
||||
let mut funnel_vertices = [funnel_apex; 2];
|
||||
let mut side_indices = [0; 2];
|
||||
let side_signs = [1.0, -1.0];
|
||||
|
||||
let mut i = 0;
|
||||
while i < path_triangles.len() {
|
||||
let (left, right) = if i + 1 < path_triangles.len() {
|
||||
let portal_vertices = if i + 1 < path_triangles.len() {
|
||||
let portal = navmesh
|
||||
.portal_between(path_triangles[i], path_triangles[i + 1])
|
||||
.unwrap();
|
||||
@@ -695,54 +693,44 @@ impl NavmeshAgent {
|
||||
right -= offset;
|
||||
}
|
||||
|
||||
(left, right)
|
||||
[left, right]
|
||||
} else {
|
||||
(dest_position, dest_position)
|
||||
[dest_position, dest_position]
|
||||
};
|
||||
|
||||
// Update right vertex.
|
||||
if signed_triangle_area_2d(portal_apex, portal_right, right) <= 0.0 {
|
||||
if portal_apex == portal_right
|
||||
|| signed_triangle_area_2d(portal_apex, portal_left, right) > 0.0
|
||||
for current in 0..2 {
|
||||
let opposite = 1 - current;
|
||||
let side_sign = side_signs[current];
|
||||
if side_sign
|
||||
* triangle_area_2d(
|
||||
funnel_apex,
|
||||
funnel_vertices[current],
|
||||
portal_vertices[current],
|
||||
)
|
||||
>= 0.0
|
||||
{
|
||||
// Tighten the funnel.
|
||||
portal_right = right;
|
||||
right_index = i;
|
||||
} else {
|
||||
// Right over left, insert left to path and restart scan from portal left point.
|
||||
self.path.push(portal_left);
|
||||
// Make current left the new apex.
|
||||
portal_apex = portal_left;
|
||||
// Reset portal
|
||||
portal_left = portal_apex;
|
||||
portal_right = portal_apex;
|
||||
right_index = left_index;
|
||||
// Restart scan
|
||||
i = left_index + 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if funnel_apex == funnel_vertices[current]
|
||||
|| side_sign
|
||||
* triangle_area_2d(
|
||||
funnel_apex,
|
||||
funnel_vertices[opposite],
|
||||
portal_vertices[current],
|
||||
)
|
||||
< 0.0
|
||||
{
|
||||
funnel_vertices[current] = portal_vertices[current];
|
||||
side_indices[current] = i;
|
||||
} else {
|
||||
funnel_apex = funnel_vertices[opposite];
|
||||
funnel_vertices = [funnel_apex; 2];
|
||||
|
||||
// Update left vertex.
|
||||
if signed_triangle_area_2d(portal_apex, portal_left, left) >= 0.0 {
|
||||
if portal_apex == portal_left
|
||||
|| signed_triangle_area_2d(portal_apex, portal_right, left) < 0.0
|
||||
{
|
||||
// Tighten the funnel.
|
||||
portal_left = left;
|
||||
left_index = i;
|
||||
} else {
|
||||
// Left over right, insert right to path and restart scan from portal right point.
|
||||
self.path.push(portal_right);
|
||||
// Make current right the new apex.
|
||||
portal_apex = portal_right;
|
||||
// Reset portal
|
||||
portal_left = portal_apex;
|
||||
portal_right = portal_apex;
|
||||
left_index = right_index;
|
||||
// Restart scan
|
||||
i = right_index + 1;
|
||||
continue;
|
||||
self.path.push(funnel_apex);
|
||||
|
||||
i = side_indices[opposite];
|
||||
side_indices[current] = i;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user