Kaynağa Gözat

Merge branch 'master' of https://github.com/taylor001/crown

Dexter89 12 yıl önce
ebeveyn
işleme
0c480c840d

+ 21 - 43
engine/lua/LuaPhysicsWorld.cpp

@@ -65,7 +65,7 @@ CE_EXPORT int physics_world_make_raycast(lua_State* L)
 	int mode = stack.get_int(3);
 	int filter = stack.get_int(4);
 
-	RaycastId raycast = world->create_raycast(callback, (SceneQueryMode::Enum) mode, (SceneQueryFilter::Enum) filter);
+	RaycastId raycast = world->create_raycast(callback, (CollisionMode::Enum) mode, (CollisionType::Enum) filter);
 
 	stack.push_raycast(world->lookup_raycast(raycast));
 	return 1;
@@ -78,41 +78,24 @@ CE_EXPORT int physics_world_overlap_test(lua_State* L)
 
 	PhysicsWorld* world = stack.get_physics_world(1);
 	const char* callback = stack.get_string(2);
-	int mode = stack.get_int(3);
-	int filter = stack.get_int(4);
-	int shape_type = stack.get_int(5);
-	Vector3 pos = stack.get_vector3(6);
-	Quaternion rot = stack.get_quaternion(7);
-	Vector3 size = stack.get_vector3(8);
+	CollisionType::Enum filter = (CollisionType::Enum) stack.get_int(3);
+	ShapeType::Enum shape_type = (ShapeType::Enum) stack.get_int(4);
+	Vector3 pos = stack.get_vector3(5);
+	Quaternion rot = stack.get_quaternion(6);
+	Vector3 size = stack.get_vector3(7);
 
-	world->overlap_test(callback, (SceneQueryMode::Enum) mode, (SceneQueryFilter::Enum) filter,
-						(ShapeType::Enum) shape_type, pos, rot, size);
+	List<Actor*> actors(default_allocator());
 
-	return 0;
-}
+	world->overlap_test(callback, filter, shape_type, pos, rot, size, actors);
 
-//-----------------------------------------------------------------------------
-CE_EXPORT int physics_world_sync_overlap_test(lua_State* L)
-{
-	LuaStack stack(L);
+	stack.push_table();
+	for (uint32_t i = 0; i < actors.size(); i++)
+	{
+		stack.push_key_begin(i+1);
+		stack.push_actor(actors[i]);
+		stack.push_key_end();
+	}
 
-	PhysicsWorld* world = stack.get_physics_world(1);
-	const char* callback = stack.get_string(2);
-	int mode = stack.get_int(3);
-	int filter = stack.get_int(4);
-	int shape_type = stack.get_int(5);
-	Vector3 pos = stack.get_vector3(6);
-	Quaternion rot = stack.get_quaternion(7);
-	Vector3 size = stack.get_vector3(8);
-
-	Actor* actor = world->sync_overlap_test(callback, (SceneQueryMode::Enum) mode, (SceneQueryFilter::Enum) filter,
-										(ShapeType::Enum) shape_type, pos, rot, size);
-
-	if (actor)
-		stack.push_actor(actor);
-	else
-		stack.push_nil();
-	
 	return 1;
 }
 
@@ -123,7 +106,6 @@ void load_physics_world(LuaEnvironment& env)
 	env.load_module_function("PhysicsWorld", "set_gravity",			physics_world_set_gravity);
 	env.load_module_function("PhysicsWorld", "make_raycast",		physics_world_make_raycast);
 	env.load_module_function("PhysicsWorld", "overlap_test",		physics_world_overlap_test);
-	env.load_module_function("PhysicsWorld", "sync_overlap_test",	physics_world_sync_overlap_test);
 
 	// Actor types
 	env.load_module_enum("ActorType", "STATIC",						ActorType::STATIC);
@@ -137,19 +119,15 @@ void load_physics_world(LuaEnvironment& env)
 	env.load_module_enum("ShapeType", "PLANE",						ShapeType::PLANE);
 	env.load_module_enum("ShapeType", "CONVEX_MESH",				ShapeType::CONVEX_MESH);
 
-	// SceneQuery types
-	env.load_module_enum("SceneQueryType", "RAYCAST",				SceneQueryType::RAYCAST);
-	env.load_module_enum("SceneQueryType", "OVERLAP",				SceneQueryType::OVERLAP);
-
 	// SceneQuery modes
-	env.load_module_enum("SceneQueryMode", "CLOSEST",				SceneQueryMode::CLOSEST);
-	env.load_module_enum("SceneQueryMode", "ANY",					SceneQueryMode::ANY);
-	env.load_module_enum("SceneQueryMode", "ALL",					SceneQueryMode::ALL);
+	env.load_module_enum("CollisionMode", "CLOSEST",				CollisionMode::CLOSEST);
+	env.load_module_enum("CollisionMode", "ANY",					CollisionMode::ANY);
+	env.load_module_enum("CollisionMode", "ALL",					CollisionMode::ALL);
 
 	// SceneQuery filters
-	env.load_module_enum("SceneQueryFilter", "STATIC",				SceneQueryFilter::STATIC);
-	env.load_module_enum("SceneQueryFilter", "DYNAMIC",				SceneQueryFilter::DYNAMIC);
-	env.load_module_enum("SceneQueryFilter", "BOTH",				SceneQueryFilter::BOTH);
+	env.load_module_enum("CollisionType", "STATIC",					CollisionType::STATIC);
+	env.load_module_enum("CollisionType", "DYNAMIC",				CollisionType::DYNAMIC);
+	env.load_module_enum("CollisionType", "BOTH",					CollisionType::BOTH);
 }
 
 } // namespace crown

+ 42 - 17
engine/lua/LuaRaycast.cpp

@@ -27,6 +27,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "LuaStack.h"
 #include "LuaEnvironment.h"
 #include "Raycast.h"
+#include "Log.h"
 
 namespace crown
 {
@@ -41,25 +42,50 @@ CE_EXPORT int raycast_cast(lua_State* L)
 	Vector3 dir = stack.get_vector3(3);
 	float length = stack.get_float(4);
 	
-	raycast->cast(from, dir, length);
+	List<RaycastHit> hits(default_allocator());
 
-	return 0;
-}
-
-//-----------------------------------------------------------------------------
-CE_EXPORT int raycast_sync_cast(lua_State* L)
-{
-	LuaStack stack(L);
+	raycast->cast(from, dir, length, hits);
 
-	Raycast* raycast = stack.get_raycast(1);
-	Vector3 from = stack.get_vector3(2);
-	Vector3 dir = stack.get_vector3(3);
-	float length = stack.get_float(4);
-	
-	Actor* actor = raycast->sync_cast(from, dir, length);
+	switch(raycast->mode())
+	{
+		case CollisionMode::CLOSEST:
+		{
+			bool hit = hits.size() > 0 ? true : false;
+			stack.push_bool(hit);
+			break;
+		}
+		case CollisionMode::ANY:
+		{
+			bool hit = hits.size() > 0 ? true : false;
+			stack.push_bool(hit);
+			if (hit)
+			{
+				stack.push_vector3(hits[0].position);
+				stack.push_float(hits[0].distance);
+				stack.push_vector3(hits[0].normal);
+				stack.push_actor(hits[0].actor);
+				return 5;
+			}
+			break;
+		}
+		case CollisionMode::ALL:
+		{
+			stack.push_table();
+			for (uint32_t i = 0; i < hits.size(); i++)
+			{
+				stack.push_key_begin(i+1);
+				
+				stack.push_table();
+				stack.push_key_begin("position"); stack.push_vector3(hits[i].position);	stack.push_key_end();
+				stack.push_key_begin("distance"); stack.push_float(hits[i].distance); stack.push_key_end();
+				stack.push_key_begin("normal"); stack.push_vector3(hits[i].normal); stack.push_key_end();
+				stack.push_key_begin("actor"); stack.push_actor(hits[i].actor); stack.push_key_end();
 
-	if (actor) stack.push_actor(actor);
-	else stack.push_nil();
+				stack.push_key_end();
+			}
+			break;
+		}
+	}
 
 	return 1;
 }
@@ -68,7 +94,6 @@ CE_EXPORT int raycast_sync_cast(lua_State* L)
 void load_raycast(LuaEnvironment& env)
 {
 	env.load_module_function("Raycast", "cast",	raycast_cast);
-	env.load_module_function("Raycast", "sync_cast", raycast_sync_cast);
 }
 
 } // namespace crown

+ 7 - 31
engine/physics/PhysicsTypes.h

@@ -118,17 +118,18 @@ struct CollisionGroup
 };
 
 //-----------------------------------------------------------------------------
-struct SceneQueryType
+struct CollisionType
 {
 	enum Enum
 	{
-		RAYCAST,
-		OVERLAP
+		STATIC,
+		DYNAMIC,
+		BOTH
 	};
 };
 
 //-----------------------------------------------------------------------------
-struct SceneQueryMode
+struct CollisionMode
 {
 	enum Enum
 	{
@@ -138,17 +139,6 @@ struct SceneQueryMode
 	};
 };
 
-//-----------------------------------------------------------------------------
-struct SceneQueryFilter
-{
-	enum Enum
-	{
-		STATIC,
-		DYNAMIC,
-		BOTH
-	};
-};
-
 namespace physics_world
 {
 //-----------------------------------------------------------------------------	
@@ -157,8 +147,7 @@ struct EventType
 	enum Enum
 	{
 		COLLISION,
-		TRIGGER,
-		SCENE_QUERY
+		TRIGGER
 	};
 };
 
@@ -175,19 +164,6 @@ struct TriggerEvent
 	Actor* actor;
 };
 
-//-----------------------------------------------------------------------------
-struct SceneQueryEvent
-{
-	const char*				callback;
-	SceneQueryType::Enum	type;
-	SceneQueryMode::Enum	mode;
-	bool					hit;
-	Vector3					position;
-	float					distance;
-	Vector3					normal;
-	Actor*					actor;
-};
-
-}
+} // namespace physics_world
 
 } // namespace crown

+ 7 - 59
engine/physics/PhysicsWorld.cpp

@@ -308,7 +308,7 @@ void PhysicsWorld::destroy_joint(JointId id)
 }
 
 //-----------------------------------------------------------------------------
-RaycastId PhysicsWorld::create_raycast(const char* callback, SceneQueryMode::Enum mode, SceneQueryFilter::Enum filter)
+RaycastId PhysicsWorld::create_raycast(const char* callback, CollisionMode::Enum mode, CollisionType::Enum filter)
 {
 	Raycast* raycast = CE_NEW(m_raycasts_pool, Raycast)(m_scene, m_events, callback, mode, filter);
 	return m_raycasts.create(raycast);
@@ -386,10 +386,9 @@ void PhysicsWorld::clear_kinematic(ActorId id)
 }
 
 //-----------------------------------------------------------------------------
-void PhysicsWorld::overlap_test(const char* callback, SceneQueryMode::Enum mode, SceneQueryFilter::Enum filter,
-								ShapeType::Enum type, const Vector3& pos, const Quaternion& rot, const Vector3& size)
+void PhysicsWorld::overlap_test(const char* callback, CollisionType::Enum filter, ShapeType::Enum type,
+								const Vector3& pos, const Quaternion& rot, const Vector3& size, List<Actor*>& actors)
 {
-	bool hit = false;
 	PxTransform transform(PxVec3(pos.x, pos.y, pos.z), PxQuat(rot.v.x, rot.v.y, rot.v.z, rot.w));
 
 	switch(type)
@@ -397,19 +396,19 @@ void PhysicsWorld::overlap_test(const char* callback, SceneQueryMode::Enum mode,
 		case ShapeType::SPHERE:	
 		{
 			PxSphereGeometry geometry(size.x);
-			hit = m_scene->overlap(geometry, transform, m_buffer);
+			m_scene->overlap(geometry, transform, m_buffer);
 			break;
 		}
 		case ShapeType::CAPSULE:
 		{
 			PxCapsuleGeometry geometry(size.x, size.y);
-			hit = m_scene->overlap(geometry, transform, m_buffer);
+			m_scene->overlap(geometry, transform, m_buffer);
 			break;
 		}
 		case ShapeType::BOX:
 		{
 			PxBoxGeometry geometry(size.x, size.y, size.z);
-			hit = m_scene->overlap(geometry, transform, m_buffer);
+			m_scene->overlap(geometry, transform, m_buffer);
 			break;
 		}
 		default: CE_FATAL("Only spheres, capsules and boxs are supported in overlap test"); break;
@@ -419,58 +418,7 @@ void PhysicsWorld::overlap_test(const char* callback, SceneQueryMode::Enum mode,
 	{
 		PxOverlapHit oh = m_buffer.getAnyHit(i);
 
-		physics_world::SceneQueryEvent ev;
-
-		ev.type = SceneQueryType::OVERLAP;
-		ev.mode = mode;
-		ev.hit = hit;
-		ev.callback = callback;
-		ev.actor = (Actor*)(oh.actor->userData);
-
-		event_stream::write(m_events, physics_world::EventType::SCENE_QUERY, ev);
-
-		Log::i("callback: %s, type: %d, mode: %d, hit: %s", ev.callback, ev.type, ev.mode, ev.hit ? "true" : "false");
-	}
-}
-
-//-----------------------------------------------------------------------------
-Actor* PhysicsWorld::sync_overlap_test(const char* callback, SceneQueryMode::Enum mode, SceneQueryFilter::Enum filter,
-									ShapeType::Enum type, const Vector3& pos, const Quaternion& rot, const Vector3& size)
-{
-	bool hit = false;
-	PxTransform transform(PxVec3(pos.x, pos.y, pos.z), PxQuat(rot.v.x, rot.v.y, rot.v.z, rot.w));
-
-	switch(type)
-	{
-		case ShapeType::SPHERE:	
-		{
-			PxSphereGeometry geometry(size.x);
-			hit = m_scene->overlap(geometry, transform, m_buffer);
-			break;
-		}
-		case ShapeType::CAPSULE:
-		{
-			PxCapsuleGeometry geometry(size.x, size.y);
-			hit = m_scene->overlap(geometry, transform, m_buffer);
-			break;
-		}
-		case ShapeType::BOX:
-		{
-			PxBoxGeometry geometry(size.x, size.y, size.z);
-			hit = m_scene->overlap(geometry, transform, m_buffer);
-			break;
-		}
-		default: CE_FATAL("Only spheres, capsules and boxs are supported in overlap test"); break;
-	}
-
-	if (hit)
-	{
-		PxOverlapHit oh = m_buffer.getAnyHit(0);
-		return (Actor*)(oh.actor->userData);
-	} 
-	else
-	{
-		return NULL;
+		actors.push_back((Actor*)(oh.actor->userData));
 	}
 }
 

+ 3 - 6
engine/physics/PhysicsWorld.h

@@ -92,7 +92,7 @@ public:
 	JointId						create_joint(const PhysicsResource* pr, const uint32_t index, const Actor& actor_0, const Actor& actor_1);
 	void						destroy_joint(JointId id);
 
-	RaycastId					create_raycast(const char* callback, SceneQueryMode::Enum mode, SceneQueryFilter::Enum filter);
+	RaycastId					create_raycast(const char* callback, CollisionMode::Enum mode, CollisionType::Enum filter);
 	void						destroy_raycast(RaycastId id);
 
 	Actor*						lookup_actor(StringId32 name);
@@ -107,11 +107,8 @@ public:
 	void						clear_kinematic(ActorId id);
 
 	/// Finds all actors in the physics world that are in a particular shape (supported: spheres, capsules and boxes)
-	void						overlap_test(const char* callback, SceneQueryMode::Enum mode, SceneQueryFilter::Enum filter,
-											ShapeType::Enum type, const Vector3& pos, const Quaternion& rot, const Vector3& size);
-
-	Actor*						sync_overlap_test(const char* callback, SceneQueryMode::Enum mode, SceneQueryFilter::Enum filter,
-											ShapeType::Enum type, const Vector3& pos, const Quaternion& rot, const Vector3& size);
+	void						overlap_test(const char* callback, CollisionType::Enum filter, ShapeType::Enum type,
+											const Vector3& pos, const Quaternion& rot, const Vector3& size, List<Actor*>& actors);
 
 	void						update(float dt);
 

+ 30 - 48
engine/physics/Raycast.cpp

@@ -35,81 +35,63 @@ namespace crown
 {
 
 //-------------------------------------------------------------------------
-Raycast::Raycast(PxScene* scene, EventStream& events, const char* callback, SceneQueryMode::Enum mode, SceneQueryFilter::Enum filter)
+Raycast::Raycast(PxScene* scene, EventStream& events, const char* callback, CollisionMode::Enum mode, CollisionType::Enum type)
 	: m_scene(scene)
 	, m_buffer(m_hits, CE_MAX_RAY_INTERSECTIONS)
 	, m_events(events)
 	, m_callback(callback)
 	, m_mode(mode)
-	, m_filter(filter)
+	, m_type(type)
 {
-	switch (m_filter)
+	switch (m_type)
 	{
-		case SceneQueryFilter::BOTH: break;
-		case SceneQueryFilter::STATIC: m_fd.flags = PxQueryFlag::eSTATIC; break;
-		case SceneQueryFilter::DYNAMIC: m_fd.flags = PxQueryFlag::eDYNAMIC; break;
+		case CollisionType::BOTH: break;
+		case CollisionType::STATIC: m_fd.flags = PxQueryFlag::eSTATIC; break;
+		case CollisionType::DYNAMIC: m_fd.flags = PxQueryFlag::eDYNAMIC; break;
 	}
 
 	switch (m_mode)
 	{
-		case SceneQueryMode::CLOSEST: break;
-		case SceneQueryMode::ANY: m_fd.flags |= PxQueryFlag::eANY_HIT; break;
-		case SceneQueryMode::ALL: break;
+		case CollisionMode::CLOSEST: break;
+		case CollisionMode::ANY: m_fd.flags |= PxQueryFlag::eANY_HIT; break;
+		case CollisionMode::ALL: break;
 	}
 }
 
 //-------------------------------------------------------------------------
-void Raycast::cast(const Vector3& from, const Vector3& dir, const float length)
+void Raycast::cast(const Vector3& from, const Vector3& dir, const float length, List<RaycastHit>& hits)
 {
-	bool hit = m_scene->raycast(PxVec3(from.x, from.y, from.z), PxVec3(dir.x, dir.y, dir.z), length,
-								m_buffer, PxHitFlags(PxHitFlag::eDEFAULT), m_fd);
+	m_scene->raycast(PxVec3(from.x, from.y, from.z), PxVec3(dir.x, dir.y, dir.z), length, m_buffer, PxHitFlags(PxHitFlag::eDEFAULT), m_fd);
 
 	for (uint32_t i = 0; i < m_buffer.getNbAnyHits(); i++)
 	{
 		PxRaycastHit rh = m_buffer.getAnyHit(i);
 
-		physics_world::SceneQueryEvent ev;
-
-		ev.type = SceneQueryType::RAYCAST;
-		ev.mode = m_mode;	
-		ev.hit = hit;
-		ev.callback = m_callback;
-		ev.position.x = rh.position.x;
-		ev.position.y = rh.position.y;
-		ev.position.z = rh.position.z;
-		ev.distance = rh.distance;
-		ev.normal.x = rh.normal.x;
-		ev.normal.y = rh.normal.y;
-		ev.normal.z = rh.normal.z;
-		ev.actor = (Actor*)(rh.actor->userData);
-
-		event_stream::write(m_events, physics_world::EventType::SCENE_QUERY, ev);
-
-		Log::i("callback: %s", ev.callback);
-		Log::i("position: (%f, %f, %f)", ev.position.x, ev.position.y, ev.position.z);
-		Log::i("normal: (%f, %f, %f)", ev.normal.x, ev.normal.y, ev.normal.z);
-		Log::i("distance: %f", ev.distance);
+		RaycastHit hit;
+
+		hit.position.x = rh.position.x;
+		hit.position.y = rh.position.y;
+		hit.position.z = rh.position.z;
+		hit.distance = rh.distance;
+		hit.normal.x = rh.normal.x;
+		hit.normal.y = rh.normal.y;
+		hit.normal.z = rh.normal.z;
+		hit.actor = (Actor*)(rh.actor->userData);
+
+		hits.push_back(hit);
 	}
 }
 
 //-------------------------------------------------------------------------
-Actor* Raycast::sync_cast(const Vector3& from, const Vector3& dir, const float length)
+CollisionMode::Enum Raycast::mode() const
 {
-	bool hit = m_scene->raycast(PxVec3(from.x, from.y, from.z), PxVec3(dir.x, dir.y, dir.z), length,
-								m_buffer, PxHitFlags(PxHitFlag::eDEFAULT), m_fd);
-
-	if (hit)
-	{
-		PxRaycastHit rh = m_buffer.getAnyHit(0);
-
-		Log::i("callback: %s", m_callback);
-		Log::i("position: (%f, %f, %f)", rh.position.x, rh.position.y, rh.position.z);
-		Log::i("distance: %f", rh.distance);
-
-		return (Actor*)(rh.actor->userData);
-	}
-	else return NULL;
+	return m_mode;
 }
 
+//-------------------------------------------------------------------------
+CollisionType::Enum Raycast::type() const
+{
+	return m_type;
+}
 
 } // namespace crown

+ 20 - 8
engine/physics/Raycast.h

@@ -46,21 +46,33 @@ namespace crown
 struct Vector3;
 struct Actor;
 
+//-----------------------------------------------------------------------------
+struct RaycastHit
+{
+	Vector3					position;
+	float					distance;
+	Vector3					normal;
+	Actor*					actor;
+};
+
+//-----------------------------------------------------------------------------
 struct Raycast
 {
 	/// Constructor
-			Raycast(PxScene* scene, EventStream& events, const char* callback, SceneQueryMode::Enum mode, SceneQueryFilter::Enum filter);
+	Raycast(PxScene* scene, EventStream& events, const char* callback, CollisionMode::Enum mode, CollisionType::Enum type);
 
 	/// Performs a raycast against objects in the scene. The ray is casted from position @a from, has direction @a dir and is long @a length
 	/// If any actor is hit along the ray, @a EventStream is filled according to @a mode previously specified and callback will be called for processing.
-	/// @a SceneQueryMode::ANY: the callback is called with just true or false depending on whether the ray hit anything or not.
-	/// @a SceneQueryMode::CLOSEST: the first argument will tell if there was a hit or not, as before. 
+	/// @a CollisionMode::ANY: the callback is called with just true or false depending on whether the ray hit anything or not.
+	/// @a CollisionMode::CLOSEST: the first argument will tell if there was a hit or not, as before. 
 	/// If there was a hit, the callback will also be called with the position of the hit, the distance from the origin, the normal of the surface that 
 	/// was hit and the actor that was hit.
-	/// @a SceneQueryMode::ALL: as @a SceneQueryMode::CLOSEST, with more tuples
-	void	cast(const Vector3& from, const Vector3& dir, const float length);
+	/// @a CollisionMode::ALL: as @a CollisionMode::CLOSEST, with more tuples
+	void					cast(const Vector3& from, const Vector3& dir, const float length, List<RaycastHit>& hits);
+
+	CollisionMode::Enum 	mode() const;
 
-	Actor*	sync_cast(const Vector3& from, const Vector3& dir, const float length);
+	CollisionType::Enum 	type() const;
 
 private:
 
@@ -72,8 +84,8 @@ private:
 	EventStream&			m_events;
 	const char*				m_callback;
 
-	SceneQueryMode::Enum		m_mode;
-	SceneQueryFilter::Enum		m_filter;
+	CollisionMode::Enum		m_mode;
+	CollisionType::Enum		m_type;
 };
 
 } // namespace crown