Просмотр исходного кода

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

Daniele Bartolini 12 лет назад
Родитель
Сommit
263e9db339

+ 1 - 0
engine/CMakeLists.txt

@@ -404,6 +404,7 @@ set (PHYSICS_HEADERS
 	physics/PhysicsTypes.h
 	physics/PhysicsWorld.h
 	physics/Trigger.h
+	physics/PhysicsCallback.h
 )
 
 set (WORLD_SRC

+ 107 - 20
engine/physics/Actor.cpp

@@ -32,6 +32,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Device.h"
 #include "Physics.h"
 #include "Log.h"
+#include "PhysicsResource.h"
 #include "SceneGraph.h"
 #include "PxPhysicsAPI.h"
 
@@ -41,6 +42,7 @@ using physx::PxTransform;
 using physx::PxActorFlag;
 using physx::PxVec3;
 using physx::PxReal;
+using physx::PxRigidActor;
 using physx::PxRigidBody;
 using physx::PxRigidDynamic;
 using physx::PxRigidStatic;
@@ -48,6 +50,10 @@ using physx::PxPlaneGeometry;
 using physx::PxSphereGeometry;
 using physx::PxBoxGeometry;
 using physx::PxRigidBodyExt;
+using physx::PxShape;
+using physx::PxShapeFlag;
+using physx::PxU32;
+using physx::PxFilterData;
 
 using physx::PxD6Joint;
 using physx::PxD6JointCreate;
@@ -56,19 +62,52 @@ using physx::PxD6Motion;
 
 namespace crown
 {
-	
+
+//-----------------------------------------------------------------------------
+struct FilterGroup
+{
+	enum Enum
+	{
+		eACTOR 			= (1 << 0),
+		eHEIGHTFIELD 	= (1 << 1)
+	};
+};
+
+//-----------------------------------------------------------------------------
+static void setup_filtering(PxRigidActor* actor, PxU32 filterGroup, PxU32 filterMask)
+{
+	PxFilterData filterData;
+	filterData.word0 = filterGroup;	// word0 = own ID
+	filterData.word1 = filterMask;	// word1 = ID mask to filter pairs that trigger a contact callback;
+
+	const PxU32 num_shapes = actor->getNbShapes();
+	PxShape** shapes = (PxShape**) default_allocator().allocate((sizeof(PxShape*) * num_shapes));
+	actor->getShapes(shapes, num_shapes);
+
+	for(PxU32 i = 0; i < num_shapes; i++)
+	{
+		PxShape* shape = shapes[i];
+		shape->setSimulationFilterData(filterData);
+	}
+
+	default_allocator().deallocate(shapes);
+}
+
 //-----------------------------------------------------------------------------
-Actor::Actor(PxScene* scene, SceneGraph& sg, int32_t node, ActorType::Enum type, const Vector3& pos, const Quaternion& rot)
-	: m_scene(scene)
+Actor::Actor(const PhysicsResource* res, uint32_t i, PxScene* scene, SceneGraph& sg, int32_t node, const Vector3& pos, const Quaternion& rot)
+	: m_resource(res)
+	, m_index(i)
+	, m_scene(scene)
 	, m_scene_graph(sg)
 	, m_node(node)
-	, m_type(type)
 {
-	Matrix4x4 m = sg.world_pose(node);
+	const PhysicsActor& a = m_resource->actor(m_index);
 
+	// Creates actor
+	Matrix4x4 m = sg.world_pose(node);
 	PxMat44 pose((PxReal*)(m.to_float_ptr()));
 
-	switch (type)
+	switch (a.type)
 	{
 		case ActorType::STATIC:
 		{
@@ -80,7 +119,7 @@ Actor::Actor(PxScene* scene, SceneGraph& sg, int32_t node, ActorType::Enum type,
 		{
 			m_actor = device()->physx()->createRigidDynamic(PxTransform(pose));
 
-			if (type == ActorType::DYNAMIC_KINEMATIC)
+			if (a.type == ActorType::DYNAMIC_KINEMATIC)
 			{
 				static_cast<PxRigidDynamic*>(m_actor)->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true);
 			}
@@ -94,11 +133,41 @@ Actor::Actor(PxScene* scene, SceneGraph& sg, int32_t node, ActorType::Enum type,
 	}
 
 	m_actor->userData = this;
-	m_mat = device()->physx()->createMaterial(0.5f, 0.5f, 0.5f);
-	
-	create_box(Vector3(0, 0, 0), .5, .5, .5);
+	m_mat = device()->physx()->createMaterial(0.5f, 0.5f, 1.0f);
 
-	if (type == ActorType::DYNAMIC_PHYSICAL || type == ActorType::DYNAMIC_KINEMATIC)
+	// Creates shapes
+	uint32_t index = m_resource->shape_index(m_index);
+	for (uint32_t i = 0; i < a.num_shapes; i++)
+	{
+		PhysicsShape shape = m_resource->shape(index);
+		Vector3 pos = sg.world_position(node);
+
+		switch(shape.type)
+		{
+			case PhysicsShapeType::SPHERE:
+			{
+				create_sphere(pos, shape.data_0);
+				break;
+			}
+			case PhysicsShapeType::BOX:
+			{
+				create_box(pos, shape.data_0, shape.data_1, shape.data_2);
+				break;
+			}
+			case PhysicsShapeType::PLANE:
+			{
+				create_plane(pos, Vector3(shape.data_0, shape.data_1, shape.data_2));
+				break;
+			}
+			default:
+			{
+				CE_FATAL("Oops, unknown shape type");
+			}
+		}
+		index++;
+	}
+
+	if (a.type == ActorType::DYNAMIC_PHYSICAL || a.type == ActorType::DYNAMIC_KINEMATIC)
 	{
 		PxRigidBodyExt::setMassAndUpdateInertia(*static_cast<PxRigidDynamic*>(m_actor), 500.0f);
 
@@ -110,6 +179,9 @@ Actor::Actor(PxScene* scene, SceneGraph& sg, int32_t node, ActorType::Enum type,
 		joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
 	}
 
+	m_actor->setActorFlag(PxActorFlag::eSEND_SLEEP_NOTIFIES, true);
+	setup_filtering(m_actor, FilterGroup::eACTOR, FilterGroup::eACTOR);
+	// static_cast<PxRigidBody*>(m_actor)->setRigidBodyFlag(PxRigidBodyFlag::eENABLE_CCD, true);
 	m_scene->addActor(*m_actor);
 }
 
@@ -126,17 +198,21 @@ Actor::~Actor()
 //-----------------------------------------------------------------------------
 void Actor::create_sphere(const Vector3& position, float radius)
 {
-	m_actor->createShape(PxSphereGeometry(radius), *m_mat);
+	PxShape* shape = m_actor->createShape(PxSphereGeometry(radius), *m_mat);
+	// shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
+	// shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);
 }
 
 //-----------------------------------------------------------------------------
 void Actor::create_box(const Vector3& position, float a, float b, float c)
 {
-	m_actor->createShape(PxBoxGeometry(a, b, c), *m_mat);
+	PxShape* shape = m_actor->createShape(PxBoxGeometry(a, b, c), *m_mat);
+	// shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
+	// shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);
 }
 
 //-----------------------------------------------------------------------------
-void Actor::create_plane(const Vector3& /*position*/, const Vector3& /*normal*/)
+void Actor::create_plane(const Vector3& position, const Vector3& /*normal*/)
 {
 	m_actor->createShape(PxPlaneGeometry(), *m_mat);
 }
@@ -156,25 +232,33 @@ void Actor::disable_gravity()
 //-----------------------------------------------------------------------------
 bool Actor::is_static() const
 {
-	return m_type == ActorType::STATIC;
+	const PhysicsActor& a = m_resource->actor(m_index);
+
+	return a.type == ActorType::STATIC;
 }
 
 //-----------------------------------------------------------------------------
 bool Actor::is_dynamic() const
 {
-	return m_type == ActorType::DYNAMIC_PHYSICAL || m_type == ActorType::DYNAMIC_KINEMATIC;
+	const PhysicsActor& a = m_resource->actor(m_index);
+
+	return a.type == ActorType::DYNAMIC_PHYSICAL || a.type == ActorType::DYNAMIC_KINEMATIC;
 }
 
 //-----------------------------------------------------------------------------
 bool Actor::is_kinematic() const
 {
-	return m_type == ActorType::DYNAMIC_KINEMATIC;
+	const PhysicsActor& a = m_resource->actor(m_index);
+
+	return a.type == ActorType::DYNAMIC_KINEMATIC;
 }
 
 //-----------------------------------------------------------------------------
 bool Actor::is_physical() const
 {
-	return m_type == ActorType::DYNAMIC_PHYSICAL;
+	const PhysicsActor& a = m_resource->actor(m_index);
+
+	return a.type == ActorType::DYNAMIC_PHYSICAL;
 }
 
 //-----------------------------------------------------------------------------
@@ -251,7 +335,9 @@ void Actor::update_pose()
 	const PxMat44 pose((PxReal*) (wp.to_float_ptr()));
 	const PxTransform world_transform(pose);
 
-	switch (m_type)
+	const PhysicsActor& a = m_resource->actor(m_index);
+
+	switch (a.type)
 	{
 		case ActorType::STATIC:
 		{
@@ -273,8 +359,9 @@ void Actor::update_pose()
 //-----------------------------------------------------------------------------
 void Actor::update(const Matrix4x4& pose)
 {
+	const PhysicsActor& a = m_resource->actor(m_index);
 
-	if (m_type == ActorType::DYNAMIC_PHYSICAL)
+	if (a.type == ActorType::DYNAMIC_PHYSICAL)
 	{
 		m_scene_graph.set_world_pose(m_node, pose);
 	}

+ 12 - 7
engine/physics/Actor.h

@@ -27,6 +27,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "Types.h"
+#include "IdTable.h"
+#include "IdArray.h"
 #include "PhysicsTypes.h"
 #include "Vector3.h"
 #include "Matrix4x4.h"
@@ -43,6 +45,7 @@ using physx::PxScene;
 namespace crown
 {
 
+struct PhysicsResource;
 struct Quaternion;
 struct Matrix4x4;
 struct Unit;
@@ -50,7 +53,7 @@ class SceneGraph;
 
 struct Actor
 {
-						Actor(PxScene* scene, SceneGraph& sg, int32_t node, ActorType::Enum type, const Vector3& pos, const Quaternion& rot);
+						Actor(const PhysicsResource* res, uint32_t i, PxScene* scene, SceneGraph& sg, int32_t node, const Vector3& pos, const Quaternion& rot);
 						~Actor();
 
 	void				enable_gravity();
@@ -88,12 +91,14 @@ private:
 	
 public:
 
-	PxScene*			m_scene;
-	SceneGraph&			m_scene_graph;
-	int32_t				m_node;
-	PxRigidActor* 		m_actor;
-	PxMaterial* 		m_mat;
-	ActorType::Enum 	m_type;
+	const PhysicsResource*	m_resource;
+	uint32_t				m_index;
+
+	PxScene*				m_scene;
+	SceneGraph&				m_scene_graph;
+	int32_t					m_node;
+	PxRigidActor* 			m_actor;
+	PxMaterial* 			m_mat;
 };
 
 } // namespace crown

+ 80 - 0
engine/physics/PhysicsCallback.h

@@ -0,0 +1,80 @@
+/*
+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.
+*/
+
+#pragma once
+
+#include "PxSimulationEventCallback.h"
+
+using physx::PxSimulationEventCallback;
+using physx::PxContactPairHeader;
+using physx::PxContactPair;
+using physx::PxConstraintInfo;
+using physx::PxTriggerPair;
+using physx::PxU32;
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+class PhysicsCallback : public PxSimulationEventCallback
+{
+public:
+
+	//-----------------------------------------------------------------------------
+	PhysicsCallback() {}
+
+	//-----------------------------------------------------------------------------
+	void onConstraintBreak(PxConstraintInfo* /*constraints*/, PxU32 /*count*/)
+	{
+		Log::i("COSTRAINTBREAK");
+	}
+
+	//-----------------------------------------------------------------------------
+	void onContact(const PxContactPairHeader& /*pairHeader*/, const PxContactPair* /*pairs*/, PxU32 /*nbPairs*/)
+	{
+		Log::i("CONTACT");
+	}
+
+	//-----------------------------------------------------------------------------
+	void onTrigger(PxTriggerPair* /*pairs*/, PxU32 /*count*/)
+	{
+		Log::i("TRIGGER");
+	}
+
+	//-----------------------------------------------------------------------------
+	void onWake(PxActor** /*actors*/, PxU32 /*count*/)
+	{
+		Log::i("WAKE");
+	}
+
+	//-----------------------------------------------------------------------------
+	void onSleep(PxActor** /*actors*/, PxU32 /*count*/)
+	{
+		Log::i("SLEEP");
+	}
+};
+
+} // namespace crown

+ 49 - 14
engine/physics/PhysicsWorld.cpp

@@ -33,6 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "SceneGraph.h"
 #include "Controller.h"
 #include "Trigger.h"
+#include "PhysicsCallback.h"
 
 #include "PxPhysicsAPI.h"
 
@@ -49,11 +50,42 @@ using physx::PxRigidStatic;
 using physx::PxActiveTransform;
 using physx::PxU32;
 using physx::PxSceneFlag;
+using physx::PxFilterFlags;
+using physx::PxFilterData;
+using physx::PxPairFlags;
+using physx::PxFilterObjectAttributes;
+using physx::PxFilterObjectIsTrigger;
+using physx::PxPairFlag;
+using physx::PxFilterFlag;
 
 namespace crown
 {
 
-static physx::PxSimulationFilterShader g_default_filter_shader = physx::PxDefaultSimulationFilterShader;
+PxFilterFlags PhysicsFilterShader(PxFilterObjectAttributes attributes0, PxFilterData filterData0, 
+								PxFilterObjectAttributes attributes1, PxFilterData filterData1,
+								PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
+{
+	// let triggers through
+	if(PxFilterObjectIsTrigger(attributes0) || PxFilterObjectIsTrigger(attributes1))
+	{
+		pairFlags = PxPairFlag::eTRIGGER_DEFAULT;
+		return PxFilterFlag::eDEFAULT;
+	}
+
+	// generate contacts for all that were not filtered above
+	pairFlags = PxPairFlag::eCONTACT_DEFAULT;
+
+	// trigger the contact callback for pairs (A,B) where 
+	// the filtermask of A contains the ID of B and vice versa.
+	if((filterData0.word0 & filterData1.word1) && (filterData1.word0 & filterData0.word1))
+	{
+		pairFlags |= PxPairFlag::eNOTIFY_TOUCH_FOUND;
+	}
+
+	return PxFilterFlag::eDEFAULT;
+}
+
+static physx::PxSimulationFilterShader g_default_filter_shader = PhysicsFilterShader;
 
 //-----------------------------------------------------------------------------
 PhysicsWorld::PhysicsWorld()
@@ -62,7 +94,6 @@ PhysicsWorld::PhysicsWorld()
 	, m_controllers_pool(default_allocator(), MAX_CONTROLLERS, sizeof(Controller), CE_ALIGNOF(Controller))
 	, m_triggers_pool(default_allocator(), MAX_TRIGGERS, sizeof(Trigger), CE_ALIGNOF(Trigger))
 {
-	// Create scene
 	PxSceneDesc scene_desc(device()->physx()->getTolerancesScale());
 	scene_desc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
 
@@ -74,39 +105,43 @@ PhysicsWorld::PhysicsWorld()
 		scene_desc.cpuDispatcher = m_cpu_dispatcher;
 	}
 
-	if(!scene_desc.filterShader)
-		scene_desc.filterShader = g_default_filter_shader;
-
+	// Set filter shader
+	scene_desc.filterShader = g_default_filter_shader;
+	// Enable active transformation
 	scene_desc.flags = PxSceneFlag::eENABLE_ACTIVETRANSFORMS;
+	// Enable collision detection
+	// scene_desc.flags |= PxSceneFlag::eENABLE_CCD;
+
+	// Set simulation event callback
+	m_callback = CE_NEW(default_allocator(), PhysicsCallback)();
+	scene_desc.simulationEventCallback = m_callback;
 	
+	// Create scene
 	m_scene = device()->physx()->createScene(scene_desc);
 
+	m_scene->setFlag(PxSceneFlag::eENABLE_KINEMATIC_STATIC_PAIRS, true);
+
 	// Create controller manager
 	m_controller_manager = PxCreateControllerManager(device()->physx()->getFoundation());
 	CE_ASSERT(m_controller_manager != NULL, "Failed to create PhysX controller manager");
 
-	PxTransform pose = PxTransform(PxVec3(0.0f, -3.75, 0.0f), PxQuat(PxHalfPi, PxVec3(0.0f, 0.0f, 1.0f)));
-	PxMaterial* mat = device()->physx()->createMaterial(0.5f, 0.5f, 1.0f);
-	PxRigidStatic* plane = device()->physx()->createRigidStatic(pose);
-	PxShape* shape = plane->createShape(PxPlaneGeometry(), *mat);
-	m_scene->addActor(*plane);
-
 	// FIXME FIXME FIXME
-	create_trigger(Vector3(.5, .5, .5), Vector3(5.0, -3.0, 3), Quaternion::IDENTITY);
+	//create_trigger(Vector3(.5, .5, .5), Vector3(5.0, -3.0, 3), Quaternion::IDENTITY);
 }
 
 //-----------------------------------------------------------------------------
 PhysicsWorld::~PhysicsWorld()
 {
+	CE_DELETE(default_allocator(), m_callback);
 	m_cpu_dispatcher->release();
 	m_controller_manager->release();
 	m_scene->release();
 }
 
 //-----------------------------------------------------------------------------
-ActorId	PhysicsWorld::create_actor(SceneGraph& sg, int32_t node, ActorType::Enum type)
+ActorId	PhysicsWorld::create_actor(const PhysicsResource* res, const uint32_t index, SceneGraph& sg, int32_t node)
 {
-	Actor* actor = CE_NEW(m_actors_pool, Actor)(m_scene, sg, node, type, Vector3::ZERO, Quaternion::IDENTITY);
+	Actor* actor = CE_NEW(m_actors_pool, Actor)(res, index, m_scene, sg, node, Vector3::ZERO, Quaternion::IDENTITY);
 	return m_actors.create(actor);
 }
 

+ 7 - 1
engine/physics/PhysicsWorld.h

@@ -34,9 +34,12 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "PxDefaultCpuDispatcher.h"
 #include "PxControllerManager.h"
 
+#include "Log.h"
+
 using physx::PxControllerManager;
 using physx::PxScene;
 using physx::PxDefaultCpuDispatcher;
+using physx::PxActor;
 
 #define MAX_ACTORS 1024
 #define MAX_CONTROLLERS 1024
@@ -46,12 +49,14 @@ namespace crown
 {
 
 struct PhysicsResource;
+struct PhysicsActor;
 struct Controller;
 struct Vector3;
 struct Actor;
 struct Trigger;
 struct Quaternion;
 class SceneGraph;
+class PhysicsCallback;
 
 //-----------------------------------------------------------------------------
 class PhysicsWorld
@@ -61,7 +66,7 @@ public:
 								PhysicsWorld();
 								~PhysicsWorld();
 
-	ActorId						create_actor(SceneGraph& sg, int32_t node, ActorType::Enum type);
+	ActorId						create_actor(const PhysicsResource* res, const uint32_t index, SceneGraph& sg, int32_t node);
 	void						destroy_actor(ActorId id);
 
 	ControllerId				create_controller(const PhysicsResource* pr, SceneGraph& sg, int32_t node);
@@ -84,6 +89,7 @@ public:
 	PxControllerManager*		m_controller_manager;
 	PxScene*					m_scene;
 	PxDefaultCpuDispatcher*		m_cpu_dispatcher;
+	PhysicsCallback*			m_callback;
 	
 	PoolAllocator				m_actors_pool;
 	IdArray<MAX_ACTORS, Actor*>	m_actors;

+ 60 - 9
engine/resource/PhysicsResource.cpp

@@ -50,10 +50,10 @@ static uint32_t shape_type_to_enum(const char* type)
 {
 	const StringId32 th = hash::murmur2_32(type, string::strlen(type));
 
-	if (string::strcmp("sphere", type) == 0) return PhysicsShapeType::SPHERE;
-	else if (string::strcmp("capsule", type) == 0) return PhysicsShapeType::CAPSULE;
-	else if (string::strcmp("box", type) == 0) return PhysicsShapeType::BOX;
-	else if (string::strcmp("plane", type) == 0) return PhysicsShapeType::PLANE;
+	if (string::strcmp("sphere", type) == 0) 		return PhysicsShapeType::SPHERE;
+	else if (string::strcmp("capsule", type) == 0) 	return PhysicsShapeType::CAPSULE;
+	else if (string::strcmp("box", type) == 0) 		return PhysicsShapeType::BOX;
+	else if (string::strcmp("plane", type) == 0) 	return PhysicsShapeType::PLANE;
 
 	CE_FATAL("Bad shape type");
 }
@@ -83,6 +83,10 @@ void parse_shape(JSONElement e, PhysicsShape& shape)
 {
 	JSONElement name = e.key("name");
 	JSONElement type = e.key("type");
+/*	JSONElement x = e.key("x");
+	JSONElement y = e.key("y");
+	JSONElement z = e.key("z");
+	JSONElement w = e.key("w");*/
 
 	DynamicString shape_name;
 	DynamicString shape_type;
@@ -91,6 +95,38 @@ void parse_shape(JSONElement e, PhysicsShape& shape)
 
 	shape.name = hash::murmur2_32(shape_name.c_str(), shape_name.length());
 	shape.type = shape_type_to_enum(shape_type.c_str());
+
+	switch (shape.type)
+	{
+		case PhysicsShapeType::SPHERE:
+		{
+			JSONElement radius = e.key("radius");
+			shape.data_0 = radius.float_value();
+			break;
+		}
+		case PhysicsShapeType::CAPSULE:
+		{
+			// TODO
+			break;
+		}
+		case PhysicsShapeType::BOX:
+		{
+			JSONElement half_x = e.key("half_x");
+			JSONElement half_y = e.key("half_y");
+			JSONElement half_z = e.key("half_z");
+
+			shape.data_0 = half_x.float_value();
+			shape.data_1 = half_y.float_value();
+			shape.data_2 = half_z.float_value();
+
+			break;
+		}
+		case PhysicsShapeType::PLANE:
+		{
+			// TODO
+			break;
+		}
+	}
 }
 
 //-----------------------------------------------------------------------------
@@ -111,6 +147,7 @@ void parse_actor(JSONElement e, PhysicsActor& actor, List<PhysicsShape>& actor_s
 	actor.name = hash::murmur2_32(actor_name.c_str(), actor_name.length());
 	actor.node = hash::murmur2_32(actor_node.c_str(), actor_node.length());
 	actor.type = actor_type_to_enum(actor_type.c_str());
+
 	actor.num_shapes = shapes.size();
 
 	for (uint32_t i = 0; i < actor.num_shapes; i++)
@@ -148,7 +185,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 	// Read actors
 	List<PhysicsActor> m_actors(default_allocator());
-	List<uint32_t> m_shape_index(default_allocator());
+	List<uint32_t> m_shapes_indices(default_allocator());
 	List<PhysicsShape> m_shapes(default_allocator());
 	JSONElement actors = root.key_or_nil("actors");
 	if (!actors.is_nil())
@@ -157,13 +194,13 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 		{
 			if (m_shapes.size() == 0)
 			{
-				m_shape_index.push_back(0);
+				m_shapes_indices.push_back(0);
 			}
 			else
 			{
-				m_shape_index.push_back(m_shapes.size() - 1);
+				m_shapes_indices.push_back(m_shapes.size());
 			}
-			
+
 			PhysicsActor a;
 			parse_actor(actors[i], a, m_shapes);
 			m_actors.push_back(a);
@@ -177,10 +214,14 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	h.version = 1;
 	h.num_controllers = m_has_controller ? 1 : 0;
 	h.num_actors = m_actors.size();
+	h.num_shapes_indices = m_shapes_indices.size();
+	h.num_shapes = m_shapes.size();
 
 	uint32_t offt = sizeof(PhysicsHeader);
 	h.controller_offset = offt; offt += sizeof(PhysicsController) * h.num_controllers;
-	h.actors_offset = offt;
+	h.actors_offset = offt; offt += sizeof(PhysicsActor) * h.num_actors;
+	h.shapes_indices_offset = offt; offt += sizeof(uint32_t) * h.num_shapes_indices;
+	h.shapes_offset = offt;
 
 	out_file->write((char*) &h, sizeof(PhysicsHeader));
 
@@ -193,6 +234,16 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	{
 		out_file->write((char*) m_actors.begin(), sizeof(PhysicsActor) * m_actors.size());
 	}
+
+	if (m_shapes_indices.size())
+	{
+		out_file->write((char*) m_shapes_indices.begin(), sizeof(uint32_t) * m_shapes_indices.size());
+	}
+
+	if (m_shapes.size())
+	{
+		out_file->write((char*) m_shapes.begin(), sizeof(PhysicsShape) * m_shapes.size());
+	}
 }
 
 } // namespace physics_resource

+ 41 - 0
engine/resource/PhysicsResource.h

@@ -42,6 +42,10 @@ struct PhysicsHeader
 	uint32_t controller_offset;
 	uint32_t num_actors;
 	uint32_t actors_offset;
+	uint32_t num_shapes_indices;
+	uint32_t shapes_indices_offset;
+	uint32_t num_shapes;
+	uint32_t shapes_offset;
 };
 
 struct PhysicsController
@@ -87,6 +91,11 @@ struct PhysicsShape
 {
 	StringId32 name;
 	uint32_t type;
+
+	float data_0;
+	float data_1;
+	float data_2;
+	float data_3;
 };
 
 //-----------------------------------------------------------------------------
@@ -153,6 +162,38 @@ struct PhysicsResource
 		return actor[i];
 	}
 
+	//-----------------------------------------------------------------------------
+	uint32_t num_shapes_indices() const
+	{
+		return ((PhysicsHeader*) this)->num_shapes_indices;
+	}
+
+	//-----------------------------------------------------------------------------
+	uint32_t shape_index(uint32_t i) const
+	{
+		CE_ASSERT(i < num_shapes_indices(), "Index out of bounds");
+
+		const PhysicsHeader* ph = (PhysicsHeader*) this;
+		uint32_t* index = (uint32_t*) (((char*) this) + ph->shapes_indices_offset);
+		return index[i];
+	}
+
+	//-----------------------------------------------------------------------------
+	uint32_t num_shapes() const
+	{
+		return ((PhysicsHeader*) this)->num_shapes;
+	}
+
+	//-----------------------------------------------------------------------------
+	PhysicsShape shape(uint32_t i) const
+	{
+		CE_ASSERT(i < num_shapes(), "Index out of bounds");
+
+		const PhysicsHeader* ph = (PhysicsHeader*) this;
+		PhysicsShape* shape = (PhysicsShape*) (((char*) this) + ph->shapes_offset);
+		return shape[i];
+	}
+
 private:
 
 	// Disable construction

+ 3 - 3
engine/world/Unit.cpp

@@ -206,9 +206,9 @@ void Unit::create_physics_objects()
 		// Create actors if any
 		for (uint32_t i = 0; i < pr->num_actors(); i++)
 		{
-			const PhysicsActor actor = pr->actor(i);
-			Log::i("node: %d", m_scene_graph.node(actor.node));
-			add_actor(actor.name, m_world.physics_world()->create_actor(m_scene_graph, m_scene_graph.node(actor.node), (ActorType::Enum)actor.type));
+			const PhysicsActor& actor = pr->actor(i);
+
+			add_actor(actor.name, m_world.physics_world()->create_actor(pr, i, m_scene_graph, m_scene_graph.node(actor.node)));
 		}
 	}
 }

+ 4 - 2
samples/03.bounce/box.physics

@@ -7,8 +7,10 @@
 			"shapes" : [
 				{
 					"name" : "shape_0",
-					"type" : "sphere",
-					"radius" : 0.5
+					"type" : "box",
+					"half_x" : 0.5,
+					"half_y" : 2.0,
+					"half_z" : 0.5
 				}
 			]
 		}

+ 5 - 3
samples/03.bounce/level.package

@@ -8,7 +8,8 @@
 		"camera",
 		"bounce",
 		"box",
-		"sun"
+		"sun",
+		"terrain"
 	],
 	"sprite" : [
 		"sprites/bounce",
@@ -16,14 +17,15 @@
 		"sprites/sun"
 	],
 	"sound" : [
-		"sounds/beep",
 		"sounds/gunshoot",
 		"sounds/footsteps",
 		"sounds/jump"
 	],
 	"physics" : [
 		"bounce",
-		"box"
+		"box",
+		"terrain",
+		"sun"
 	],
 	"material" : [
 		"bounce",

+ 40 - 23
samples/03.bounce/lua/game.lua

@@ -16,31 +16,38 @@ spd_x = 0
 spd_y = 0
 
 footsteps = nil
-speed = 3
-
-
-function spawn_terrain(x, y, dim)
-	for t = 0, dim, 2 do
-		World.spawn_unit(world, "box", Vector3(x + t, math.random(-3, 6) , 0))
+speed = 12
+
+function spawn_obstacle(pos)
+	if math.random(0, 10) >= 0 and math.random(0, 10) <= 3 then
+		World.spawn_unit(world, "box", Vector3(pos, -2, 0))
+	elseif math.random(0, 10) > 3 and math.random(0, 10) <=7 then
+		World.spawn_unit(world, "box", Vector3(pos, 6, 0))
+	else
+		World.spawn_unit(world, "box", Vector3(pos, 3, 0))
 	end
 end
 
-function spawn_suns(x, y, dim)
-	for t=0, dim, 7 do
-		World.spawn_unit(world, "sun", Vector3(x + t, math.random(-3, 6) , 0))
-	end	
+function spawn_obstacles(dim)
+	for t = 0, dim, 15 do
+		spawn_obstacle(t)
+	end
 end
 
 function update_player(world, unit, dt)
 
 	-- 3 m/s
-	speed = speed + 0.1 * dt;
+	-- speed = speed + 0.1 * dt;
 
 	if (Keyboard.button_pressed(Keyboard.w)) then up_pressed = true end
 	if (Keyboard.button_pressed(Keyboard.s)) then down_pressed = true end
+	if (Keyboard.button_pressed(Keyboard.a)) then left_pressed = true end
+	if (Keyboard.button_pressed(Keyboard.d)) then right_pressed = true end
 
 	if (Keyboard.button_released(Keyboard.w)) then up_pressed = false end
 	if (Keyboard.button_released(Keyboard.s)) then down_pressed = false end
+	if (Keyboard.button_released(Keyboard.a)) then left_pressed = 	false end
+	if (Keyboard.button_released(Keyboard.d)) then right_pressed = 	false end
 
 	if (Touch.pointer_down(1)) then up_pressed = true end
 	if (Touch.pointer_up(1)) then up_pressed = false end
@@ -51,9 +58,20 @@ function update_player(world, unit, dt)
 	if up_pressed then
 		spd_y = speed * dt
 	end
+	if right_pressed then
+		spd_x = speed * dt
+	end
+	if left_pressed then
+		spd_x = -speed * dt
+	end
 
-	spd_x = speed * dt
+	if not left_pressed and not right_pressed then
+		spd_x = 0
+	end
 
+	if not up_pressed and not down_pressed then
+		spd_y = 0
+	end
 	Controller.move(contr, Vector3(spd_x, spd_y, 0.0))
 
 	spd_y = spd_y - 0.5 * dt
@@ -87,11 +105,15 @@ function init()
 	camera_unit = World.spawn_unit(world, "camera")
 	camera = Unit.camera(camera_unit, "camera")
 
-	-- Spawn dragon
-	dragon = World.spawn_unit(world, "bounce")
+	-- Spawn terrain
+	terrain = World.spawn_unit(world, "terrain", Vector3(0, -3.75, 0), Quaternion(Vector3(0, 0, 1), 1.57))
+
+	-- Spawn bounce
+	bounce = World.spawn_unit(world, "bounce")
 
-	spawn_suns(15, -2, 400)
-	spawn_terrain(10, -3, 400)
+	sun = World.spawn_unit(world, "sun", Vector3(5, 3, 0))
+
+	spawn_obstacles(400)
 
 	Camera.set_near_clip_distance(camera, 0.01)
 	Camera.set_far_clip_distance(camera, 1000)
@@ -132,21 +154,16 @@ function frame(dt)
 	end
 
 	-- Update the player
-	update_player(world, dragon, dt)
+	update_player(world, bounce, dt)
 
 	-- Update the camera
-	update_camera(dragon, camera_unit, camera)
+	update_camera(bounce, camera_unit, camera)
 
 	-- Render world
 	Device.render_world(world, camera)
 end
 
 function shutdown()
-
-	--World.destroy_unit(world, dragon)
-	--World.destroy_unit(world, button)
-	--World.destroy_unit(world, camera_unit)
-	
 	ResourcePackage.unload(package)
 	Device.destroy_resource_package(package)
 	Device.destroy_world(world)

BIN
samples/03.bounce/sounds/beep.sound


BIN
samples/03.bounce/sounds/birds1.sound


BIN
samples/03.bounce/sounds/birds2.sound


BIN
samples/03.bounce/sounds/birds3.sound


BIN
samples/03.bounce/sounds/birds4.sound


BIN
samples/03.bounce/sounds/mario.sound


BIN
samples/03.bounce/sounds/mono.sound


BIN
samples/03.bounce/sounds/mono1.sound


BIN
samples/03.bounce/sounds/sweep.sound


BIN
samples/03.bounce/sounds/untrue.sound


+ 1 - 1
samples/03.bounce/sprites/box.sprite

@@ -6,7 +6,7 @@
 			"name" : "box",
 			"region" : [0.0, 0.0, 1.0, 1.0],
 			"offset" : [0.0, 0.0],
-			"scale" : [1.0, 1.0],
+			"scale" : [1.0, 4.0],
 			"rotated" : false
 		}
 	]

+ 16 - 0
samples/03.bounce/sun.physics

@@ -0,0 +1,16 @@
+{
+	"actors" : [
+		{
+			"name" : "actor_sun",
+			"node" : "root",
+			"type" : "dynamic_physical",
+			"shapes" : [
+				{
+					"name" : "shape_0",
+					"type" : "sphere",
+					"radius" : 0.5
+				}
+			]
+		}
+	]
+}

+ 19 - 0
samples/03.bounce/terrain.physics

@@ -0,0 +1,19 @@
+{
+	"actors" : [
+		{
+			"name" : "actor_terrain",
+			"node" : "root",
+			"type" : "static",
+			"shapes" : [
+				{
+					"name" : "shape_terrain",
+					"type" : "plane",
+					"nx" : 1.0,
+					"ny" : 0.0,
+					"nz" : 0.0,
+					"distance" : 0.0
+				}
+			]
+		}
+	]
+}

+ 10 - 0
samples/03.bounce/terrain.unit

@@ -0,0 +1,10 @@
+{
+	"nodes" : [
+		{
+			"name" : "root",
+			"parent" : null,
+			"position" : [0, -3.5, 0],
+			"rotation" : [0, 0, 1, 1.57]
+		}
+	]
+}