From efca3ae4bac53ed7565ca221274ba9c7c93611db Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Wed, 21 Aug 2013 21:24:30 +0200 Subject: [PATCH] [DEV] add dynamic shape at mesh --- ege/CollisionShapeCreator.cpp | 171 ++++++++++++++++++++++++++++++++++ ege/CollisionShapeCreator.h | 23 +++++ ege/ElementGame.cpp | 73 ++++++++++++++- ege/ElementGame.h | 37 +++++++- ege/Environement.cpp | 8 +- ege/Environement.h | 10 +- lutin_ege.py | 1 + 7 files changed, 310 insertions(+), 13 deletions(-) create mode 100644 ege/CollisionShapeCreator.cpp create mode 100644 ege/CollisionShapeCreator.h diff --git a/ege/CollisionShapeCreator.cpp b/ege/CollisionShapeCreator.cpp new file mode 100644 index 0000000..e9b5ccd --- /dev/null +++ b/ege/CollisionShapeCreator.cpp @@ -0,0 +1,171 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Documentetion of bullet library : +// http://bulletphysics.org/mediawiki-1.5.8/index.php/Collision_Shapes + +btCollisionShape* ege::collision::CreateShape(const ewol::Mesh* _mesh) +{ + if (NULL == _mesh) { + return new btEmptyShape();; + } + const etk::Vector& physiqueProperty = _mesh->GetPhysicalProperties(); + if (physiqueProperty.Size()==0) { + return new btEmptyShape();; + } + int32_t count = 0; + for (int32_t iii=0; iii1) { + outputShape = new btCompoundShape(); + } + for (int32_t iii=0; iiiGetType()) { + case ewol::PhysicsShape::box : { + const ewol::PhysicsBox* tmpElement = physiqueProperty[iii]->ToBox(); + if (NULL ==tmpElement) { + // ERROR ... + continue; + } + btCollisionShape* tmpShape = new btBoxShape(tmpElement->GetSize()); + if (NULL != tmpShape) { + if (outputShape == NULL) { + return tmpShape; + } else { + vec4 qqq = tmpElement->GetQuaternion(); + const btTransform localTransform(btQuaternion(qqq.x(),qqq.y(),qqq.z(),qqq.w()), tmpElement->GetOrigin()); + outputShape->addChildShape(localTransform, tmpShape); + } + } + break; + } + case ewol::PhysicsShape::cylinder : { + const ewol::PhysicsCylinder* tmpElement = physiqueProperty[iii]->ToCylinder(); + if (NULL ==tmpElement) { + // ERROR ... + continue; + } + btCollisionShape* tmpShape = new btCylinderShape(tmpElement->GetSize()); + if (NULL != tmpShape) { + if (outputShape == NULL) { + return tmpShape; + } else { + vec4 qqq = tmpElement->GetQuaternion(); + const btTransform localTransform(btQuaternion(qqq.x(),qqq.y(),qqq.z(),qqq.w()), tmpElement->GetOrigin()); + outputShape->addChildShape(localTransform, tmpShape); + } + } + break; + } + case ewol::PhysicsShape::capsule : { + const ewol::PhysicsCapsule* tmpElement = physiqueProperty[iii]->ToCapsule(); + if (NULL ==tmpElement) { + // ERROR ... + continue; + } + btCollisionShape* tmpShape = new btCapsuleShape(tmpElement->GetRadius(), tmpElement->GetHeight()); + if (NULL != tmpShape) { + if (outputShape == NULL) { + return tmpShape; + } else { + vec4 qqq = tmpElement->GetQuaternion(); + const btTransform localTransform(btQuaternion(qqq.x(),qqq.y(),qqq.z(),qqq.w()), tmpElement->GetOrigin()); + outputShape->addChildShape(localTransform, tmpShape); + } + } + break; + } + case ewol::PhysicsShape::cone : { + const ewol::PhysicsCone* tmpElement = physiqueProperty[iii]->ToCone(); + if (NULL ==tmpElement) { + // ERROR ... + continue; + } + btCollisionShape* tmpShape = new btConeShape(tmpElement->GetRadius(), tmpElement->GetHeight()); + if (NULL != tmpShape) { + if (outputShape == NULL) { + return tmpShape; + } else { + vec4 qqq = tmpElement->GetQuaternion(); + const btTransform localTransform(btQuaternion(qqq.x(),qqq.y(),qqq.z(),qqq.w()), tmpElement->GetOrigin()); + outputShape->addChildShape(localTransform, tmpShape); + } + } + break; + } + case ewol::PhysicsShape::sphere : { + const ewol::PhysicsSphere* tmpElement = physiqueProperty[iii]->ToSphere(); + if (NULL ==tmpElement) { + // ERROR ... + continue; + } + btCollisionShape* tmpShape = new btSphereShape(tmpElement->GetRadius()); + if (NULL != tmpShape) { + if (outputShape == NULL) { + return tmpShape; + } else { + vec4 qqq = tmpElement->GetQuaternion(); + const btTransform localTransform(btQuaternion(qqq.x(),qqq.y(),qqq.z(),qqq.w()), tmpElement->GetOrigin()); + outputShape->addChildShape(localTransform, tmpShape); + } + } + break; + } + case ewol::PhysicsShape::convexHull : { + const ewol::PhysicsConvexHull* tmpElement = physiqueProperty[iii]->ToConvexHull(); + if (NULL ==tmpElement) { + // ERROR ... + continue; + } + btConvexHullShape* tmpShape = new btConvexHullShape(&(tmpElement->GetPointList()[0].x()), tmpElement->GetPointList().Size()); + if (NULL != tmpShape) { + if (outputShape == NULL) { + return tmpShape; + } else { + vec4 qqq = tmpElement->GetQuaternion(); + const btTransform localTransform(btQuaternion(qqq.x(),qqq.y(),qqq.z(),qqq.w()), tmpElement->GetOrigin()); + outputShape->addChildShape(localTransform, tmpShape); + } + } + break; + } + default : + // TODO : UNKNOW type ... + break; + } + } + if (NULL==outputShape) { + return new btEmptyShape(); + } + return outputShape; +} + + diff --git a/ege/CollisionShapeCreator.h b/ege/CollisionShapeCreator.h new file mode 100644 index 0000000..03eaa87 --- /dev/null +++ b/ege/CollisionShapeCreator.h @@ -0,0 +1,23 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + * + */ + +#ifndef __EGE_COLLISION_SHAPE_CREATOR_H__ +#define __EGE_COLLISION_SHAPE_CREATOR_H__ + +#include +#include +#include + +namespace ege { + namespace collision { + btCollisionShape* CreateShape(const ewol::Mesh* _mesh); + }; +}; +#endif + diff --git a/ege/ElementGame.cpp b/ege/ElementGame.cpp index 733b97e..0f13829 100644 --- a/ege/ElementGame.cpp +++ b/ege/ElementGame.cpp @@ -24,6 +24,8 @@ #include #include +#include + #undef __class__ #define __class__ "ElementGame" @@ -37,6 +39,8 @@ const etk::UString& ege::ElementGame::GetType(void) const ege::ElementGame::ElementGame(ege::Environement& _env) : m_env(_env), m_body(NULL), + m_uID(0), + m_mesh(NULL), m_shape(NULL), m_life(100), m_lifeMax(100), @@ -58,6 +62,7 @@ ege::ElementGame::~ElementGame(void) IADisable(); // same ... DynamicDisable(); + RemoveShape(); if (NULL != m_mesh) { // release the mesh ewol::resource::Release(m_mesh); @@ -66,11 +71,75 @@ ege::ElementGame::~ElementGame(void) delete(m_body); m_body = NULL; } - if (NULL != m_shape) { + EGE_DEBUG("Destroy element : uId=" << m_uID); +} + +void ege::ElementGame::RemoveShape(void) +{ + // no shape + if (NULL == m_shape) { + return; + } + // need to chek if the shape is the same as the mesh shape ... + if (m_mesh == NULL) { + // no mesh ==> standalone shape delete(m_shape); m_shape=NULL; + return; } - EGE_DEBUG("Destroy element : uId=" << m_uID); + if (m_shape != m_mesh->GetShape()) { + delete(m_shape); + m_shape=NULL; + return; + } + // otherwise : the shape is auto remove by the resources when no more needed ... +} + +void ege::ElementGame::FunctionFreeShape(void* _pointer) +{ + if (NULL==_pointer) { + return; + } + delete(static_cast(_pointer)); +} + +bool ege::ElementGame::LoadMesh(const etk::UString& _meshFileName) +{ + ewol::Mesh* tmpMesh=NULL; + ewol::resource::Keep(_meshFileName, tmpMesh); + if(NULL==tmpMesh) { + EGE_ERROR("can not load the resources : " << _meshFileName); + return false; + } + return SetMesh(tmpMesh); +} + +bool ege::ElementGame::SetMesh(ewol::Mesh* _mesh) +{ + if (NULL!=m_mesh) { + RemoveShape(); + ewol::resource::Release(m_mesh); + } + m_mesh = _mesh; + // auto load the shape : + if (NULL==m_mesh) { + return true; + } + if (NULL != m_mesh->GetShape()) { + m_shape = static_cast(m_mesh->GetShape()); + return true; + } + m_mesh->SetShape(ege::collision::CreateShape(m_mesh)); + m_mesh->SetFreeShapeFunction(&FunctionFreeShape); + m_shape = static_cast(m_mesh->GetShape()); + return true; +} + +bool ege::ElementGame::SetShape(btCollisionShape* _shape) +{ + RemoveShape(); + m_shape = _shape; + return true; } diff --git a/ege/ElementGame.h b/ege/ElementGame.h index b5f01fa..8987f09 100644 --- a/ege/ElementGame.h +++ b/ege/ElementGame.h @@ -32,6 +32,8 @@ namespace ege { class ElementGame { + private: + static void FunctionFreeShape(void* _pointer); protected: ege::Environement& m_env; protected: @@ -58,15 +60,46 @@ namespace ege * @return The requested Unique ID. */ inline uint32_t GetUID(void) const { return m_uID; }; - protected: + private: ewol::Mesh* m_mesh; //!< Mesh of the Element (can be NULL) btCollisionShape* m_shape; //!< shape of the element (set a copy here to have the debug display of it) public: /** * @brief Select a mesh with a specific name. * @param[in] _meshFileName Filename of the Mesh. + * @note Automaticly load the shape if it is specify in the mesh file + * @return true if no error occured */ - void LoadMesh(const etk::UString& _meshFileName); + bool LoadMesh(const etk::UString& _meshFileName); + /** + * @brief Set the the Mesh properties. + * @param[in] _mesh The mesh pointer. (NULL to force the mesh remove ...) + * @note : this remove the shape and the mesh properties. + * @return true if no error occured + */ + bool SetMesh(ewol::Mesh* _mesh); + /** + * @brief Set the shape properties. + * @param[in] _shape The shape pointer. + * @note : this remove the shape properties. + * @return true if no error occured + */ + bool SetShape(btCollisionShape* _shape); + /** + * @brief Get a pointer on the Mesh file. + * @return the mesh pointer. + */ + inline ewol::Mesh* GetMesh(void) { return m_mesh; }; + /** + * @brief Get a pointer on the bullet collision shape. + * @return the collision pointer. + */ + inline btCollisionShape* GetShape(void) { return m_shape; }; + private: + /** + * @brief Remove the curent selected shape. + */ + void RemoveShape(void); protected: float m_life; //!< Current life of the object float m_lifeMax; //!< Maximum possible life of the element diff --git a/ege/Environement.cpp b/ege/Environement.cpp index f4e56c8..30d94ec 100644 --- a/ege/Environement.cpp +++ b/ege/Environement.cpp @@ -175,8 +175,8 @@ void ege::Environement::AddCreator(const etk::UString& _type, ege::createElement ege::ElementGame* ege::Environement::CreateElement( const etk::UString& _type, const etk::UString* _description, - const ejson::Value* _value, - const exml::Node* _node, + ejson::Value* _value, + exml::Node* _node, bool _autoAddElement) { if (false==GetHachTableCreating().Exist(_type)) { @@ -237,12 +237,12 @@ ege::ElementGame* ege::Environement::CreateElement(const etk::UString& _type, co return CreateElement(_type, &_description, NULL, NULL, _autoAddElement); } -ege::ElementGame* ege::Environement::CreateElement(const etk::UString& _type, const ejson::Value* _value, bool _autoAddElement) +ege::ElementGame* ege::Environement::CreateElement(const etk::UString& _type, ejson::Value* _value, bool _autoAddElement) { return CreateElement(_type, NULL, _value, NULL, _autoAddElement); } -ege::ElementGame* ege::Environement::CreateElement(const etk::UString& _type, const exml::Node* _node, bool _autoAddElement) +ege::ElementGame* ege::Environement::CreateElement(const etk::UString& _type, exml::Node* _node, bool _autoAddElement) { return CreateElement(_type, NULL, NULL, _node, _autoAddElement); } diff --git a/ege/Environement.h b/ege/Environement.h index 9152b22..fec1764 100644 --- a/ege/Environement.h +++ b/ege/Environement.h @@ -22,8 +22,8 @@ namespace ege { class ElementGame; class Environement; typedef ege::ElementGame* (*createElement_string_tf)(ege::Environement& _env, const etk::UString& _description); - typedef ege::ElementGame* (*createElement_ejson_tf)(ege::Environement& _env, const ejson::Value* _value); - typedef ege::ElementGame* (*createElement_exml_tf)(ege::Environement& _env, const exml::Node* _node); + typedef ege::ElementGame* (*createElement_ejson_tf)(ege::Environement& _env, ejson::Value* _value); + typedef ege::ElementGame* (*createElement_exml_tf)(ege::Environement& _env, exml::Node* _node); class ElementInteraction { @@ -81,10 +81,10 @@ namespace ege { */ ege::ElementGame* CreateElement(const etk::UString& _type, bool _autoAddElement=true); ege::ElementGame* CreateElement(const etk::UString& _type, const etk::UString& _description, bool _autoAddElement=true); - ege::ElementGame* CreateElement(const etk::UString& _type, const ejson::Value* _value, bool _autoAddElement=true); - ege::ElementGame* CreateElement(const etk::UString& _type, const exml::Node* _node, bool _autoAddElement=true); + ege::ElementGame* CreateElement(const etk::UString& _type, ejson::Value* _value, bool _autoAddElement=true); + ege::ElementGame* CreateElement(const etk::UString& _type, exml::Node* _node, bool _autoAddElement=true); protected: - ege::ElementGame* CreateElement(const etk::UString& _type, const etk::UString* _description, const ejson::Value* _value, const exml::Node* _node, bool _autoAddElement); + ege::ElementGame* CreateElement(const etk::UString& _type, const etk::UString* _description, ejson::Value* _value, exml::Node* _node, bool _autoAddElement); public: class ResultNearestElement { diff --git a/lutin_ege.py b/lutin_ege.py index 75f781e..731bb33 100644 --- a/lutin_ege.py +++ b/lutin_ege.py @@ -12,6 +12,7 @@ def Create(target): 'ege/AudioElement.cpp', 'ege/AudioEngine.cpp', 'ege/Camera.cpp', + 'ege/CollisionShapeCreator.cpp', 'ege/ElementGame.cpp', 'ege/Particule.cpp', 'ege/ParticuleEngine.cpp',