| @@ -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) | |||
| @@ -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__ | |||
| @@ -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__ */ | |||
| @@ -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; | |||
| @@ -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 */ | |||
| @@ -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))); | |||
| } | |||
| } | |||
| //------------------------------------------------------------------------- | |||