Browse Source

implement overlap_test in PhysicsWorld

mikymod 12 năm trước cách đây
mục cha
commit
ec40eedac1

+ 22 - 0
engine/lua/LuaPhysicsWorld.cpp

@@ -29,6 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "PhysicsWorld.h"
 #include "Raycast.h"
 #include "Vector3.h"
+#include "Quaternion.h"
 
 namespace crown
 {
@@ -72,12 +73,33 @@ CE_EXPORT int physics_world_make_raycast(lua_State* L)
 	return 1;
 }
 
+//-----------------------------------------------------------------------------
+CE_EXPORT int physics_world_overlap_test(lua_State* L)
+{
+	LuaStack stack(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);
+
+	world->overlap_test(callback, (SceneQueryMode::Enum) mode, (SceneQueryFilter::Enum) filter,
+						(ShapeType::Enum) shape_type, pos, rot, size);
+
+	return 0;
+}
+
 //-----------------------------------------------------------------------------
 void load_physics_world(LuaEnvironment& env)
 {
 	env.load_module_function("PhysicsWorld", "gravity",			physics_world_gravity);
 	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);
 }
 
 } // namespace crown

+ 20 - 9
engine/physics/PhysicsTypes.h

@@ -117,6 +117,16 @@ struct CollisionGroup
 	};
 };
 
+//-----------------------------------------------------------------------------
+struct SceneQueryType
+{
+	enum Enum
+	{
+		RAYCAST,
+		OVERLAP
+	};
+};
+
 //-----------------------------------------------------------------------------
 struct SceneQueryMode
 {
@@ -148,7 +158,7 @@ struct EventType
 	{
 		COLLISION,
 		TRIGGER,
-		RAYCAST
+		SCENE_QUERY
 	};
 };
 
@@ -166,15 +176,16 @@ struct TriggerEvent
 };
 
 //-----------------------------------------------------------------------------
-struct RaycastEvent
+struct SceneQueryEvent
 {
-	bool 				hit;
-	char* 				callback;
-	SceneQueryMode::Enum 	mode;
-	Vector3 			position;
-	float				distance;
-	Vector3 			normal;
-	Actor*				actor;
+	const char*				callback;
+	SceneQueryType::Enum	type;
+	SceneQueryMode::Enum	mode;
+	bool					hit;
+	Vector3					position;
+	float					distance;
+	Vector3					normal;
+	Actor*					actor;
 };
 
 }

+ 52 - 0
engine/physics/PhysicsWorld.cpp

@@ -64,6 +64,9 @@ using physx::PxPairFlag;
 using physx::PxFilterFlag;
 using physx::PxSceneLimits;
 using physx::PxVisualizationParameter;
+using physx::PxSphereGeometry;
+using physx::PxCapsuleGeometry;
+using physx::PxBoxGeometry;
 
 namespace crown
 {
@@ -208,6 +211,7 @@ namespace physics_system
 //-----------------------------------------------------------------------------
 PhysicsWorld::PhysicsWorld()
 	: m_scene(NULL)
+	, m_buffer(m_hits, 64)
 	, m_actors_pool(default_allocator(), CE_MAX_ACTORS, sizeof(Actor), CE_ALIGNOF(Actor))
 	, m_controllers_pool(default_allocator(), CE_MAX_CONTROLLERS, sizeof(Controller), CE_ALIGNOF(Controller))
 	, m_joints_pool(default_allocator(), CE_MAX_JOINTS, sizeof(Joint), CE_ALIGNOF(Joint))
@@ -380,6 +384,54 @@ void PhysicsWorld::clear_kinematic(ActorId id)
 	actor->clear_kinematic();
 }
 
+//-----------------------------------------------------------------------------
+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)
+{
+	bool hit = false;
+	PxTransform transform(PxVec3(pos.x, pos.y, pos.x), 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;
+	}
+
+	for (uint32_t i = 0; i < m_buffer.getNbAnyHits(); i++)
+	{
+		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");
+	}
+}
+
 //-----------------------------------------------------------------------------
 void PhysicsWorld::update(float dt)
 {

+ 9 - 0
engine/physics/PhysicsWorld.h

@@ -42,6 +42,8 @@ using physx::PxControllerManager;
 using physx::PxScene;
 using physx::PxDefaultCpuDispatcher;
 using physx::PxActor;
+using physx::PxOverlapHit;
+using physx::PxOverlapBuffer;
 
 namespace crown
 {
@@ -62,6 +64,7 @@ struct PhysicsResource;
 struct PhysicsActor;
 struct Controller;
 struct Vector3;
+struct Matrix4x4;
 struct Actor;
 struct Joint;
 struct Quaternion;
@@ -100,6 +103,9 @@ public:
 	void						set_kinematic(ActorId id);
 	void						clear_kinematic(ActorId id);
 
+	void						overlap_test(const char* callback, SceneQueryMode::Enum mode, SceneQueryFilter::Enum filter,
+											ShapeType::Enum type, const Vector3& pos, const Quaternion& rot, const Vector3& size);
+
 	void						update(float dt);
 
 public:
@@ -108,6 +114,9 @@ public:
 	PxScene*					m_scene;
 	PxDefaultCpuDispatcher*		m_cpu_dispatcher;
 
+	PxOverlapHit 				m_hits[64]; // hardcoded	
+	PxOverlapBuffer 			m_buffer;
+
 	PoolAllocator				m_actors_pool;
 	PoolAllocator				m_controllers_pool;
 	PoolAllocator				m_joints_pool;

+ 7 - 6
engine/physics/Raycast.cpp

@@ -68,11 +68,12 @@ void Raycast::cast(const Vector3& from, const Vector3& dir, const float length)
 	{
 		PxRaycastHit rh = m_buffer.getAnyHit(i);
 
-		physics_world::RaycastEvent ev;
-		
+		physics_world::SceneQueryEvent ev;
+
+		ev.type = SceneQueryType::RAYCAST;
+		ev.mode = m_mode;	
 		ev.hit = hit;
-		string::strncpy(ev.callback, m_callback, string::strlen(m_callback)+1);
-		ev.mode = m_mode;
+		ev.callback = m_callback;
 		ev.position.x = rh.position.x;
 		ev.position.y = rh.position.y;
 		ev.position.z = rh.position.z;
@@ -82,12 +83,12 @@ void Raycast::cast(const Vector3& from, const Vector3& dir, const float length)
 		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);
-
-		event_stream::write(m_events, physics_world::EventType::RAYCAST, ev);
 	}
 }