Kaynağa Gözat

implement raycast in PhysicsWorld

mikymod 12 yıl önce
ebeveyn
işleme
84e008df2d

+ 2 - 0
engine/CMakeLists.txt

@@ -369,6 +369,7 @@ set (LUA_SRC
 	lua/LuaMouse.cpp
 	lua/LuaPhysicsWorld.cpp
 	lua/LuaQuaternion.cpp
+	lua/LuaRaycast.cpp
 	lua/LuaResourcePackage.cpp
 	lua/LuaSoundWorld.cpp
 	lua/LuaSprite.cpp
@@ -410,6 +411,7 @@ set (PHYSICS_HEADERS
 	physics/PhysicsWorld.h
 	physics/Trigger.h
 	physics/Joint.h
+	physics/Raycast.h
 	physics/PhysicsCallback.h
 )
 

+ 1 - 0
engine/lua/LuaEnvironment.h

@@ -110,6 +110,7 @@ void load_vector3(LuaEnvironment& env);
 void load_window(LuaEnvironment& env);
 void load_world(LuaEnvironment& env);
 void load_debug_line(LuaEnvironment& env);
+void load_raycast(LuaEnvironment& env);
 
 CE_EXPORT int32_t luaopen_libcrown(lua_State* L);
 

+ 19 - 2
engine/lua/LuaPhysicsWorld.cpp

@@ -24,10 +24,11 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
+#include "LuaEnvironment.h"
+#include "LuaStack.h"
 #include "PhysicsWorld.h"
+#include "Raycast.h"
 #include "Vector3.h"
-#include "LuaStack.h"
-#include "LuaEnvironment.h"
 
 namespace crown
 {
@@ -55,11 +56,27 @@ CE_EXPORT int physics_world_set_gravity(lua_State* L)
 	return 0;
 }
 
+//-----------------------------------------------------------------------------
+CE_EXPORT int physics_world_make_raycast(lua_State* L)
+{
+	LuaStack stack(L);
+
+	PhysicsWorld* world = stack.get_physics_world(1);
+	int mode = stack.get_int(2);
+	int filter = stack.get_int(3);
+
+	Raycast* raycast = world->make_raycast((RaycastMode::Enum) mode, (RaycastFilter::Enum) filter);
+
+	stack.push_raycast(raycast);
+	return 1;
+}
+
 //-----------------------------------------------------------------------------
 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);
 }
 
 } // namespace crown

+ 64 - 0
engine/lua/LuaRaycast.cpp

@@ -0,0 +1,64 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "LuaStack.h"
+#include "LuaEnvironment.h"
+#include "Raycast.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int raycast_cast(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Raycast* raycast = stack.get_raycast(1);
+	Vector3 from = stack.get_vector3(2);
+	Vector3 dir = stack.get_vector3(3);
+	float length = stack.get_float(4);
+
+	bool status = raycast->cast(from, dir, length);
+
+	stack.push_bool(status);
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+void load_raycast(LuaEnvironment& env)
+{
+	env.load_module_function("Raycast", "cast",	raycast_cast);
+
+	env.load_module_enum("Raycast", "CLOSEST",	RaycastMode::CLOSEST);
+	env.load_module_enum("Raycast", "ANY",		RaycastMode::ANY);
+	env.load_module_enum("Raycast", "ALL",		RaycastMode::ALL);
+
+	env.load_module_enum("Raycast", "STATIC",	RaycastFilter::STATIC);
+	env.load_module_enum("Raycast", "DYNAMIC",	RaycastFilter::DYNAMIC);
+	env.load_module_enum("Raycast", "BOTH",		RaycastFilter::BOTH);
+}
+
+} // namespace crown

+ 13 - 0
engine/lua/LuaStack.h

@@ -49,6 +49,7 @@ struct Unit;
 struct Vector2;
 struct Vector3;
 struct DebugLine;
+struct Raycast;
 
 typedef Id SoundInstanceId;
 typedef Id GuiId;
@@ -310,6 +311,18 @@ public:
 		return (Controller*) lua_touserdata(m_state, index);
 	}
 
+	//-----------------------------------------------------------------------------
+	void push_raycast(Raycast* raycast)
+	{
+		lua_pushlightuserdata(m_state, raycast);
+	}
+
+	//-----------------------------------------------------------------------------
+	Raycast* get_raycast(int32_t index)
+	{
+		return (Raycast*) lua_touserdata(m_state, index);
+	}
+
 	//-----------------------------------------------------------------------------
 	void push_sound_instance_id(const SoundInstanceId id)
 	{

+ 1 - 0
engine/lua/LuaSystem.cpp

@@ -212,6 +212,7 @@ namespace lua_system
 		load_sound_world(env);
 		load_gui(env);
 		load_debug_line(env);
+		load_raycast(env);
 
 		// Register custom loader
 		lua_getfield(s_L, LUA_GLOBALSINDEX, "package");

+ 30 - 0
engine/physics/PhysicsCallback.h

@@ -32,6 +32,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "PxRigidActor.h"
 #include "PxController.h"
 #include "PxSimulationEventCallback.h"
+#include "PxQueryReport.h"
+#include "PxQueryFiltering.h"
 
 
 using physx::PxActor;
@@ -50,6 +52,9 @@ using physx::PxTriggerPairFlag;
 using physx::PxU32;
 using physx::PxUserControllerHitReport;
 using physx::PxVec3;
+using physx::PxRaycastCallback;
+using physx::PxAgain;
+using physx::PxRaycastHit;
 
 namespace crown
 {
@@ -164,4 +169,29 @@ class PhysicsControllerCallback : public PxUserControllerHitReport
 	}
 };
 
+// //-----------------------------------------------------------------------------
+// struct PhysicsRaycastCallback : public PxRaycastCallback
+// {
+// 	PhysicsRaycastCallback(PxRaycastHit* touches, PxU32 max_touches) : PxRaycastCallback(touches, max_touches)
+// 	{
+// 	}
+
+// 	//-----------------------------------------------------------------------------
+// 	virtual PxAgain processTouches(const PxRaycastHit* buffer, PxU32 nbHits)
+// 	{
+// 		for (PxU32 i = 0; i < nbHits; i++)
+// 		{
+// 			printf("buffer['%d']=(%f, %f)\n", i, buffer[i].u, buffer[i].v);
+// 		}
+
+// 		return false;
+// 	}
+
+// 	//-----------------------------------------------------------------------------
+// 	virtual void finalizeQuery()
+// 	{
+// 		printf("Raycast query finalized\n");
+// 	}
+// };
+
 } // namespace crown

+ 22 - 0
engine/physics/PhysicsTypes.h

@@ -116,6 +116,28 @@ struct CollisionGroup
 	};
 };
 
+//-----------------------------------------------------------------------------
+struct RaycastMode
+{
+	enum Enum
+	{
+		CLOSEST,
+		ANY,
+		ALL
+	};
+};
+
+//-----------------------------------------------------------------------------
+struct RaycastFilter
+{
+	enum Enum
+	{
+		STATIC,
+		DYNAMIC,
+		BOTH
+	};
+};
+
 namespace physics_world
 {
 	struct EventType

+ 10 - 1
engine/physics/PhysicsWorld.cpp

@@ -39,6 +39,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "StringUtils.h"
 #include "Actor.h"
 #include "ResourceManager.h"
+#include "Raycast.h"
 
 #include "PxPhysicsAPI.h"
 
@@ -225,7 +226,9 @@ PhysicsWorld::PhysicsWorld()
 	scene_desc.limits = scene_limits;
 	scene_desc.filterShader = physics_system::FilterShader;
 	scene_desc.simulationEventCallback = &m_callback;
-	scene_desc.flags = PxSceneFlag::eENABLE_ACTIVETRANSFORMS | PxSceneFlag::eENABLE_KINEMATIC_STATIC_PAIRS | PxSceneFlag::eENABLE_KINEMATIC_PAIRS;
+	scene_desc.flags = 	PxSceneFlag::eENABLE_ACTIVETRANSFORMS 
+					  | PxSceneFlag::eENABLE_KINEMATIC_STATIC_PAIRS
+					  | PxSceneFlag::eENABLE_KINEMATIC_PAIRS;
 
 	if(!scene_desc.cpuDispatcher)
 	{
@@ -377,6 +380,12 @@ void PhysicsWorld::clear_kinematic(ActorId id)
 	actor->clear_kinematic();
 }
 
+//-----------------------------------------------------------------------------
+Raycast* PhysicsWorld::make_raycast(RaycastMode::Enum mode, RaycastFilter::Enum filter)
+{
+	return CE_NEW(default_allocator(), Raycast)(m_scene, mode, filter);
+}
+
 //-----------------------------------------------------------------------------
 void PhysicsWorld::update(float dt)
 {

+ 3 - 0
engine/physics/PhysicsWorld.h

@@ -68,6 +68,7 @@ struct Joint;
 struct Quaternion;
 class SceneGraph;
 struct Actor;
+struct Raycast;
 
 //-----------------------------------------------------------------------------
 class PhysicsWorld
@@ -100,6 +101,8 @@ public:
 	void						set_kinematic(ActorId id);
 	void						clear_kinematic(ActorId id);
 
+	Raycast*					make_raycast(RaycastMode::Enum mode, RaycastFilter::Enum filter);
+
 	void						update(float dt);
 
 public:

+ 102 - 0
engine/physics/Raycast.h

@@ -0,0 +1,102 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "Log.h"
+#include "PhysicsCallback.h"
+#include "PhysicsTypes.h"
+#include "PxQueryFiltering.h"
+#include "PxScene.h"
+#include "PxVec3.h"
+
+using physx::PxQueryFilterData;
+using physx::PxQueryFlag;
+using physx::PxHitFlag;
+using physx::PxHitFlags;
+using physx::PxRaycastBuffer;
+using physx::PxScene;
+using physx::PxVec3;
+
+#define MAX_RAYCAST_INTERSECTIONS 32
+
+namespace crown
+{
+
+struct Raycast
+{
+	//-------------------------------------------------------------------------
+	Raycast(PxScene* scene, RaycastMode::Enum mode, RaycastFilter::Enum filter)
+		: m_scene(scene)
+		, m_buffer(m_hits, MAX_RAYCAST_INTERSECTIONS)
+		, m_mode(mode)
+		, m_filter(filter)
+	{
+		switch (m_filter)
+		{
+			case RaycastFilter::BOTH: break;
+			case RaycastFilter::STATIC: m_fd.flags = PxQueryFlag::eSTATIC; break;
+			case RaycastFilter::DYNAMIC: m_fd.flags = PxQueryFlag::eDYNAMIC; break;
+		}
+
+		switch (m_mode)
+		{
+			case RaycastMode::CLOSEST: break;
+			case RaycastMode::ANY: m_fd.flags |= PxQueryFlag::eANY_HIT; break;
+			case RaycastMode::ALL: break;
+		}
+	}
+
+	//-------------------------------------------------------------------------
+	bool cast(const Vector3& from, const Vector3& dir, const float length)
+	{
+		// Log::i("from: (%f, %f, %f)", from.x, from.y, from.z);
+		// Log::i("dir: (%f, %f, %f)", dir.x, dir.y, dir.z);
+		// Log::i("length: %f", length);
+
+		bool status = 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 (status)	Log::i("Raycast YES");
+		return status;
+	}
+
+private:
+
+	PxScene* 				m_scene;
+	PxRaycastHit 			m_hits[MAX_RAYCAST_INTERSECTIONS];	
+	PxRaycastBuffer			m_buffer;
+	PxQueryFilterData 		m_fd;
+
+	// PhysicsRaycastCallback	m_callback;
+
+	RaycastMode::Enum		m_mode;
+	RaycastFilter::Enum		m_filter;
+};
+
+} // namespace crown