From 6cb8bb99ca718a341a6053607efaef8f6161c237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20=E2=80=98Touky=E2=80=99=20Huet?= Date: Sun, 8 Jul 2012 16:16:57 +0000 Subject: [PATCH] Behold the power of LolPhysics ! Added lol::phys::Simulation, lol::phys::EasyPhysics for easy physic uses. Added PhysicsObject, wich hold EasyMesh & EasyPhysics components so it is easy to use. Easy seems to be the consensus. BtPhysTest now works with new physics classes. Known problem for this commit: Physics is not properly setup. There might be memory leaks, I don't think I've parsed all new/delete. A LOT of primitives are not taken into account. --- build/vs2010/Lol.Core.Vars.props | 3 +- test/BtPhysTest.cpp | 56 ++++++++- test/BtPhysTest.h | 7 ++ test/BtPhysTest.vcxproj | 7 +- test/BtPhysTest.vcxproj.filters | 16 +++ test/PhysicObject.h | 90 ++++++++++++++ test/Physics/EasyPhysics.cpp | 160 +++++++++++++++++++++++++ test/Physics/EasyPhysics.h | 77 ++++++++++++ test/Physics/LolBtPhysicsIntegration.h | 38 ++++++ test/Physics/LolPhysics.h | 122 +++++++++++++++++++ 10 files changed, 568 insertions(+), 8 deletions(-) create mode 100644 test/PhysicObject.h create mode 100644 test/Physics/EasyPhysics.cpp create mode 100644 test/Physics/EasyPhysics.h create mode 100644 test/Physics/LolBtPhysicsIntegration.h create mode 100644 test/Physics/LolPhysics.h diff --git a/build/vs2010/Lol.Core.Vars.props b/build/vs2010/Lol.Core.Vars.props index 75774ec4..7745b7d1 100644 --- a/build/vs2010/Lol.Core.Vars.props +++ b/build/vs2010/Lol.Core.Vars.props @@ -22,8 +22,9 @@ $(ContribDir)\bullet-2.80-rev2531 $(BtPhysDir)\include;$(BtPhysDir)\include\bullet + HAVE_PHYS_USE_BULLET;$(Win32Defines) - + $(ContribDir)\gtk-2.22.1 $(ContribDir)\gtkglarea-2.0.1 $(GtkDir)\lib\glib-2.0\include;$(GtkDir)\lib\gtk-2.0\include;$(GtkDir)\include\glib-2.0;$(GtkDir)\include\gtk-2.0;$(GtkDir)\include\cairo;$(GtkDir)\include\pango-1.0;$(GtkDir)\include\gdk-pixbuf-2.0;$(GtkDir)\include\atk-1.0;$(GtkGlDir)\include diff --git a/test/BtPhysTest.cpp b/test/BtPhysTest.cpp index 057cda6c..1e2f85ff 100644 --- a/test/BtPhysTest.cpp +++ b/test/BtPhysTest.cpp @@ -40,8 +40,17 @@ using namespace lol; +#ifndef HAVE_PHYS_USE_BULLET +#define HAVE_PHYS_USE_BULLET +#endif /* HAVE_PHYS_USE_BULLET */ + +#include "Physics\LolPhysics.h" +#include "Physics\EasyPhysics.h" +#include "PhysicObject.h" #include "BtPhysTest.h" +using namespace lol::phys; + #define CUBE_HALF_EXTENTS .5f #define EXTRA_HEIGHT 1.f @@ -60,6 +69,24 @@ BtPhysTest::BtPhysTest(bool editor) m_ready = false; + m_simulation = new Simulation(); + m_simulation->InitContext(); + m_simulation->SetGravity(vec3(.0f, -10.0f, .0f)); + + m_ground_object = new PhysicsObject(m_simulation); + Ticker::Ref(m_ground_object); + + for (int x=0; x < 10; x++) + { + for (int y=0; y < 10; y++) + { + PhysicsObject* new_physobj = new PhysicsObject(m_simulation, 10.f, vec3(0.f, 20.f, -20.0f) + vec3(.0f, 4.f * (float)y, 4.f * (float)x)); + m_physobj_list << new_physobj; + Ticker::Ref(new_physobj); + } + } + +#if 0 //init Physics { m_bt_ccd_mode = USE_CCD; @@ -69,7 +96,10 @@ BtPhysTest::BtPhysTest(bool editor) //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_dispatcher->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE, + BOX_SHAPE_PROXYTYPE, + m_bt_collision_config->getCollisionAlgorithmCreateFunc(CONVEX_SHAPE_PROXYTYPE, + CONVEX_SHAPE_PROXYTYPE)); m_bt_broadphase = new btDbvtBroadphase(); @@ -88,7 +118,7 @@ BtPhysTest::BtPhysTest(bool editor) 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 afcb110 1 110 -1]"); + m_ground_mesh.Compile("[sc#ddd afcb220 2 220 -1]"); //m_bt_collision_shapes << new btCylinderShape(btVector3(.5f,.5f,.5f)); @@ -151,7 +181,7 @@ BtPhysTest::BtPhysTest(bool editor) //stack them int colsize = 10; - int row = (i*CUBE_HALF_EXTENTS*2)/(colsize*2*CUBE_HALF_EXTENTS); + 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; @@ -199,6 +229,7 @@ BtPhysTest::BtPhysTest(bool editor) } } } +#endif } void BtPhysTest::TickGame(float seconds) @@ -208,15 +239,22 @@ void BtPhysTest::TickGame(float seconds) if (Input::GetButtonState(27 /*SDLK_ESCAPE*/)) Ticker::Shutdown(); + m_simulation->TickContext(seconds); + + m_camera->SetTarget(vec3(.0f)); + m_camera->SetPosition(vec3(-30.0f, 10.0f, .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); + //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) @@ -225,6 +263,7 @@ void BtPhysTest::TickDraw(float seconds) if (!m_ready) { +#if 0 m_ground_mesh.MeshConvert(); m_rigid_mesh[0].MeshConvert(); m_rigid_mesh[1].MeshConvert(); @@ -232,12 +271,14 @@ void BtPhysTest::TickDraw(float seconds) 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;iSetTarget(BarycenterLocation); m_camera->SetPosition(BarycenterLocation + vec3(-20.0f, 8.0f, .0f)); } +#endif } BtPhysTest::~BtPhysTest() { Ticker::Unref(m_camera); +#if 0 //Exit Physics { //cleanup in the reverse order of creation/initialization @@ -309,6 +352,7 @@ BtPhysTest::~BtPhysTest() delete m_bt_dispatcher; delete m_bt_collision_config; } +#endif } int main(int argc, char **argv) diff --git a/test/BtPhysTest.h b/test/BtPhysTest.h index bb8956ec..b4f421be 100644 --- a/test/BtPhysTest.h +++ b/test/BtPhysTest.h @@ -23,6 +23,12 @@ protected: private: Camera* m_camera; bool m_ready; + + lol::phys::Simulation* m_simulation; + Array m_physobj_list; + PhysicsObject* m_ground_object; + +#if 0 EasyMesh m_ground_mesh; EasyMesh m_rigid_mesh[6]; @@ -40,6 +46,7 @@ private: btDiscreteDynamicsWorld* m_bt_world; Array m_bt_collision_shapes; Array m_bt_dynamic_shapes; +#endif }; #endif // __BTPHYSTEST_H__ diff --git a/test/BtPhysTest.vcxproj b/test/BtPhysTest.vcxproj index f3062079..0bea4235 100644 --- a/test/BtPhysTest.vcxproj +++ b/test/BtPhysTest.vcxproj @@ -36,9 +36,14 @@ + + + + + @@ -70,4 +75,4 @@ - + \ No newline at end of file diff --git a/test/BtPhysTest.vcxproj.filters b/test/BtPhysTest.vcxproj.filters index 1ac784b1..6ef488ad 100644 --- a/test/BtPhysTest.vcxproj.filters +++ b/test/BtPhysTest.vcxproj.filters @@ -2,13 +2,29 @@ + + Physics + + + Physics + + + Physics + + + + Physics + {4fc7662b-b17a-49b9-acd1-0cf767183b06} + + {ccecd634-9321-4c49-9471-e9da50dda6d3} + \ No newline at end of file diff --git a/test/PhysicObject.h b/test/PhysicObject.h new file mode 100644 index 00000000..44a7c60f --- /dev/null +++ b/test/PhysicObject.h @@ -0,0 +1,90 @@ +// +// Orbital +// +// Copyright: (c) 2009-2012 Cédric Lecacheur +// (c) 2009-2012 Benjamin Huet +// (c) 2012 Sam Hocevar +// + +/* FIXME: this file is pure crap; it's only a test. */ + +#if !defined __PHYSICOBJECT_H__ +#define __PHYSICOBJECT_H__ + +#include "core.h" +#include "easymesh\easymesh.h" +#include "Physics\EasyPhysics.h" + +using namespace lol; +using namespace lol::phys; + +class PhysicsObject : public WorldEntity +{ +public: + PhysicsObject(Simulation* new_sim) + : m_ready(false) + { + m_mesh.Compile("[sc#add afcb110 1 110 -.1]"); + m_physics.SetShapeToBox(vec3(110.f, 1.f, 110.f)); + m_physics.SetMass(.0f); + m_physics.InitBodyToRigid(); + m_physics.AddToSimulation(new_sim); + } + + PhysicsObject(Simulation* new_sim, float base_mass, vec3 &base_location) + : m_ready(false) + { + Array MeshRand; + + MeshRand << "[sc#add afcb2 2 2 -.1]"; + MeshRand << "[sc#dad afcb2 2 2 -.1]"; + MeshRand << "[sc#dda afcb2 2 2 -.1]"; + MeshRand << "[sc#daa afcb2 2 2 -.1]"; + MeshRand << "[sc#ada afcb2 2 2 -.1]"; + MeshRand << "[sc#aad afcb2 2 2 -.1]"; + + int RandValue = (int)(lol::RandF() * (MeshRand.Count() - 1)); + + m_mesh.Compile(MeshRand[RandValue]); + m_physics.SetShapeToBox(vec3(2.0f)); + m_physics.SetMass(base_mass); + m_physics.SetBaseTransform(base_location); + m_physics.InitBodyToRigid(); + m_physics.AddToSimulation(new_sim); + } + + ~PhysicsObject() + { + } + + char const *GetName() { return ""; } + +protected: + virtual void TickGame(float seconds) + { + WorldEntity::TickGame(seconds); + } + + virtual void TickDraw(float seconds) + { + WorldEntity::TickDraw(seconds); + + if (!m_ready) + { + m_mesh.MeshConvert(); + m_ready = true; + } + + m_mesh.Render(m_physics.GetTransform()); + } + +private: + //Base datas + EasyMesh m_mesh; + EasyPhysics m_physics; + + bool m_ready; +}; + +#endif /* __PHYSICOBJECT_H__ */ + diff --git a/test/Physics/EasyPhysics.cpp b/test/Physics/EasyPhysics.cpp new file mode 100644 index 00000000..1a432fd9 --- /dev/null +++ b/test/Physics/EasyPhysics.cpp @@ -0,0 +1,160 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2012 Sam Hocevar +// (c) 2009-2012 Cédric Lecacheur +// (c) 2009-2012 Benjamin Huet +// This program is free software; you can redistribute it and/or +// modify it under the terms of the Do What The Fuck You Want To +// Public License, Version 2, as published by Sam Hocevar. See +// http://sam.zoy.org/projects/COPYING.WTFPL for more details. +// + +// +// The EasyMesh class +// ------------------ +// + +#if defined HAVE_CONFIG_H +# include "config.h" +#endif + +#include "LolBtPhysicsIntegration.h" +#include "LolPhysics.h" + +namespace lol +{ + +namespace phys +{ + +#ifdef HAVE_PHYS_USE_BULLET + +EasyPhysics::EasyPhysics() : + m_collision_object(NULL), + m_rigid_body(NULL), + m_collision_shape(NULL), + m_motion_state(NULL), + m_mass(.0f), + m_local_inertia(btVector3(.0f, .0f, .0f)) +{ +} + +//------------------------------------------------------------------------- +//Set Shape functions +//-- + +void EasyPhysics::SetShapeTo(btCollisionShape* collision_shape) +{ + bool bReinitToRigidBody = false; + if (m_rigid_body) + { + bReinitToRigidBody = true; + delete m_rigid_body; + } + if (m_collision_shape) + delete m_collision_shape; + + m_collision_shape = collision_shape; + + if (bReinitToRigidBody) + InitBodyToRigid(); +} + +//Box Shape support +void EasyPhysics::SetShapeToBox(lol::vec3& box_size) +{ + SetShapeTo(new btBoxShape(LOL2BT_VEC3(box_size * LOL2BT_UNIT * LOL2BT_SIZE))); +} + +//------------------------------------------------------------------------- +//Base Location/Rotation setup +//-- +void EasyPhysics::SetBaseTransform(const lol::vec3& base_location, const lol::quat& base_rotation) +{ + if (m_motion_state) + m_motion_state->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location))); + else + m_motion_state = new btDefaultMotionState(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location))); +} + +//------------------------------------------------------------------------- +//Mass related functions +//-- + +//Set Shape functions +void EasyPhysics::SetMass(float mass) +{ + m_mass = mass; + + if (m_rigid_body) + { + SetLocalInertia(m_mass); + m_rigid_body->setMassProps(mass, LOL2BT_VEC3(m_local_inertia)); + } +} + +//------------------------------------------------------------------------- +//Final conversion pass functons : Body related +//-- + +//Init to rigid body +void EasyPhysics::InitBodyToRigid() +{ + if (m_collision_object) + delete m_collision_object; + + SetLocalInertia(m_mass); + if (!m_motion_state) + SetBaseTransform(vec3(.0f)); + btRigidBody::btRigidBodyConstructionInfo NewInfos(m_mass, m_motion_state, m_collision_shape, m_local_inertia); + m_rigid_body = new btRigidBody(NewInfos); + m_collision_object = m_rigid_body; +} + +void EasyPhysics::AddToSimulation(class Simulation* current_simulation) +{ + btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld(); + if (m_rigid_body) + { + dynamics_world->addRigidBody(m_rigid_body); + if (m_mass != .0f) + current_simulation->AddToDynamic(this); + else + current_simulation->AddToStatic(this); + } + else + dynamics_world->addCollisionObject(m_collision_object); +} + +//------------------------------------------------------------------------- +//Getter functons +//-- + +mat4 EasyPhysics::GetTransform() +{ + m_local_to_world = lol::mat4(1.0f); + if (m_rigid_body && m_motion_state) + { + btTransform CurTransform; + m_motion_state->getWorldTransform(CurTransform); + CurTransform.getOpenGLMatrix(&m_local_to_world[0][0]); + } + else if (m_collision_object) + m_collision_object->getWorldTransform().getOpenGLMatrix(&m_local_to_world[0][0]); + return m_local_to_world; +} + +//Set Local Inertia +void EasyPhysics::SetLocalInertia(float mass) +{ + if (mass != .0f) + m_collision_shape->calculateLocalInertia(mass, m_local_inertia); + else + m_local_inertia = btVector3(.0f, .0f, .0f); +} +#endif + +} /* namespace phys */ + +} /* namespace lol */ diff --git a/test/Physics/EasyPhysics.h b/test/Physics/EasyPhysics.h new file mode 100644 index 00000000..5828def7 --- /dev/null +++ b/test/Physics/EasyPhysics.h @@ -0,0 +1,77 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2012 Sam Hocevar +// (c) 2009-2012 Benjamin Huet +// This program is free software; you can redistribute it and/or +// modify it under the terms of the Do What The Fuck You Want To +// Public License, Version 2, as published by Sam Hocevar. See +// http://sam.zoy.org/projects/COPYING.WTFPL for more details. +// + +// +// The EasyPhysics class +// ------------------ +// + +#if !defined __EASYPHYSICS_EASYPHYSICS_H__ +#define __EASYPHYSICS_EASYPHYSICS_H__ + +#ifdef HAVE_PHYS_USE_BULLET +#include "core.h" +#include +#include +#endif + +namespace lol +{ + +namespace phys +{ + +class EasyPhysics +{ +#ifdef HAVE_PHYS_USE_BULLET +public: + EasyPhysics(); + + void SetShapeToBox(lol::vec3& box_size); + void SetBaseTransform(const lol::vec3& base_location, const lol::quat& base_rotation=lol::quat(lol::mat4(1.0f))); + void SetMass(float mass); + void InitBodyToRigid(); + void AddToSimulation(class Simulation* current_simulation); + mat4 GetTransform(); + +protected: + void SetLocalInertia(float mass); + void SetShapeTo(btCollisionShape* collision_shape); + + btCollisionObject* m_collision_object; + + btRigidBody* m_rigid_body; + btScalar m_mass; + btVector3 m_local_inertia; + + btCollisionShape* m_collision_shape; + btMotionState* m_motion_state; + + lol::mat4 m_local_to_world; +#else +public: + EasyPhysics() { } + + void SetShapeToBox(lol::vec3& BoxSize) { } + void SetBaseTransform(const lol::vec3& base_location, const lol::quat& base_rotation=lol::quat(lol::mat4(1.0f))) { } + void SetMass(float mass) { } + void InitBodyToRigid() { } + void AddToSimulation(class Simulation* current_simulation) { } + mat4 GetTransform() { return mat4(1.0f); } +#endif +}; + +} /* namespace phys */ + +} /* namespace lol */ + +#endif /* __EASYPHYSICS_EASYPHYSICS_H__ */ + diff --git a/test/Physics/LolBtPhysicsIntegration.h b/test/Physics/LolBtPhysicsIntegration.h new file mode 100644 index 00000000..e4cbcdc9 --- /dev/null +++ b/test/Physics/LolBtPhysicsIntegration.h @@ -0,0 +1,38 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2012 Sam Hocevar +// (c) 2009-2012 Benjamin Huet +// This program is free software; you can redistribute it and/or +// modify it under the terms of the Do What The Fuck You Want To +// Public License, Version 2, as published by Sam Hocevar. See +// http://sam.zoy.org/projects/COPYING.WTFPL for more details. +// + +// +// Bullet Physics integration in Lol +// ------------------ +// + +#if !defined __LOLBTPHYSICSINTEGRATION_H__ +#define __LOLBTPHYSICSINTEGRATION_H__ + +namespace lol +{ + +#define LOL2BT_UNIT 1.0f +#define BT2LOL_UNIT 1.0f + +#define LOL2BT_SIZE 0.5f +#define BT2LOL_SIZE 2.0f + +#define LOL2BT_VEC3(ELEMENT) (*(btVector3*)(&(ELEMENT))) +#define BT2LOL_VEC3(ELEMENT) (*(lol::vec3*)(&(ELEMENT))) + +#define LOL2BT_QUAT(ELEMENT) (*(btQuaternion*)(&(ELEMENT))) +#define BT2LOL_QUAT(ELEMENT) (*(lol::quat*)(&(ELEMENT))) + +} /* namespace lol */ + +#endif /* __LOLBTPHYSICSINTEGRATION_H__ */ + diff --git a/test/Physics/LolPhysics.h b/test/Physics/LolPhysics.h new file mode 100644 index 00000000..47c4e71a --- /dev/null +++ b/test/Physics/LolPhysics.h @@ -0,0 +1,122 @@ +// +// LolPhysics +// +// Copyright: (c) 2009-2012 Benjamin Huet +// (c) 2012 Sam Hocevar +// + +#if !defined __LOLPHYSICS_H__ +#define __LOLPHYSICS_H__ + +#ifdef HAVE_PHYS_USE_BULLET +#include +#include +#include "LolBtPhysicsIntegration.h" +#include "EasyPhysics.h" +#endif + +namespace lol +{ + +namespace phys +{ + +class Simulation +{ +public: + Simulation() : + m_broadphase(NULL), + m_collision_configuration(NULL), + m_dispatcher(NULL), + m_solver(NULL), + m_dynamics_world(NULL) + { + } + ~Simulation() { } + + char const *GetName() { return ""; } + +#ifdef HAVE_PHYS_USE_BULLET + void InitContext() + { + // Build the broadphase + m_broadphase = new btDbvtBroadphase(); + + // Set up the collision configuration and dispatcher + m_collision_configuration = new btDefaultCollisionConfiguration(); + m_dispatcher = new btCollisionDispatcher(m_collision_configuration); + + // The actual physics solver + m_solver = new btSequentialImpulseConstraintSolver; + + // The world. + m_dynamics_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collision_configuration); + } + + void SetGravity(vec3 &NewGravity) + { + if (m_dynamics_world) + m_dynamics_world->setGravity(LOL2BT_VEC3(NewGravity)); + } + + void TickContext(float seconds) + { + //step the simulation + if (m_dynamics_world) + { + int steps = (int)(seconds / 0.005f); + for (int i = 0; i < steps; i++) + m_dynamics_world->stepSimulation(seconds / steps); + } + } + + void ExitContext() + { + delete m_broadphase; + delete m_collision_configuration; + delete m_dispatcher; + delete m_solver; + delete m_dynamics_world; + } + + btDiscreteDynamicsWorld* GetWorld() + { + return m_dynamics_world; + } + void AddToDynamic(EasyPhysics* dynamic_EP) + { + m_dynamic_list << dynamic_EP; + } + void AddToStatic(EasyPhysics* static_EP) + { + m_static_list << static_EP; + } + +private: + + //broadphase + btBroadphaseInterface* m_broadphase; + // Set up the collision configuration and dispatc + btDefaultCollisionConfiguration* m_collision_configuration; + btCollisionDispatcher* m_dispatcher; + // The actual physics solver + btSequentialImpulseConstraintSolver* m_solver; + // The world. + btDiscreteDynamicsWorld* m_dynamics_world; + + //Easy Physics body List + Array m_dynamic_list; + Array m_static_list; +#else + void InitContext() { } + void TickContext(float seconds) { } + void ExitContext() { } +#endif //HAVE_PHYS_USE_BULLET +}; + +} /* namespace phys */ + +} /* namespace lol */ + +#endif // __LOLPHYSICS_H__ +