ソースを参照

improve raycasting

mikymod 12 年 前
コミット
ed35456655

+ 1 - 0
engine/Android.mk

@@ -152,6 +152,7 @@ LOCAL_SRC_FILES :=\
 	physics/PhysicsWorld.cpp\
 	physics/Trigger.cpp\
 	physics/Joint.cpp\
+	physics/Raycast.cpp\
 \
 	renderers/backend/gl/egl/GLContext.cpp\
 	renderers/backend/gl/GLRenderer.cpp\

+ 1 - 0
engine/CMakeLists.txt

@@ -402,6 +402,7 @@ set (PHYSICS_SRC
 	physics/PhysicsWorld.cpp
 	physics/Trigger.cpp
 	physics/Joint.cpp
+	physics/Raycast.cpp
 )
 
 set (PHYSICS_HEADERS

+ 4 - 3
engine/lua/LuaPhysicsWorld.cpp

@@ -62,10 +62,11 @@ 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);
+	const char* callback = stack.get_string(2);
+	int mode = stack.get_int(3);
+	int filter = stack.get_int(4);
 
-	Raycast* raycast = world->make_raycast((RaycastMode::Enum) mode, (RaycastFilter::Enum) filter);
+	Raycast* raycast = world->make_raycast(callback, (RaycastMode::Enum) mode, (RaycastFilter::Enum) filter);
 
 	stack.push_raycast(raycast);
 	return 1;

+ 3 - 4
engine/lua/LuaRaycast.cpp

@@ -40,11 +40,10 @@ CE_EXPORT int raycast_cast(lua_State* L)
 	Vector3 from = stack.get_vector3(2);
 	Vector3 dir = stack.get_vector3(3);
 	float length = stack.get_float(4);
+	
+	raycast->cast(from, dir, length);
 
-	bool status = raycast->cast(from, dir, length);
-
-	stack.push_bool(status);
-	return 1;
+	return 0;
 }
 
 //-----------------------------------------------------------------------------

+ 10 - 10
engine/physics/Actor.h

@@ -108,16 +108,16 @@ private:
 	
 public:
 
-	const PhysicsResource*	m_resource;
-	const PhysicsConfigResource* m_config;
-	uint32_t				m_index;
-
-	PxScene*				m_scene;
-	SceneGraph&				m_scene_graph;
-	int32_t					m_node;
-	PxRigidActor* 			m_actor;
-	uint32_t				m_group;
-	uint32_t				m_mask;
+	const PhysicsResource*			m_resource;
+	const PhysicsConfigResource* 	m_config;
+	uint32_t						m_index;
+
+	PxScene*						m_scene;
+	SceneGraph&						m_scene_graph;
+	int32_t							m_node;
+	PxRigidActor* 					m_actor;
+	uint32_t						m_group;
+	uint32_t						m_mask;
 
 private:
 

+ 32 - 15
engine/physics/PhysicsTypes.h

@@ -140,25 +140,42 @@ struct RaycastFilter
 
 namespace physics_world
 {
-	struct EventType
+//-----------------------------------------------------------------------------	
+struct EventType
+{
+	enum Enum
 	{
-		enum Enum
-		{
-			COLLISION,
-			TRIGGER
-		};
+		COLLISION,
+		TRIGGER,
+		RAYCAST
 	};
+};
 
-	struct CollisionEvent
-	{
-		Actor* actors[2];
-		Vector3 where;
-	};
+//-----------------------------------------------------------------------------
+struct CollisionEvent
+{
+	Actor* actors[2];
+	Vector3 where;
+};
+
+//-----------------------------------------------------------------------------
+struct TriggerEvent
+{
+	Actor* actor;
+};
+
+//-----------------------------------------------------------------------------
+struct RaycastEvent
+{
+	bool 				hit;
+	char* 				callback;
+	RaycastMode::Enum 	mode;
+	Vector3 			position;
+	float				distance;
+	Vector3 			normal;
+	Actor*				actor;
+};
 
-	struct TriggerEvent
-	{
-		Actor* actor;
-	};
 }
 
 } // namespace crown

+ 2 - 2
engine/physics/PhysicsWorld.cpp

@@ -381,9 +381,9 @@ void PhysicsWorld::clear_kinematic(ActorId id)
 }
 
 //-----------------------------------------------------------------------------
-Raycast* PhysicsWorld::make_raycast(RaycastMode::Enum mode, RaycastFilter::Enum filter)
+Raycast* PhysicsWorld::make_raycast(const char* callback, RaycastMode::Enum mode, RaycastFilter::Enum filter)
 {
-	return CE_NEW(default_allocator(), Raycast)(m_scene, mode, filter);
+	return CE_NEW(default_allocator(), Raycast)(m_scene, m_events, callback, mode, filter);
 }
 
 //-----------------------------------------------------------------------------

+ 1 - 1
engine/physics/PhysicsWorld.h

@@ -101,7 +101,7 @@ public:
 	void						set_kinematic(ActorId id);
 	void						clear_kinematic(ActorId id);
 
-	Raycast*					make_raycast(RaycastMode::Enum mode, RaycastFilter::Enum filter);
+	Raycast*					make_raycast(const char* callback, RaycastMode::Enum mode, RaycastFilter::Enum filter);
 
 	void						update(float dt);
 

+ 94 - 0
engine/physics/Raycast.cpp

@@ -0,0 +1,94 @@
+/*
+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 "PxRigidActor.h"
+#include "Raycast.h"
+#include "Actor.h"
+#include "StringUtils.h"
+
+using physx::PxRigidActor;
+
+namespace crown
+{
+
+//-------------------------------------------------------------------------
+Raycast::Raycast(PxScene* scene, EventStream& events, const char* callback, RaycastMode::Enum mode, RaycastFilter::Enum filter)
+	: m_scene(scene)
+	, m_buffer(m_hits, MAX_RAYCAST_INTERSECTIONS)
+	, m_events(events)
+	, m_callback(callback)
+	, 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;
+	}
+}
+
+//-------------------------------------------------------------------------
+void Raycast::cast(const Vector3& from, const Vector3& dir, const float length)
+{
+	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);
+
+	for (uint32_t i = 0; i < m_buffer.getNbAnyHits(); i++)
+	{
+		PxRaycastHit rh = m_buffer.getAnyHit(i);
+
+		physics_world::RaycastEvent ev;
+		
+		ev.hit = hit;
+		string::strncpy(ev.callback, m_callback, string::strlen(m_callback)+1);
+		ev.mode = m_mode;
+		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);
+
+		// 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);
+	}
+}
+
+} // namespace crown

+ 8 - 40
engine/physics/Raycast.h

@@ -25,16 +25,17 @@ OTHER DEALINGS IN THE SOFTWARE.
 */
 
 #include "Log.h"
-#include "PhysicsCallback.h"
 #include "PhysicsTypes.h"
 #include "PxQueryFiltering.h"
 #include "PxScene.h"
 #include "PxVec3.h"
+#include "EventStream.h"
 
 using physx::PxQueryFilterData;
 using physx::PxQueryFlag;
 using physx::PxHitFlag;
 using physx::PxHitFlags;
+using physx::PxRaycastHit;
 using physx::PxRaycastBuffer;
 using physx::PxScene;
 using physx::PxVec3;
@@ -44,47 +45,13 @@ using physx::PxVec3;
 namespace crown
 {
 
+struct Vector3;
+
 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);
+			Raycast(PxScene* scene, EventStream& events, const char* callback, RaycastMode::Enum mode, RaycastFilter::Enum filter);
 
-		if (status)	Log::i("Raycast YES");
-		return status;
-	}
+	void	cast(const Vector3& from, const Vector3& dir, const float length);
 
 private:
 
@@ -93,7 +60,8 @@ private:
 	PxRaycastBuffer			m_buffer;
 	PxQueryFilterData 		m_fd;
 
-	// PhysicsRaycastCallback	m_callback;
+	EventStream&			m_events;
+	const char*				m_callback;
 
 	RaycastMode::Enum		m_mode;
 	RaycastFilter::Enum		m_filter;