Przeglądaj źródła

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

Daniele Bartolini 12 lat temu
rodzic
commit
236342d1a8

+ 15 - 0
engine/core/json/JSONParser.cpp

@@ -314,6 +314,21 @@ void JSONElement::array_value(List<float>& array) const
 	}
 }
 
+//--------------------------------------------------------------------------
+void JSONElement::array_value(Vector<DynamicString>& array) const
+{
+	List<const char*> temp(default_allocator());
+
+	json::parse_array(m_at, temp);
+
+	for (uint32_t i = 0; i < temp.size(); i++)
+	{
+		DynamicString str;
+		json::parse_string(temp[i], str);
+		array.push_back(str);
+	}
+}
+
 //--------------------------------------------------------------------------
 bool JSONElement::is_nil() const
 {

+ 4 - 0
engine/core/json/JSONParser.h

@@ -28,6 +28,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "Types.h"
 #include "List.h"
+#include "Vector.h"
 
 namespace crown
 {
@@ -144,6 +145,9 @@ public:
 	/// @copydoc JSONElement::array_value(List<bool>&)
 	void				array_value(List<float>& array) const;
 
+	/// @copydoc JSONElement::array_value(List<bool>&)
+	void				array_value(Vector<DynamicString>& array) const;
+
 private:
 
 	const char*			m_at;

+ 15 - 52
engine/physics/Actor.cpp

@@ -63,36 +63,6 @@ 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(const PhysicsResource* res, uint32_t i, PxScene* scene, SceneGraph& sg, int32_t node, const Vector3& pos, const Quaternion& rot)
 	: m_resource(res)
@@ -124,6 +94,15 @@ Actor::Actor(const PhysicsResource* res, uint32_t i, PxScene* scene, SceneGraph&
 				static_cast<PxRigidDynamic*>(m_actor)->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true);
 			}
 			break;
+
+			PxRigidBodyExt::setMassAndUpdateInertia(*static_cast<PxRigidDynamic*>(m_actor), 500.0f);
+
+			PxD6Joint* joint = PxD6JointCreate(*device()->physx(), m_actor, PxTransform(pose), NULL, PxTransform(pose));
+			joint->setMotion(PxD6Axis::eX, PxD6Motion::eFREE);
+			joint->setMotion(PxD6Axis::eY, PxD6Motion::eFREE);
+			//joint->setMotion(PxD6Axis::eZ, PxD6Motion::eFREE);
+			//joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
+			joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
 		}
 		default:
 		{
@@ -133,7 +112,9 @@ Actor::Actor(const PhysicsResource* res, uint32_t i, PxScene* scene, SceneGraph&
 	}
 
 	m_actor->userData = this;
-	m_mat = device()->physx()->createMaterial(0.5f, 0.5f, 1.0f);
+
+	// Creates material
+	m_mat = device()->physx()->createMaterial(a.static_friction, a.dynamic_friction, a.restitution);
 
 	// Creates shapes
 	uint32_t index = m_resource->shape_index(m_index);
@@ -167,21 +148,7 @@ Actor::Actor(const PhysicsResource* res, uint32_t i, PxScene* scene, SceneGraph&
 		index++;
 	}
 
-	if (a.type == ActorType::DYNAMIC_PHYSICAL || a.type == ActorType::DYNAMIC_KINEMATIC)
-	{
-		PxRigidBodyExt::setMassAndUpdateInertia(*static_cast<PxRigidDynamic*>(m_actor), 500.0f);
-
-		PxD6Joint* joint = PxD6JointCreate(*device()->physx(), m_actor, PxTransform(pose), NULL, PxTransform(pose));
-		joint->setMotion(PxD6Axis::eX, PxD6Motion::eFREE);
-		joint->setMotion(PxD6Axis::eY, PxD6Motion::eFREE);
-		//joint->setMotion(PxD6Axis::eZ, PxD6Motion::eFREE);
-		//joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
-		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);
 }
 
@@ -198,17 +165,13 @@ Actor::~Actor()
 //-----------------------------------------------------------------------------
 void Actor::create_sphere(const Vector3& position, float radius)
 {
-	PxShape* shape = m_actor->createShape(PxSphereGeometry(radius), *m_mat);
-	// shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
-	// shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);
+	/*PxShape* shape = */m_actor->createShape(PxSphereGeometry(radius), *m_mat);
 }
 
 //-----------------------------------------------------------------------------
-void Actor::create_box(const Vector3& position, float a, float b, float c)
+void Actor::create_box(const Vector3& position, float half_x, float half_y, float half_z)
 {
-	PxShape* shape = m_actor->createShape(PxBoxGeometry(a, b, c), *m_mat);
-	// shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
-	// shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);
+	/*PxShape* shape = */m_actor->createShape(PxBoxGeometry(half_x, half_y, half_z), *m_mat);
 }
 
 //-----------------------------------------------------------------------------

+ 4 - 0
engine/physics/Controller.cpp

@@ -30,6 +30,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "PhysicsResource.h"
 #include "SceneGraph.h"
 #include "Vector3.h"
+#include "PhysicsCallback.h"
 
 #include "PxCapsuleController.h"
 using physx::PxCapsuleClimbingMode;
@@ -68,6 +69,8 @@ Controller::Controller(const PhysicsResource* pr, SceneGraph& sg, int32_t node,
 	desc.position = PxExtendedVec3(0, 0, 0);
 
 	CE_ASSERT(desc.isValid(), "Capsule is not valid");
+	m_callback = CE_NEW(default_allocator(), PhysicsControllerCallback)();
+	desc.callback = m_callback;
 
 	m_controller = manager->createController(*device()->physx(), scene, desc);
 	CE_ASSERT(m_controller, "Failed to create controller");
@@ -76,6 +79,7 @@ Controller::Controller(const PhysicsResource* pr, SceneGraph& sg, int32_t node,
 //-----------------------------------------------------------------------------
 Controller::~Controller()
 {
+	CE_DELETE(default_allocator(), m_callback);
 	m_controller->release();
 }
 

+ 5 - 0
engine/physics/Controller.h

@@ -24,6 +24,8 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
+#pragma once
+
 #include "PxController.h"
 #include "PxControllerManager.h"
 
@@ -38,6 +40,7 @@ namespace crown
 struct PhysicsResource;
 struct Vector3;
 class SceneGraph;
+class PhysicsControllerCallback;
 
 struct Controller
 {
@@ -63,6 +66,8 @@ private:
 	PxControllerManager*	m_manager;
 	PxController*			m_controller;
 	PxU32					m_flags;
+
+	PhysicsControllerCallback* m_callback;
 };
 
 } // namespace crown

+ 31 - 2
engine/physics/PhysicsCallback.h

@@ -27,24 +27,31 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "PxSimulationEventCallback.h"
+#include "PxController.h"
 
 using physx::PxSimulationEventCallback;
 using physx::PxContactPairHeader;
 using physx::PxContactPair;
 using physx::PxConstraintInfo;
 using physx::PxTriggerPair;
+using physx::PxActor;
 using physx::PxU32;
 
+using physx::PxUserControllerHitReport;
+using physx::PxControllerShapeHit;
+using physx::PxControllersHit;
+using physx::PxControllerObstacleHit;
+
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-class PhysicsCallback : public PxSimulationEventCallback
+class PhysicsSimulationCallback : public PxSimulationEventCallback
 {
 public:
 
 	//-----------------------------------------------------------------------------
-	PhysicsCallback() {}
+	PhysicsSimulationCallback() {}
 
 	//-----------------------------------------------------------------------------
 	void onConstraintBreak(PxConstraintInfo* /*constraints*/, PxU32 /*count*/)
@@ -77,4 +84,26 @@ public:
 	}
 };
 
+//-----------------------------------------------------------------------------
+class PhysicsControllerCallback : public PxUserControllerHitReport
+{
+	//-----------------------------------------------------------------------------
+	void onShapeHit(const PxControllerShapeHit& hit)
+	{
+		Log::i("SHAPE HIT");
+	}
+
+	//-----------------------------------------------------------------------------
+	void onControllerHit(const PxControllersHit& hit)
+	{
+		Log::i("CONTROLLER HIT");
+	}
+
+	//-----------------------------------------------------------------------------
+	void onObstacleHit(const PxControllerObstacleHit& hit)
+	{
+		Log::i("OBSTACLE HIT");
+	}
+};
+
 } // namespace crown

+ 26 - 7
engine/physics/PhysicsWorld.cpp

@@ -109,13 +109,11 @@ PhysicsWorld::PhysicsWorld()
 	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)();
+	m_callback = CE_NEW(default_allocator(), PhysicsSimulationCallback)();
 	scene_desc.simulationEventCallback = m_callback;
-	
+
 	// Create scene
 	m_scene = device()->physx()->createScene(scene_desc);
 
@@ -124,9 +122,6 @@ PhysicsWorld::PhysicsWorld()
 	// Create controller manager
 	m_controller_manager = PxCreateControllerManager(device()->physx()->getFoundation());
 	CE_ASSERT(m_controller_manager != NULL, "Failed to create PhysX controller manager");
-
-	// FIXME FIXME FIXME
-	//create_trigger(Vector3(.5, .5, .5), Vector3(5.0, -3.0, 3), Quaternion::IDENTITY);
 }
 
 //-----------------------------------------------------------------------------
@@ -219,6 +214,30 @@ void PhysicsWorld::set_gravity(const Vector3& g)
 	m_scene->setGravity(PxVec3(g.x, g.y, g.z));
 }
 
+//-----------------------------------------------------------------------------
+void PhysicsWorld::set_filtering(ActorId id, uint32_t group, uint32_t mask)
+{
+	Actor* actor_instance = lookup_actor(id);
+	PxRigidActor* actor = actor_instance->m_actor;
+
+	PxFilterData filter_data;
+	filter_data.word0 = (PxU32) group;	// word0 = own ID
+	filter_data.word1 = (PxU32) mask;	// 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(filter_data);
+	}
+
+	default_allocator().deallocate(shapes);
+}
+
 //-----------------------------------------------------------------------------
 void PhysicsWorld::update(float dt)
 {

+ 46 - 3
engine/physics/PhysicsWorld.h

@@ -48,6 +48,7 @@ using physx::PxActor;
 namespace crown
 {
 
+//-----------------------------------------------------------------------------
 struct PhysicsResource;
 struct PhysicsActor;
 struct Controller;
@@ -56,7 +57,47 @@ struct Actor;
 struct Trigger;
 struct Quaternion;
 class SceneGraph;
-class PhysicsCallback;
+class PhysicsSimulationCallback;
+
+//-----------------------------------------------------------------------------
+struct FilterGroup
+{
+	enum Enum
+	{
+		GROUP_0		= (1<<0),
+		GROUP_1		= (1<<1),
+		GROUP_2		= (1<<2),
+		GROUP_3		= (1<<3),
+		GROUP_4		= (1<<4),
+		GROUP_5		= (1<<5),
+		GROUP_6		= (1<<6),
+		GROUP_7		= (1<<7),
+		GROUP_8		= (1<<8),
+		GROUP_9		= (1<<9),
+		GROUP_10	= (1<<10),
+		GROUP_11	= (1<<11),
+		GROUP_12	= (1<<12),
+		GROUP_13	= (1<<13),
+		GROUP_14	= (1<<14),
+		GROUP_15	= (1<<15),
+		GROUP_16	= (1<<16),
+		GROUP_17	= (1<<17),
+		GROUP_18	= (1<<18),
+		GROUP_19	= (1<<19),
+		GROUP_20	= (1<<20),
+		GROUP_21	= (1<<21),
+		GROUP_22	= (1<<22),
+		GROUP_23	= (1<<23),
+		GROUP_24	= (1<<24),
+		GROUP_25	= (1<<25),
+		GROUP_26	= (1<<26),
+		GROUP_27	= (1<<27),
+		GROUP_28	= (1<<28),
+		GROUP_29	= (1<<29),
+		GROUP_30	= (1<<30),
+		GROUP_31	= (1<<31)
+	};
+};
 
 //-----------------------------------------------------------------------------
 class PhysicsWorld
@@ -82,6 +123,8 @@ public:
 	Vector3						gravity() const;
 	void						set_gravity(const Vector3& g);
 
+	void						set_filtering(ActorId actor, uint32_t group, uint32_t mask);
+
 	void						update(float dt);
 
 public:
@@ -89,8 +132,8 @@ public:
 	PxControllerManager*		m_controller_manager;
 	PxScene*					m_scene;
 	PxDefaultCpuDispatcher*		m_cpu_dispatcher;
-	PhysicsCallback*			m_callback;
-	
+	PhysicsSimulationCallback*	m_callback;
+
 	PoolAllocator				m_actors_pool;
 	IdArray<MAX_ACTORS, Actor*>	m_actors;
 

+ 55 - 6
engine/resource/PhysicsResource.cpp

@@ -46,10 +46,46 @@ static uint32_t actor_type_to_enum(const char* type)
 	CE_FATAL("Bad actor type");
 }
 
-static uint32_t shape_type_to_enum(const char* type)
+static uint32_t actor_group_to_enum(const char* group)
 {
-	const StringId32 th = hash::murmur2_32(type, string::strlen(type));
+	if (string::strcmp("GROUP_0", group) == 0) 	return PhysicsActorGroup::GROUP_0;
+	if (string::strcmp("GROUP_1", group) == 0) 	return PhysicsActorGroup::GROUP_1;
+	if (string::strcmp("GROUP_2", group) == 0) 	return PhysicsActorGroup::GROUP_2;
+	if (string::strcmp("GROUP_3", group) == 0) 	return PhysicsActorGroup::GROUP_3;
+	if (string::strcmp("GROUP_4", group) == 0) 	return PhysicsActorGroup::GROUP_4;
+	if (string::strcmp("GROUP_5", group) == 0) 	return PhysicsActorGroup::GROUP_5;
+	if (string::strcmp("GROUP_6", group) == 0) 	return PhysicsActorGroup::GROUP_6;
+	if (string::strcmp("GROUP_7", group) == 0) 	return PhysicsActorGroup::GROUP_7;
+	if (string::strcmp("GROUP_8", group) == 0) 	return PhysicsActorGroup::GROUP_8;
+	if (string::strcmp("GROUP_9", group) == 0) 	return PhysicsActorGroup::GROUP_9;
+	if (string::strcmp("GROUP_10", group) == 0) return PhysicsActorGroup::GROUP_10;
+	if (string::strcmp("GROUP_11", group) == 0) return PhysicsActorGroup::GROUP_11;
+	if (string::strcmp("GROUP_12", group) == 0) return PhysicsActorGroup::GROUP_12;
+	if (string::strcmp("GROUP_13", group) == 0) return PhysicsActorGroup::GROUP_13;
+	if (string::strcmp("GROUP_14", group) == 0) return PhysicsActorGroup::GROUP_14;
+	if (string::strcmp("GROUP_15", group) == 0) return PhysicsActorGroup::GROUP_15;
+	if (string::strcmp("GROUP_16", group) == 0) return PhysicsActorGroup::GROUP_16;
+	if (string::strcmp("GROUP_17", group) == 0) return PhysicsActorGroup::GROUP_17;
+	if (string::strcmp("GROUP_18", group) == 0) return PhysicsActorGroup::GROUP_18;
+	if (string::strcmp("GROUP_19", group) == 0) return PhysicsActorGroup::GROUP_19;
+	if (string::strcmp("GROUP_20", group) == 0) return PhysicsActorGroup::GROUP_20;
+	if (string::strcmp("GROUP_21", group) == 0) return PhysicsActorGroup::GROUP_21;
+	if (string::strcmp("GROUP_22", group) == 0) return PhysicsActorGroup::GROUP_22;
+	if (string::strcmp("GROUP_23", group) == 0) return PhysicsActorGroup::GROUP_23;
+	if (string::strcmp("GROUP_24", group) == 0) return PhysicsActorGroup::GROUP_24;
+	if (string::strcmp("GROUP_25", group) == 0) return PhysicsActorGroup::GROUP_25;
+	if (string::strcmp("GROUP_26", group) == 0) return PhysicsActorGroup::GROUP_26;
+	if (string::strcmp("GROUP_27", group) == 0) return PhysicsActorGroup::GROUP_27;
+	if (string::strcmp("GROUP_28", group) == 0) return PhysicsActorGroup::GROUP_28;
+	if (string::strcmp("GROUP_29", group) == 0) return PhysicsActorGroup::GROUP_29;
+	if (string::strcmp("GROUP_30", group) == 0) return PhysicsActorGroup::GROUP_30;
+	if (string::strcmp("GROUP_31", group) == 0) return PhysicsActorGroup::GROUP_31;
+
+	CE_FATAL("Bad actor group");
+}
 
+static uint32_t shape_type_to_enum(const char* 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;
@@ -83,10 +119,6 @@ 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;
@@ -135,18 +167,35 @@ void parse_actor(JSONElement e, PhysicsActor& actor, List<PhysicsShape>& actor_s
 	JSONElement name = e.key("name");
 	JSONElement node = e.key("node");
 	JSONElement type = e.key("type");
+	JSONElement material = e.key("material");
+	JSONElement group = e.key("group");
+	JSONElement mask = e.key("mask");
 	JSONElement shapes = e.key("shapes");
 
 	DynamicString actor_name;
 	DynamicString actor_node;
 	DynamicString actor_type;
+	List<float> actor_material(default_allocator());
+	DynamicString actor_group;
+	Vector<DynamicString> actor_mask(default_allocator());
 	name.string_value(actor_name);
 	node.string_value(actor_node);
 	type.string_value(actor_type);
+	material.array_value(actor_material);
+	group.string_value(actor_group);
+	mask.array_value(actor_mask);
 
 	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.static_friction = actor_material[0];
+	actor.dynamic_friction = actor_material[1];
+	actor.restitution = actor_material[2];
+	actor.group = actor_group_to_enum(actor_group.c_str());
+	for (uint32_t i = 0; i < actor_mask.size(); i++)
+	{
+		actor.mask |= actor_group_to_enum(actor_mask[i].c_str());
+	}
 
 	actor.num_shapes = shapes.size();
 

+ 51 - 0
engine/resource/PhysicsResource.h

@@ -35,6 +35,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
+//-----------------------------------------------------------------------------
 struct PhysicsHeader
 {
 	uint32_t version;
@@ -48,6 +49,7 @@ struct PhysicsHeader
 	uint32_t shapes_offset;
 };
 
+//-----------------------------------------------------------------------------
 struct PhysicsController
 {
 	StringId32 name;
@@ -58,6 +60,7 @@ struct PhysicsController
 	float contact_offset;	// Skin around the object within which contacts will be generated. Use it to avoid numerical precision issues.
 };
 
+//-----------------------------------------------------------------------------
 struct PhysicsActorType
 {
 	enum Enum
@@ -68,14 +71,61 @@ struct PhysicsActorType
 	};
 };
 
+//-----------------------------------------------------------------------------
+struct PhysicsActorGroup
+{
+	enum Enum
+	{
+		GROUP_0		= (1<<0),
+		GROUP_1		= (1<<1),
+		GROUP_2		= (1<<2),
+		GROUP_3		= (1<<3),
+		GROUP_4		= (1<<4),
+		GROUP_5		= (1<<5),
+		GROUP_6		= (1<<6),
+		GROUP_7		= (1<<7),
+		GROUP_8		= (1<<8),
+		GROUP_9		= (1<<9),
+		GROUP_10	= (1<<10),
+		GROUP_11	= (1<<11),
+		GROUP_12	= (1<<12),
+		GROUP_13	= (1<<13),
+		GROUP_14	= (1<<14),
+		GROUP_15	= (1<<15),
+		GROUP_16	= (1<<16),
+		GROUP_17	= (1<<17),
+		GROUP_18	= (1<<18),
+		GROUP_19	= (1<<19),
+		GROUP_20	= (1<<20),
+		GROUP_21	= (1<<21),
+		GROUP_22	= (1<<22),
+		GROUP_23	= (1<<23),
+		GROUP_24	= (1<<24),
+		GROUP_25	= (1<<25),
+		GROUP_26	= (1<<26),
+		GROUP_27	= (1<<27),
+		GROUP_28	= (1<<28),
+		GROUP_29	= (1<<29),
+		GROUP_30	= (1<<30),
+		GROUP_31	= (1<<31)
+	};
+};
+
+//-----------------------------------------------------------------------------
 struct PhysicsActor
 {
 	StringId32 name;
 	StringId32 node;
 	uint32_t type;
+	uint32_t group;
+	uint32_t mask;
+	float static_friction;
+	float dynamic_friction;
+	float restitution;
 	uint32_t num_shapes;
 };
 
+//-----------------------------------------------------------------------------
 struct PhysicsShapeType
 {
 	enum Enum
@@ -87,6 +137,7 @@ struct PhysicsShapeType
 	};
 };
 
+//-----------------------------------------------------------------------------
 struct PhysicsShape
 {
 	StringId32 name;

+ 4 - 1
engine/world/Unit.cpp

@@ -208,7 +208,10 @@ void Unit::create_physics_objects()
 		{
 			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)));
+			ActorId id = m_world.physics_world()->create_actor(pr, i, m_scene_graph, m_scene_graph.node(actor.node));
+			m_world.physics_world()->set_filtering(id, actor.group, actor.mask);
+			
+			add_actor(actor.name, id);
 		}
 	}
 }

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

@@ -4,6 +4,10 @@
 			"name" : "actor_0",
 			"node" : "root",
 			"type" : "static",
+			"material" : [0.5, 0.5, 0.5],
+			"group" : "GROUP_1",
+			"mask" : ["GROUP_0"],
+
 			"shapes" : [
 				{
 					"name" : "shape_0",

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

@@ -4,6 +4,9 @@
 			"name" : "actor_sun",
 			"node" : "root",
 			"type" : "dynamic_physical",
+			"material" : [0.5, 0.5, 1.0],
+			"group" : "GROUP_0",
+			"mask" : ["GROUP_0", "GROUP_1"],
 			"shapes" : [
 				{
 					"name" : "shape_0",

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

@@ -4,6 +4,9 @@
 			"name" : "actor_terrain",
 			"node" : "root",
 			"type" : "static",
+			"material" : [0.5, 0.5, 1.0],
+			"group" : "GROUP_1",
+			"mask" : ["GROUP_0"],
 			"shapes" : [
 				{
 					"name" : "shape_terrain",