Browse Source

Added Base/Attachment Logic, works with Kinematic & Ghost.

legacy
Benjamin ‘Touky’ Huet touky 12 years ago
parent
commit
7334bb2ec1
6 changed files with 167 additions and 310 deletions
  1. +33
    -240
      test/BtPhysTest.cpp
  2. +1
    -19
      test/BtPhysTest.h
  3. +59
    -44
      test/PhysicObject.h
  4. +2
    -2
      test/Physics/Include/EasyCharacterController.h
  5. +45
    -2
      test/Physics/Include/EasyPhysics.h
  6. +27
    -3
      test/Physics/Src/EasyPhysics.cpp

+ 33
- 240
test/BtPhysTest.cpp View File

@@ -109,7 +109,7 @@ BtPhysTest::BtPhysTest(bool editor)

if (USE_PLATFORM)
{
quat NewRotation = quat::fromeuler_xyz(5.f, 0.f, 0.f);
quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
vec3 NewPosition = pos_offset + vec3(5.0f, -25.0f, -15.0f);

PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
@@ -119,8 +119,32 @@ BtPhysTest::BtPhysTest(bool editor)

NewPosition = pos_offset + vec3(-20.0f, -25.0f, 5.0f);

NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
PhysicsObject* BasePhyobj = NewPhyobj;

m_platform_list << NewPhyobj;
Ticker::Ref(NewPhyobj);

NewRotation = quat::fromeuler_xyz(0.f, 0.f, 90.f);
NewPosition = pos_offset + vec3(-25.0f, -25.0f, 5.0f);

NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);

NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), true, true);
m_platform_list << NewPhyobj;
Ticker::Ref(NewPhyobj);

NewPosition += vec3(-0.0f, .0f, .0f);
NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);

NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), true, false);
m_platform_list << NewPhyobj;
Ticker::Ref(NewPhyobj);

NewPosition += vec3(-2.0f, .0f, .0f);
NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);

NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), false, false);
m_platform_list << NewPhyobj;
Ticker::Ref(NewPhyobj);
}
@@ -128,7 +152,7 @@ BtPhysTest::BtPhysTest(bool editor)
if (USE_CHARACTER)
{
quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
vec3 NewPosition = pos_offset + vec3(.0f, 20.0f, .0f);
vec3 NewPosition = pos_offset + vec3(-15.0f, 20.0f, .0f);

PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 2);

@@ -180,151 +204,6 @@ BtPhysTest::BtPhysTest(bool editor)
}
}
}

#if 0
//init Physics
{
m_bt_ccd_mode = USE_CCD;

//collision configuration contains default setup for memory, collision setup
m_bt_collision_config = new btDefaultCollisionConfiguration();

//use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
m_bt_dispatcher = new btCollisionDispatcher(m_bt_collision_config);
m_bt_dispatcher->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE,
BOX_SHAPE_PROXYTYPE,
m_bt_collision_config->getCollisionAlgorithmCreateFunc(CONVEX_SHAPE_PROXYTYPE,
CONVEX_SHAPE_PROXYTYPE));

m_bt_broadphase = new btDbvtBroadphase();

///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
m_bt_solver = new btSequentialImpulseConstraintSolver;

m_bt_world = new btDiscreteDynamicsWorld(m_bt_dispatcher, m_bt_broadphase, m_bt_solver, m_bt_collision_config);
//m_bt_world->setDebugDrawer(&sDebugDrawer);
m_bt_world->getSolverInfo().m_splitImpulse = true;
m_bt_world->getSolverInfo().m_numIterations = 20;

m_bt_world->getDispatchInfo().m_useContinuous = (m_bt_ccd_mode == USE_CCD);
m_bt_world->setGravity(btVector3(0,-10,0));

///create a few basic rigid bodies
btBoxShape* box = new btBoxShape(btVector3(btScalar(110.),btScalar(1.),btScalar(110.)));
btCollisionShape* groundShape = box;
m_bt_collision_shapes << groundShape;
m_ground_mesh.Compile("[sc#ddd afcb220 2 220 -1]");

//m_bt_collision_shapes << new btCylinderShape(btVector3(.5f,.5f,.5f));

btTransform groundTransform;
groundTransform.setIdentity();

//We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
{
btScalar mass(0.);

//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);

btVector3 localInertia(0,0,0);
if (isDynamic)
groundShape->calculateLocalInertia(mass,localInertia);

//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);

//add the body to the dynamics world
m_bt_world->addRigidBody(body);
}

//Adding Shapes
{
//create a few dynamic rigidbodies
// Re-using the same collision is better for memory usage and performance
btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
m_rigid_mesh[0].Compile("[sc#add afcb2 2 2 -.1]");
m_rigid_mesh[1].Compile("[sc#dad afcb2 2 2 -.1]");
m_rigid_mesh[2].Compile("[sc#dda afcb2 2 2 -.1]");
m_rigid_mesh[3].Compile("[sc#daa afcb2 2 2 -.1]");
m_rigid_mesh[4].Compile("[sc#ada afcb2 2 2 -.1]");
m_rigid_mesh[5].Compile("[sc#aad afcb2 2 2 -.1]");

m_bt_collision_shapes << colShape;
m_bt_dynamic_shapes << colShape;

/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();
btScalar mass(1.f);

//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);

btVector3 localInertia(0,0,0);
if (isDynamic)
colShape->calculateLocalInertia(mass,localInertia);

int i;
for (i=0;i<gNumObjects;i++)
{
btCollisionShape* shape = colShape;
btTransform trans;
trans.setIdentity();

//stack them
int colsize = 10;
int row = int(((float)i*CUBE_HALF_EXTENTS*2.0f)/((float)colsize*2.0f*CUBE_HALF_EXTENTS));
int row2 = row;
int col = (i)%(colsize)-colsize/2;

if (col>3)
{
col=11;
row2 |=1;
}

btVector3 pos(((row+col+row2) % 4)*CUBE_HALF_EXTENTS,
20.0f + row*8*CUBE_HALF_EXTENTS+CUBE_HALF_EXTENTS+EXTRA_HEIGHT,
col*8*CUBE_HALF_EXTENTS + 2 * (row2%2)*CUBE_HALF_EXTENTS);

trans.setOrigin(pos);
float mass = 1.f;


btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));

//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);

btVector3 localInertia(0,0,0);
if (isDynamic)
shape->calculateLocalInertia(mass,localInertia);

//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects

btDefaultMotionState* myMotionState = new btDefaultMotionState(trans);

btRigidBody::btRigidBodyConstructionInfo cInfo(mass,myMotionState,shape,localInertia);

btRigidBody* body = new btRigidBody(cInfo);
body->setContactProcessingThreshold(BT_LARGE_FLOAT);

m_bt_world->addRigidBody(body);

///when using m_ccdMode
if (m_bt_ccd_mode == USE_CCD)
{
body->setCcdMotionThreshold(CUBE_HALF_EXTENTS);
body->setCcdSweptSphereRadius(0.9*CUBE_HALF_EXTENTS);
}
}
}
}
#endif
}

void BtPhysTest::TickGame(float seconds)
@@ -334,6 +213,10 @@ void BtPhysTest::TickGame(float seconds)
if (Input::GetButtonState(27 /*SDLK_ESCAPE*/))
Ticker::Shutdown();

m_loop_value += seconds;
if (m_loop_value > M_PI * 2.0f)
m_loop_value -= M_PI * 2.0f;

vec3 GroundBarycenter = vec3(.0f);
vec3 PhysObjBarycenter = vec3(.0f);
float factor = .0f;
@@ -395,11 +278,10 @@ void BtPhysTest::TickGame(float seconds)
GroundMat = GroundMat * mat4(quat::fromeuler_xyz(vec3(20.f, .0f, .0f) * seconds));
PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat));
}
else
else if (i == 1)
{
GroundMat = GroundMat * mat4::translate(vec3(.0f, .0f, 10.0f) * seconds);
if (GroundMat.v3.z > 40.0f)
GroundMat = GroundMat * mat4::translate(vec3(.0f, .0f, -80.0f));
GroundMat = mat4::translate(vec3(-15.0f, 5.0f, lol::cos(m_loop_value) * 8.f)) *
mat4(quat::fromeuler_xyz(vec3(.0f, lol::cos(m_loop_value) * 20.f, .0f)));
PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat));
}
}
@@ -458,17 +340,6 @@ void BtPhysTest::TickGame(float seconds)
m_camera->SetPosition(GroundBarycenter + normalize(GroundBarycenter - PhysObjBarycenter) * 60.0f);
}

#if 0
///step the simulation
if (m_bt_world)
{
//int steps = (int)(seconds / 0.005f);
//for (int i = 0; i < steps; i++)
m_bt_world->stepSimulation(seconds /*/ steps*/);
//optional but useful: debug drawing
//m_bt_world->debugDrawWorld();
}
#endif
}

void BtPhysTest::TickDraw(float seconds)
@@ -477,59 +348,12 @@ void BtPhysTest::TickDraw(float seconds)

if (!m_ready)
{
#if 0
m_ground_mesh.MeshConvert();
m_rigid_mesh[0].MeshConvert();
m_rigid_mesh[1].MeshConvert();
m_rigid_mesh[2].MeshConvert();
m_rigid_mesh[3].MeshConvert();
m_rigid_mesh[4].MeshConvert();
m_rigid_mesh[5].MeshConvert();
#endif
/* FIXME: this object never cleans up */
m_ready = true;
}

//Video::SetClearColor(vec4(0.0f, 0.0f, 0.12f, 1.0f));

#if 0
vec3 BarycenterLocation = vec3(.0f);
float BarycenterFactor = 0.0f;
for(int i=0;i<gNumObjects;i++)
{
mat4 m(1.0f);
btMatrix3x3 rot; rot.setIdentity();
btCollisionObject* colObj = m_bt_world->getCollisionObjectArray()[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if(body && body->getMotionState())
{
btDefaultMotionState* myMotionState = (btDefaultMotionState*)body->getMotionState();
myMotionState->m_graphicsWorldTrans.getOpenGLMatrix(&m[0][0]);
rot = myMotionState->m_graphicsWorldTrans.getBasis();
}
else
{
colObj->getWorldTransform().getOpenGLMatrix(&m[0][0]);
rot = colObj->getWorldTransform().getBasis();
}
if (i > 0)
{
BarycenterLocation += m.v3.xyz;
BarycenterFactor += 1.0f;
}
if (i == 0)
m_ground_mesh.Render(m);
else
m_rigid_mesh[i % 6].Render(m);
}
if (BarycenterFactor > .0f)
{
BarycenterLocation /= BarycenterFactor;

m_camera->SetTarget(BarycenterLocation);
m_camera->SetPosition(BarycenterLocation + vec3(-20.0f, 8.0f, .0f));
}
#endif
}

BtPhysTest::~BtPhysTest()
@@ -573,37 +397,6 @@ BtPhysTest::~BtPhysTest()
}
Ticker::Unref(m_simulation);

#if 0
//Exit Physics
{
//cleanup in the reverse order of creation/initialization
//remove the rigidbodies from the dynamics world and delete them
for (int i = m_bt_world->getNumCollisionObjects() - 1; i >= 0 ;i--)
{
btCollisionObject* obj = m_bt_world->getCollisionObjectArray()[i];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
delete body->getMotionState();

m_bt_world->removeCollisionObject(obj);
delete obj;
}

//delete collision shapes
for (int j = 0; j < m_bt_collision_shapes.Count(); j++)
{
btCollisionShape* shape = m_bt_collision_shapes[j];
delete shape;
}
m_bt_collision_shapes.Empty();

delete m_bt_world;
delete m_bt_solver;
delete m_bt_broadphase;
delete m_bt_dispatcher;
delete m_bt_collision_config;
}
#endif
}

int main(int argc, char **argv)


+ 1
- 19
test/BtPhysTest.h View File

@@ -31,25 +31,7 @@ private:
Array<PhysicsObject*> m_platform_list;
Array<PhysicsObject*> m_character_list;

#if 0
EasyMesh m_ground_mesh;
EasyMesh m_rigid_mesh[6];

//Bullet Physics Datas
enum
{
USE_CCD=1,
USE_NO_CCD
};
int m_bt_ccd_mode;
btDefaultCollisionConfiguration* m_bt_collision_config;
btCollisionDispatcher* m_bt_dispatcher;
btDbvtBroadphase* m_bt_broadphase;
btSequentialImpulseConstraintSolver* m_bt_solver;
btDiscreteDynamicsWorld* m_bt_world;
Array<btCollisionShape*> m_bt_collision_shapes;
Array<btCollisionShape*> m_bt_dynamic_shapes;
#endif
float m_loop_value;
};

#endif // __BTPHYSTEST_H__


+ 59
- 44
test/PhysicObject.h View File

@@ -26,32 +26,37 @@ public:
PhysicsObject(Simulation* new_sim, const vec3 &base_location, const quat &base_rotation)
: m_ready(false), m_should_render(true), m_is_character(false)
{
m_physics = new EasyPhysic(this);

m_mesh.Compile("[sc#ddd afcb60 1 60 -.1]");
vec3 BoxSize = vec3(60.f, 1.f, 60.f);
m_physics.SetCollisionChannel(0, 0xFF);
m_physics.SetShapeToBox(BoxSize);
m_physics.SetMass(.0f);
m_physics.SetTransform(base_location, base_rotation);
m_physics.InitBodyToRigid(true);
m_physics.AddToSimulation(new_sim);
m_physics->SetCollisionChannel(0, 0xFF);
m_physics->SetShapeToBox(BoxSize);
m_physics->SetMass(.0f);
m_physics->SetTransform(base_location, base_rotation);
m_physics->InitBodyToRigid(true);
m_physics->AddToSimulation(new_sim);
}

PhysicsObject(Simulation* new_sim, const vec3 &base_location, const quat &base_rotation, int dummy)
: m_ready(false), m_should_render(true), m_is_character(false)
{
if (dummy == 1) //for Rope purpose
if (dummy == 1) //for platform purpose
{
m_physics = new EasyPhysic(this);

m_mesh.Compile("[sc#ddd afcb20 1 20 -.1]");
vec3 BoxSize = vec3(20.f, 1.f, 20.f);
m_physics.SetCollisionChannel(0, 0xFF);
m_physics.SetShapeToBox(BoxSize);
m_physics.SetMass(.0f);
m_physics.SetTransform(base_location, base_rotation);
m_physics.InitBodyToRigid(true);
m_physics.AddToSimulation(new_sim);
m_physics->SetCollisionChannel(0, 0xFF);
m_physics->SetShapeToBox(BoxSize);
m_physics->SetMass(.0f);
m_physics->SetTransform(base_location, base_rotation);
m_physics->InitBodyToRigid(true);
m_physics->AddToSimulation(new_sim);
}
else if (dummy == 2) //for character purpose
{
m_character = new EasyCharacterController(this);
m_is_character = true;
//m_mesh.Compile("[sc#f00 afcb10 10 10 -.1]");
m_mesh.Compile(
@@ -77,12 +82,12 @@ public:
" ty-.1 tx.05]"
);
vec3 BoxSize = vec3(.5f, 2.f, .5f);
m_character.SetCollisionChannel(0, 0xFF);
m_character.SetShapeToCapsule(BoxSize.x, BoxSize.y);
m_character.SetMass(.0f);
m_character.SetTransform(base_location, base_rotation);
m_character.InitBodyToGhost();
m_character.AddToSimulation(new_sim);
m_character->SetCollisionChannel(0, 0xFF);
m_character->SetShapeToCapsule(BoxSize.x, BoxSize.y);
m_character->SetMass(.0f);
m_character->SetTransform(base_location, base_rotation);
m_character->InitBodyToGhost();
m_character->AddToSimulation(new_sim);
}
}

@@ -167,57 +172,67 @@ public:
}
}

m_physics = new EasyPhysic(this);

m_mesh.Compile(MeshRand[RandValue]);
vec3 BoxSize = vec3(2.0f);
int ColGroup = 1;
if (RandValue < SphereLimit)
{
m_physics.SetShapeToBox(BoxSize);
m_physics->SetShapeToBox(BoxSize);
ColGroup += 0;
}
else if (RandValue < ConeLimit)
{
m_physics.SetShapeToSphere(BoxSize.x * 2.f);
m_physics->SetShapeToSphere(BoxSize.x * 2.f);
ColGroup += 1;
}
else if (RandValue < CylLimit)
{
m_physics.SetShapeToCone(BoxSize.x, BoxSize.y);
m_physics->SetShapeToCone(BoxSize.x, BoxSize.y);
ColGroup += 2;
}
else if (RandValue < CapsLimit)
{
m_physics.SetShapeToCylinder(BoxSize);
m_physics->SetShapeToCylinder(BoxSize);
ColGroup += 3;
}
else
{
m_physics.SetShapeToCapsule(BoxSize.x, BoxSize.y);
m_physics->SetShapeToCapsule(BoxSize.x, BoxSize.y);
ColGroup += 4;
}

m_physics.SetCollisionChannel(0, 0xFF);
//m_physics.SetCollisionChannel(ColGroup, (1<<ColGroup)|(1));
m_physics.SetMass(base_mass);
m_physics.SetTransform(base_location);
m_physics.InitBodyToRigid();
m_physics.AddToSimulation(new_sim);
m_physics->SetCollisionChannel(0, 0xFF);
//m_physics->SetCollisionChannel(ColGroup, (1<<ColGroup)|(1));
m_physics->SetMass(base_mass);
m_physics->SetTransform(base_location);
m_physics->InitBodyToRigid();
m_physics->AddToSimulation(new_sim);
}

void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation=lol::quat(lol::mat4(1.0f)))
{
if (m_is_character)
m_character.SetTransform(base_location, base_rotation);
m_character->SetTransform(base_location, base_rotation);
else
m_physics.SetTransform(base_location, base_rotation);
m_physics->SetTransform(base_location, base_rotation);
}

void SetLinearVelocity(const lol::vec3& NewVelocity, bool bIsLocal=false)
{
//if (m_is_character)
// m_character->SetLinearVelocity(NewVelocity);
//else
// m_physics->SetLinearVelocity(NewVelocity);
}

lol::mat4 GetTransform()
{
if (m_is_character)
return m_character.GetTransform();
return m_character->GetTransform();
else
return m_physics.GetTransform();
return m_physics->GetTransform();
}

void SetRender(bool should_render)
@@ -226,8 +241,8 @@ public:
}

EasyMesh *GetMesh() { return &m_mesh; }
EasyPhysic *GetPhysic() { return &m_physics; }
EasyPhysic *GetCharacter() { return &m_character; }
EasyPhysic *GetPhysic() { return m_physics; }
EasyPhysic *GetCharacter() { return m_character; }

~PhysicsObject()
{
@@ -254,21 +269,21 @@ protected:
if (m_should_render)
{
if (m_is_character)
m_mesh.Render(m_character.GetTransform());
m_mesh.Render(m_character->GetTransform());
else
m_mesh.Render(m_physics.GetTransform());
m_mesh.Render(m_physics->GetTransform());
}
}

private:
//Base datas
EasyMesh m_mesh;
EasyPhysic m_physics;
EasyCharacterController m_character;
EasyMesh m_mesh;
EasyPhysic* m_physics;
EasyCharacterController* m_character;

bool m_ready;
bool m_should_render;
bool m_is_character;
bool m_ready;
bool m_should_render;
bool m_is_character;
};

#endif /* __PHYSICOBJECT_H__ */


+ 2
- 2
test/Physics/Include/EasyCharacterController.h View File

@@ -35,8 +35,8 @@ class EasyCharacterController : public EasyPhysic
#ifdef HAVE_PHYS_USE_BULLET

public:
EasyCharacterController() :
EasyPhysic(),
EasyCharacterController(WorldEntity* NewOwnerEntity) :
EasyPhysic(NewOwnerEntity),
m_character(NULL)
{
m_up_axis = 1;


+ 45
- 2
test/Physics/Include/EasyPhysics.h View File

@@ -38,7 +38,7 @@ class EasyPhysic
#ifdef HAVE_PHYS_USE_BULLET

public:
EasyPhysic();
EasyPhysic(WorldEntity* NewOwnerEntity);
~EasyPhysic();

virtual void SetShapeToBox(lol::vec3& box_size);
@@ -49,6 +49,9 @@ public:

virtual bool CanChangeCollisionChannel() { return (m_rigid_body == NULL); }
virtual void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation=lol::quat(lol::mat4(1.0f)));
private:
virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix);
public:
virtual void SetMass(float mass);
virtual void InitBodyToRigid(bool ZeroMassIsKinematic=false);
virtual void InitBodyToGhost();
@@ -76,7 +79,7 @@ protected:
#else // NO PHYSIC IMPLEMENTATION

public:
EasyPhysic() { }
EasyPhysic(WorldEntity* NewOwnerEntity) { m_owner_entity = NewOwnerEntity; }

virtual void SetShapeToBox(lol::vec3& BoxSize) { }
virtual void SetShapeToSphere(float radius) { }
@@ -86,6 +89,9 @@ public:

virtual bool CanChangeCollisionChannel() { return true; }
virtual void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation=lol::quat(lol::mat4(1.0f))) { }
private:
virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix) { }
public:
virtual void SetMass(float mass) { }
virtual void InitBodyToRigid() { }
virtual void InitBodyToGhost() { }
@@ -113,11 +119,48 @@ public:
int GetCollisionGroup() { return m_collision_group; }
int GetCollisionMask() { return m_collision_mask; }

//Base/Attachment logic
virtual void AttachTo(EasyPhysic* NewBase, bool NewBaseLockLocation = true, bool NewBaseLockRotation = true)
{
if (NewBase == this || NewBase->m_base_physic == this)
return;

if (NewBase)
{
bool bAlreadyExists = false;
for (int i = 0; i < NewBase->m_based_physic_list.Count(); ++i)
if (NewBase->m_based_physic_list[i] == this)
bAlreadyExists = true;
if (!bAlreadyExists)
NewBase->m_based_physic_list << this;
m_base_physic = NewBase;
m_base_lock_location = NewBaseLockLocation;
m_base_lock_rotation = NewBaseLockRotation;
}
else
{
for (int i = 0; i < NewBase->m_based_physic_list.Count(); ++i)
if (NewBase->m_based_physic_list[i] == this)
NewBase->m_based_physic_list.Remove(i--);
m_base_physic = NULL;
}
}

protected:
lol::mat4 m_local_to_world;
float m_mass;
int m_collision_group;
int m_collision_mask;
WorldEntity* m_owner_entity;

//Base/Attachment logic
Array<EasyPhysic*> m_based_physic_list; //List of objects based on this : this object moves, its based object move with it.
EasyPhysic* m_base_physic; //Base for this object : The base moves, the object moves with it.
bool m_base_lock_location; //when this is TRUE, location moves with rotation change.
bool m_base_lock_rotation; //when this is TRUE, rotation moves with rotation change.

//Touch logic
Array<EasyPhysic*> m_touching_physic; //Maintained by ghost objects
};

} /* namespace phys */


+ 27
- 3
test/Physics/Src/EasyPhysics.cpp View File

@@ -29,7 +29,7 @@ namespace phys
//EASY_PHYSIC
//--

EasyPhysic::EasyPhysic() :
EasyPhysic::EasyPhysic(WorldEntity* NewOwnerEntity) :
m_collision_object(NULL),
m_ghost_object(NULL),
m_rigid_body(NULL),
@@ -39,7 +39,8 @@ EasyPhysic::EasyPhysic() :
m_motion_state(NULL),
m_mass(.0f),
m_collision_group(1),
m_collision_mask(1)
m_collision_mask(1),
m_owner_entity(NewOwnerEntity)
{
}

@@ -113,7 +114,8 @@ void EasyPhysic::SetShapeToCapsule(float radius, float height)
//--
void EasyPhysic::SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation)
{
m_local_to_world = lol::mat4::translate(base_location) * mat4(base_rotation);
lol::mat4 PreviousMatrix = m_local_to_world;
m_local_to_world = lol::mat4::translate(base_location) * lol::mat4(base_rotation);

if (m_ghost_object)
m_ghost_object->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location * LOL2BT_UNIT)));
@@ -124,6 +126,28 @@ void EasyPhysic::SetTransform(const lol::vec3& base_location, const lol::quat& b
else
m_motion_state = new btDefaultMotionState(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location * LOL2BT_UNIT)));
}

for (int i = 0; i < m_based_physic_list.Count(); i++)
if (m_based_physic_list[i])
m_based_physic_list[i]->BaseTransformChanged(PreviousMatrix, m_local_to_world);
else
m_based_physic_list.Remove(i--);
}

//Internal callback when Base transform has changed.
void EasyPhysic::BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix)
{
mat4 PreviousMatrixLoc = ((m_base_lock_location)?(PreviousMatrix):(lol::mat4::translate(PreviousMatrix.v3.xyz)));
mat4 PreviousMatrixRot = ((m_base_lock_rotation)?(lol::mat4(lol::quat(PreviousMatrix))):(lol::mat4(1.f)));
mat4 NewMatrixLoc = ((m_base_lock_location)?(NewMatrix):(lol::mat4::translate(NewMatrix.v3.xyz)));
mat4 NewMatrixRot = ((m_base_lock_rotation)?(lol::mat4(lol::quat(NewMatrix))):(lol::mat4(1.f)));
if (m_ghost_object || (m_rigid_body->getCollisionFlags() & btCollisionObject::CF_KINEMATIC_OBJECT))
{
mat4 ThisMatrixLoc = NewMatrixLoc * inverse(PreviousMatrixLoc) * lol::mat4::translate(m_local_to_world.v3.xyz);
mat4 ThisMatrixRot = NewMatrixRot * inverse(PreviousMatrixRot) * lol::mat4(lol::quat(m_local_to_world));
SetTransform(ThisMatrixLoc.v3.xyz, lol::mat4(lol::quat(ThisMatrixRot)));
}
}

//-------------------------------------------------------------------------


Loading…
Cancel
Save