[DEV] collision implementation done

This commit is contained in:
Edouard DUPIN 2014-12-04 22:13:54 +01:00
parent 2b1c2619c7
commit bc20095852
5 changed files with 151 additions and 32 deletions

View File

@ -39,7 +39,8 @@ ege::ElementPhysic::ElementPhysic(const std::shared_ptr<ege::Environement>& _env
m_body(nullptr),
m_shape(nullptr),
m_elementInPhysicsSystem(false),
m_IA(nullptr) {
m_IA(nullptr),
m_detectCollisionEnable(false) {
if (_autoRigidBody == true) {
createRigidBody();
} else {
@ -447,3 +448,22 @@ void ege::ElementPhysic::setAngularVelocity(const vec3& _value) {
m_body->setAngularVelocity(_value);
}
void ege::ElementPhysic::setCollisionDetectionStatus(bool _status) {
if (m_body == nullptr) {
EGE_WARNING("no body");
return;
}
if (m_detectCollisionEnable == _status) {
return;
}
m_detectCollisionEnable = _status;
if (m_detectCollisionEnable == true) {
m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
} else {
if ((m_body->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) != 0) {
m_body->setCollisionFlags(m_body->getCollisionFlags() - btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
}
}
}

View File

@ -180,6 +180,28 @@ namespace ege {
const std::shared_ptr<ewol::resource::Colored3DObject>& _draw,
mat4 _transformationMatrix,
std::vector<vec3> _tmpVertices);
protected:
bool m_detectCollisionEnable; //!< physic collision detect enable.
public:
/**
* @brief get collision status of the object.
* @return the collision status.
*/
bool getCollisionDetectionStatus() {
return m_detectCollisionEnable;
}
/**
* @brief Change enable status of the object.
* @param[in] _status new requested status.
*/
void setCollisionDetectionStatus(bool _status=true);
/**
* @brief when a collision is detected with an other object (just after calculate data update
* @param[in] _obj the Other object
* @param[in] _point Position of the impact in the global world
* @param[in] _normal Normal of the impact
*/
virtual void onCollisionDetected(const std::shared_ptr<ege::Element>& _obj, const vec3& _point, const vec3& _normal) {};
};
};

View File

@ -8,6 +8,7 @@
#include <ege/physics/Engine.h>
#include <ege/debug.h>
#include <ewol/openGL/openGL.h>
#include <etk/math/Matrix4.h>
@ -24,9 +25,36 @@
#include <btBulletDynamicsCommon.h>
#include <BulletCollision/CollisionDispatch/btCollisionObject.h>
#include <ege/elements/ElementPhysic.h>
// unique callback function :
extern ContactProcessedCallback gContactProcessedCallback;
// TODO : remove double collision call ...
static bool handleContactsProcess(btManifoldPoint& _point, btCollisionObject* _body0, btCollisionObject* _body1) {
ege::ElementPhysic* elem0 = static_cast<ege::ElementPhysic*>(_body0->getUserPointer());
ege::ElementPhysic* elem1 = static_cast<ege::ElementPhysic*>(_body1->getUserPointer());
if ( elem0 == nullptr
|| elem1 == nullptr) {
EGE_WARNING("callback of collision error");
return false;
}
EGE_VERBOSE("collision process between " << elem0->getUID() << " && " << elem1->getUID() << " pos=" << _point.getPositionWorldOnA() << " norm=" << _point.m_normalWorldOnB);
if (elem0->getCollisionDetectionStatus() == true) {
elem0->onCollisionDetected(elem1->shared_from_this(), _point.getPositionWorldOnA(), -_point.m_normalWorldOnB);
}
if (elem1->getCollisionDetectionStatus() == true) {
elem1->onCollisionDetected(elem0->shared_from_this(), _point.getPositionWorldOnA(), _point.m_normalWorldOnB);
}
return true;
}
ege::physics::Engine::Engine() {
setBulletConfig();
// set callback for collisions ...
gContactProcessedCallback = (ContactProcessedCallback)handleContactsProcess;
}
ege::physics::Engine::~Engine() {
@ -75,7 +103,36 @@ void ege::physics::Engine::setBulletConfig(std::shared_ptr<btDefaultCollisionCon
// By default we set no gravity
m_dynamicsWorld->setGravity(btVector3(0,0,0));
}
//m_env.setDynamicWorld(m_dynamicsWorld);
}
// some doccumantation : http://www.bulletphysics.org/mediawiki-1.5.8/index.php?title=Collision_Callbacks_and_Triggers
std::vector<ege::physics::Engine::collisionPoints> ege::physics::Engine::getListOfCollision() {
std::vector<collisionPoints> out;
if (m_dynamicsWorld != nullptr) {
int32_t numManifolds = m_dynamicsWorld->getDispatcher()->getNumManifolds();
for (int i=0;i<numManifolds;i++) {
btPersistentManifold* contactManifold = m_dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
const btCollisionObject* obA = static_cast<const btCollisionObject*>(contactManifold->getBody0());
const btCollisionObject* obB = static_cast<const btCollisionObject*>(contactManifold->getBody1());
if ( obA == nullptr
|| obB == nullptr) {
continue;
}
ege::ElementPhysic* elem0 = static_cast<ege::ElementPhysic*>(obA->getUserPointer());
ege::ElementPhysic* elem1 = static_cast<ege::ElementPhysic*>(obB->getUserPointer());
if ( elem0 == nullptr
|| elem1 == nullptr) {
continue;
}
int numContacts = contactManifold->getNumContacts();
for (int j=0;j<numContacts;j++) {
btManifoldPoint& pt = contactManifold->getContactPoint(j);
if (pt.getDistance()<0.f) {
out.push_back(collisionPoints(elem0->shared_from_this(), elem1->shared_from_this(), pt.getPositionWorldOnA(), pt.getPositionWorldOnB(), pt.m_normalWorldOnB));
}
}
}
}
return out;
}

View File

@ -25,6 +25,7 @@ namespace ege {
#include <ewol/resource/Manager.h>
#include <ewol/Dimension.h>
class btBroadphaseInterface;
class btCollisionShape;
class btOverlappingPairCache;
@ -36,6 +37,7 @@ class btDynamicsWorld;
#include <LinearMath/btScalar.h>
class btVector3;
//#include <ege/elements/Element.h>
namespace ege {
@ -70,6 +72,32 @@ namespace ege {
std::shared_ptr<btDynamicsWorld> getDynamicWorld() {
return m_dynamicsWorld;
};
public:
// Define a collision point ==> for debug only ...
//! @not-in-doc
class collisionPoints {
public:
std::shared_ptr<ege::Element> elem1;
std::shared_ptr<ege::Element> elem2;
vec3 positionElem1;
vec3 positionElem2;
vec3 normalElem2;
collisionPoints(const std::shared_ptr<ege::Element>& _elem1,
const std::shared_ptr<ege::Element>& _elem2,
const vec3& _pos1,
const vec3& _pos2,
const vec3& _normal) :
elem1(_elem1),
elem2(_elem2),
positionElem1(_pos1),
positionElem2(_pos2),
normalElem2(_normal) { }
};
/**
* @brief Get the list of all collision point actually availlable ...
* @return the requested list of points
*/
std::vector<ege::physics::Engine::collisionPoints> getListOfCollision();
};
};
};

View File

@ -20,12 +20,6 @@
#include <ege/physicsShape/PhysicsBox.h>
#include <ege/physicsShape/PhysicsSphere.h>
#include <BulletDynamics/Dynamics/btRigidBody.h>
#include <LinearMath/btDefaultMotionState.h>
#include <BulletDynamics/Dynamics/btDynamicsWorld.h>
#include <BulletCollision/CollisionShapes/btCollisionShape.h>
#undef __class__
#define __class__ "Windows"
@ -145,6 +139,20 @@ void appl::Windows::init() {
}
}
namespace appl {
class ElementHerit : public ege::ElementPhysic {
public:
ElementHerit(const std::shared_ptr<ege::Environement>& _env, bool _autoRigidBody=true) :
ege::ElementPhysic(_env, _autoRigidBody) {
setCollisionDetectionStatus(true);
}
virtual void onCollisionDetected(const std::shared_ptr<ege::Element>& _obj, const vec3& _point, const vec3& _normal) {
APPL_WARNING("[" << getUID() << "] collision : pos=" << _point << " norm=" <<_normal);
}
};
}
bool appl::Windows::onEventInput(const ewol::event::Input& _event) {
static float ploppp=1;
if (_event.getId() == 1) {
@ -155,7 +163,7 @@ bool appl::Windows::onEventInput(const ewol::event::Input& _event) {
std::shared_ptr<ege::resource::Mesh> myMesh;
myMesh = ege::resource::Mesh::createCube(1, "basics", etk::color::green);
if (myMesh != nullptr) {
std::shared_ptr<ege::ElementPhysic> element = std::make_shared<ege::ElementPhysic>(m_env);
std::shared_ptr<appl::ElementHerit> element = std::make_shared<appl::ElementHerit>(m_env);
std::shared_ptr<ege::PhysicsBox> physic = std::make_shared<ege::PhysicsBox>();
physic->setSize(vec3(1.01,1.01,1.01));
myMesh->addPhysicElement(physic);
@ -216,30 +224,14 @@ bool appl::Windows::onEventInput(const ewol::event::Input& _event) {
return false;
}
//! http://www.bulletphysics.org/mediawiki-1.5.8/index.php?title=Collision_Callbacks_and_Triggers
// manually detect collision : (loop to detect cillisions ...
void appl::Windows::onCallbackPeriodicCheckCollision(const ewol::event::Time& _event) {
int32_t numManifolds = m_env->getPhysicEngine().getDynamicWorld()->getDispatcher()->getNumManifolds();
if (numManifolds != 0) {
APPL_ERROR("numManifolds=" << numManifolds);
std::vector<ege::physics::Engine::collisionPoints> list = m_env->getPhysicEngine().getListOfCollision();
if (list.size() != 0) {
APPL_INFO("num contact =" << list.size());
}
for (int i=0;i<numManifolds;i++) {
btPersistentManifold* contactManifold = m_env->getPhysicEngine().getDynamicWorld()->getDispatcher()->getManifoldByIndexInternal(i);
const btCollisionObject* obA = static_cast<const btCollisionObject*>(contactManifold->getBody0());
const btCollisionObject* obB = static_cast<const btCollisionObject*>(contactManifold->getBody1());
int numContacts = contactManifold->getNumContacts();
if (numContacts != 0) {
APPL_ERROR(" numContacts=" << numContacts);
}
for (int j=0;j<numContacts;j++) {
btManifoldPoint& pt = contactManifold->getContactPoint(j);
if (pt.getDistance()<0.f) {
const vec3& ptA = pt.getPositionWorldOnA();
const vec3& ptB = pt.getPositionWorldOnB();
const vec3& normalOnB = pt.m_normalWorldOnB;
APPL_ERROR(" point1=" << ptA << " point2=" << ptB << " normal=" << normalOnB);
}
}
for (size_t iii=0;iii<list.size();++iii) {
APPL_ERROR(" [" << list[iii].elem1->getUID() << "]:point1=" << list[iii].positionElem1 << " [" << list[iii].elem1->getUID() << "]:point2=" << list[iii].positionElem2 << " normal=" << list[iii].normalElem2);
}
}