Browse Source

Adding friction and elasticity support in bodies

Panagiotis Christopoulos Charitos 10 years ago
parent
commit
1568525b30

+ 2 - 1
include/anki/physics/Common.h

@@ -46,7 +46,8 @@ enum class PhysicsMaterialBit: U16
 	STATIC_GEOMETRY = 1 << 0,
 	DYNAMIC_GEOMETRY = 1 << 1,
 	RAGDOLL = 1 << 2,
-	PARTICLES = 1 << 3
+	PARTICLES = 1 << 3,
+	ALL = MAX_U16
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(PhysicsMaterialBit, inline)
 

+ 28 - 0
include/anki/physics/PhysicsBody.h

@@ -45,6 +45,31 @@ public:
 
 	void setTransform(const Transform& trf);
 
+	F32 getFriction() const
+	{
+		return m_friction;
+	}
+
+	void setFriction(F32 friction)
+	{
+		m_friction = friction;
+	}
+
+	F32 getElasticity() const
+	{
+		return m_elasticity;
+	}
+
+	void setElasticity(F32 elasticity)
+	{
+		m_elasticity = elasticity;
+	}
+
+	void setMaterialsThatCollide(PhysicsMaterialBit bits)
+	{
+		m_materialBits = bits;
+	}
+
 	static Bool classof(const PhysicsObject& c)
 	{
 		return c.getType() == Type::BODY;
@@ -54,6 +79,9 @@ private:
 	NewtonBody* m_body = nullptr;
 	void* m_sceneCollisionProxy = nullptr;
 	Transform m_trf = Transform::getIdentity();
+	F32 m_friction = 0.03;
+	F32 m_elasticity = 0.1;
+	PhysicsMaterialBit m_materialBits = PhysicsMaterialBit::ALL;
 	Bool8 m_updated = true;
 
 	/// Newton callback.

+ 18 - 0
include/anki/physics/PhysicsWorld.h

@@ -98,6 +98,24 @@ private:
 	{}
 
 	void registerObject(PhysicsObject* ptr);
+
+	static int onAabbOverlapCallback(
+		const NewtonMaterial* const material,
+		const NewtonBody* const body0,
+		const NewtonBody* const body1,
+		int threadIndex)
+	{
+		(void)material;
+		(void)body0;
+		(void)body1;
+		(void)threadIndex;
+		return 1;
+	}
+
+	static void onContactCallback(
+		const NewtonJoint* contactJoint,
+		F32 timestep,
+		int threadIndex);
 };
 
 //==============================================================================

+ 5 - 0
include/anki/scene/BodyComponent.h

@@ -41,6 +41,11 @@ public:
 		m_body->setTransform(trf);
 	}
 
+	PhysicsBodyPtr getPhysicsBody() const
+	{
+		return m_body;
+	}
+
 	/// @name SceneComponent overrides
 	/// @{
 	ANKI_USE_RESULT Error update(SceneNode&, F32, F32, Bool& updated) override

+ 4 - 0
src/physics/PhysicsBody.cpp

@@ -70,6 +70,10 @@ Error PhysicsBody::create(const Initializer& init)
 		return ErrorCode::FUNCTION_FAILED;
 	}
 
+	// Material
+	NewtonBodySetMaterialGroupID(
+		m_body, NewtonMaterialGetDefaultGroupID(m_world->_getNewtonWorld()));
+
 	// User data & callbacks
 	NewtonBodySetUserData(m_body, this);
 	NewtonBodySetTransformCallback(m_body, onTransformCallback);

+ 2 - 0
src/physics/PhysicsPlayerController.cpp

@@ -234,6 +234,8 @@ Error PhysicsPlayerController::create(const Initializer& init)
 
 	NewtonBodySetUserData(m_body, this);
 	NewtonBodySetTransformCallback(m_body, onTransformCallback);
+	NewtonBodySetMaterialGroupID(
+		m_body, NewtonMaterialGetDefaultGroupID(m_world->_getNewtonWorld()));
 
 	// Players must have weight, otherwise they are infinitely strong when 
 	// they collide

+ 53 - 0
src/physics/PhysicsWorld.cpp

@@ -6,6 +6,7 @@
 #include "anki/physics/PhysicsWorld.h"
 #include "anki/physics/PhysicsPlayerController.h"
 #include "anki/physics/PhysicsCollisionShape.h"
+#include "anki/physics/PhysicsBody.h"
 
 namespace anki {
 
@@ -82,6 +83,12 @@ Error PhysicsWorld::create(AllocAlignedCallback allocCb, void* allocCbData)
 	NewtonWorldAddPostListener(m_world, "world", this, postUpdateCallback,
 		destroyCallback);
 
+	// Set callbacks
+	I defaultMaterialID = NewtonMaterialGetDefaultGroupID(m_world);
+	NewtonMaterialSetCollisionCallback(
+		m_world, defaultMaterialID, defaultMaterialID, nullptr,
+		onAabbOverlapCallback, onContactCallback);
+
 	return err;
 }
 
@@ -162,4 +169,50 @@ void PhysicsWorld::registerObject(PhysicsObject* ptr)
 	}
 }
 
+//==============================================================================
+void PhysicsWorld::onContactCallback(
+	const NewtonJoint* contactJoint,
+	F32 timestep,
+	int threadIndex)
+{
+	const NewtonBody* body0 = NewtonJointGetBody0(contactJoint);
+	const NewtonBody* body1 = NewtonJointGetBody1(contactJoint);
+
+	void* userData = NewtonBodyGetUserData(body0);
+	if(!userData)
+	{
+		return;
+	}
+
+	F32 friction0 = static_cast<PhysicsBody*>(userData)->getFriction();
+	F32 elasticity0 = static_cast<PhysicsBody*>(userData)->getElasticity();
+
+	userData = NewtonBodyGetUserData(body1);
+	if(!userData)
+	{
+		return;
+	}
+
+	F32 friction1 = static_cast<PhysicsBody*>(userData)->getFriction();
+	F32 elasticity1 = static_cast<PhysicsBody*>(userData)->getElasticity();
+
+	F32 friction = friction0 + friction1;
+	F32 elasticity = elasticity0 + elasticity1;
+
+	void* contact = NewtonContactJointGetFirstContact(contactJoint);
+	while(contact)
+	{
+		NewtonMaterial* material = NewtonContactGetMaterial(contact);
+
+		NewtonMaterialSetContactFrictionCoef(
+			material, friction + 0.1, friction, 0);
+		NewtonMaterialSetContactFrictionCoef(
+			material, friction + 0.1, friction, 1);
+
+		NewtonMaterialSetContactElasticity(material, elasticity);
+
+		contact = NewtonContactJointGetNextContact(contactJoint, contact);
+	}
+}
+
 } // end namespace anki

+ 17 - 3
testapp/Main.cpp

@@ -41,7 +41,7 @@ App* app;
 ModelNode* horse;
 PerspectiveCamera* cam;
 
-#define NO_PLAYER 1
+#define NO_PLAYER 0
 
 
 //==============================================================================
@@ -260,7 +260,7 @@ Error init()
 	{
 		ScriptResourcePointer script;
 
-		err = script.load("maps/techdemo/scene.lua", &resources);
+		err = script.load("maps/adis/scene.lua", &resources);
 		if(err) return err;
 
 		err = app->getScriptManager().evalString(script->getSource());
@@ -386,7 +386,21 @@ Error mainLoopExtra(App& app, void*, Bool& quit)
 
 		scene.newSceneNode<ModelNode>(CString(), horse, 
 			"models/crate0/crate0.ankimdl");
-		BodyComponent* bodyc = horse->tryGetComponent<BodyComponent>();
+	
+		horse->getComponent<MoveComponent>().enableBits(
+			MoveComponent::Flag::IGNORE_LOCAL_TRANSFORM);
+
+		BodyNode* bnode;
+		scene.newSceneNode<BodyNode>(CString(), bnode,
+			"models/crate0/crate0.ankicl");
+
+		bnode->addChild(horse);
+
+		BodyComponent* bodyc = bnode->tryGetComponent<BodyComponent>();
+
+		PhysicsBodyPtr body = bodyc->getPhysicsBody();
+		body->setElasticity(0.001);
+		body->setFriction(1.01);
 
 		Vec4 pos(randRange(3, 15), 10, randRange(-6, 8), 0);