[DEV] add dynamic shape at mesh

This commit is contained in:
Edouard DUPIN 2013-08-21 21:24:30 +02:00
parent 43bbec9af3
commit efca3ae4ba
7 changed files with 310 additions and 13 deletions

View File

@ -0,0 +1,171 @@
/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license BSD v3 (see license file)
*
*/
#include <ege/CollisionShapeCreator.h>
#include <btBulletCollisionCommon.h>
#include <BulletCollision/CollisionShapes/btConvexPolyhedron.h>
#include <BulletCollision/CollisionShapes/btShapeHull.h>
#include <BulletCollision/CollisionDispatch/btCollisionObject.h>
#include <ewol/renderer/resources/physicsShape/PhysicsShape.h>
#include <ewol/renderer/resources/physicsShape/PhysicsBox.h>
#include <ewol/renderer/resources/physicsShape/PhysicsCapsule.h>
#include <ewol/renderer/resources/physicsShape/PhysicsCone.h>
#include <ewol/renderer/resources/physicsShape/PhysicsConvexHull.h>
#include <ewol/renderer/resources/physicsShape/PhysicsCylinder.h>
#include <ewol/renderer/resources/physicsShape/PhysicsSphere.h>
// 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<ewol::PhysicsShape*>& physiqueProperty = _mesh->GetPhysicalProperties();
if (physiqueProperty.Size()==0) {
return new btEmptyShape();;
}
int32_t count = 0;
for (int32_t iii=0; iii<physiqueProperty.Size(); iii++) {
if (NULL==physiqueProperty[iii]) {
continue;
}
count++;
}
btCompoundShape* outputShape = NULL;
if (count>1) {
outputShape = new btCompoundShape();
}
for (int32_t iii=0; iii<physiqueProperty.Size(); iii++) {
if (NULL==physiqueProperty[iii]) {
continue;
}
switch (physiqueProperty[iii]->GetType()) {
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;
}

View File

@ -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 <etk/types.h>
#include <ewol/renderer/resources/Mesh.h>
#include <BulletCollision/CollisionShapes/btCollisionShape.h>
namespace ege {
namespace collision {
btCollisionShape* CreateShape(const ewol::Mesh* _mesh);
};
};
#endif

View File

@ -24,6 +24,8 @@
#include <btBulletDynamicsCommon.h>
#include <BulletCollision/CollisionDispatch/btCollisionObject.h>
#include <ege/CollisionShapeCreator.h>
#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<btCollisionShape*>(_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<btCollisionShape*>(m_mesh->GetShape());
return true;
}
m_mesh->SetShape(ege::collision::CreateShape(m_mesh));
m_mesh->SetFreeShapeFunction(&FunctionFreeShape);
m_shape = static_cast<btCollisionShape*>(m_mesh->GetShape());
return true;
}
bool ege::ElementGame::SetShape(btCollisionShape* _shape)
{
RemoveShape();
m_shape = _shape;
return true;
}

View File

@ -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

View File

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

View File

@ -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
{

View File

@ -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',