ege/ege/elements/ElementPhysic.cpp

489 lines
14 KiB
C++

/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
*******************************************
** IS REMOVED
*******************************************
#include <etk/types.hpp>
#include <ege/debug.hpp>
#include <ege/elements/ElementPhysic.hpp>
#include <ege/Environement.hpp>
#include <ege/CollisionShapeCreator.hpp>
const etk::String& ege::ElementPhysic::getType() const {
static const etk::String nameType("----");
return nameType;
}
ege::ElementPhysic::ElementPhysic(const ememory::SharedPtr<ege::Environement>& _env, bool _autoRigidBody) ://, float _mass) :
ege::Element(_env),
m_body(null),
//m_shape(null),
m_elementInPhysicsSystem(false),
m_IA(null),
m_detectCollisionEnable(false) {
if (_autoRigidBody == true) {
createRigidBody();
} else {
EGE_TODO("add basic API to create custum rigid body");
}
}
ege::ElementPhysic::~ElementPhysic() {
// in every case remove IA
//iaDisable();
// same ...
//dynamicDisable();
//removeShape();
// Destroy the rigid body
//m_dynamicsWorld->destroyRigidBody(m_body);
m_body = null;
}
void ege::ElementPhysic::createRigidBody(float _mass, bool _static) {
// Initial position and orientation of the rigid body
rp3d::Vector3 initPosition(0.0, 3.0, 0.0);
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
// Create a rigid body in the world
m_body = null;//m_dynamicsWorld->createRigidBody(transform);
/*
if (_static = true) {
m_body->setType(STATIC);
//m_body->setType(KINEMATIC);
// Disable gravity for this body
m_body->enableGravity(false);
} else {
m_body->setType(DYNAMIC);
}
*/
}
bool ege::ElementPhysic::setMesh(ememory::SharedPtr<ege::resource::Mesh> _mesh) {
EGE_WARNING("Set Mesh");
if (m_mesh != null) {
//removeShape();
}
ege::Element::setMesh(_mesh);
// auto load the shape:
if (m_mesh == null) {
return true;
}
/*
if (m_mesh->getShape() != null) {
EGE_WARNING("create shape whith mesh internal shape ...");
m_shape = static_cast<btCollisionShape*>(m_mesh->getShape());
return true;
}
EGE_DEBUG("create the mesh shape with the mesh");
m_mesh->setShape(ege::collision::createShape(m_mesh));
EGE_DEBUG("set remove function shape");
m_mesh->setFreeShapeFunction(&FunctionFreeShape);
m_shape = static_cast<btCollisionShape*>(m_mesh->getShape());
vec3 localInertia(0,0,0);
m_shape->calculateLocalInertia(50000000, localInertia); // TODO : BETTER ///
*/
return true;
}
/*
bool ege::ElementPhysic::setShape(btCollisionShape* _shape) {
EGE_DEBUG("Set Shape");
removeShape();
m_shape = _shape;
if (_shape == null) {
EGE_WARNING("Remove shape ...");
} else {
EGE_INFO("set shape ...");
}
return true;
}
void ege::ElementPhysic::removeShape() {
// no shape
if (m_shape == null) {
return;
}
// need to chek if the shape is the same as the mesh shape ...
if (m_mesh == null) {
// no mesh == > standalone shape
ETK_DELETE(btCollisionShape, m_shape);
m_shape=null;
EGE_WARNING("Remove shape .2.");
return;
}
if (m_shape != m_mesh->getShape()) {
ETK_DELETE(btCollisionShape, m_shape);
m_shape=null;
EGE_WARNING("Remove shape .3.");
return;
}
// otherwise : the shape is auto remove by the resources when no more needed ...
}
void ege::ElementPhysic::FunctionFreeShape(void* _pointer) {
if (_pointer == null) {
return;
}
ETK_DELETE(btCollisionShape, _pointer);
}
*/
void ege::ElementPhysic::setPosition(const vec3& _pos) {
if (m_body != null) {
/*
btTransform transformation = m_body->getCenterOfMassTransform();
transformation.setOrigin(_pos);
m_body->setCenterOfMassTransform(transformation);
*/
}
}
const vec3& ege::ElementPhysic::getPosition() {
/*
if (m_body != null) {
return m_body->getCenterOfMassPosition();
}
*/
return ege::Element::getPosition();
};
const vec3& ege::ElementPhysic::getSpeed() {
static vec3 emptySpeed(0,0,0);
/*
if (m_body != null) {
return m_body->getLinearVelocity();
}
*/
return emptySpeed;
};
const float ege::ElementPhysic::getInvMass() {
/*
if (m_body != null) {
return m_body->getInvMass();
}
*/
return 0.0000000001f;
};
void ege::ElementPhysic::drawShape(/*const btCollisionShape* _shape,*/
ememory::SharedPtr<ewol::resource::Colored3DObject> _draw,
mat4 _transformationMatrix,
etk::Vector<vec3> _tmpVertices) {
#if 0
if( _draw == null
|| _shape == null) {
return;
}
etk::Color<float> tmpColor(1.0, 0.0, 0.0, 0.3);
//EGE_DEBUG(" draw (6): !btIDebugDraw::DBG_DrawWireframe");
int shapetype=_shape->getShapeType();
switch (shapetype) {
case SPHERE_SHAPE_PROXYTYPE: {
// Sphere collision shape ...
EGE_DEBUG(" draw (01): SPHERE_SHAPE_PROXYTYPE");
const btSphereShape* sphereShape = static_cast<const btSphereShape*>(_shape);
float radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin
_draw->drawSphere(radius, 10, 10, _transformationMatrix, tmpColor);
break;
}
case BOX_SHAPE_PROXYTYPE: {
// Box collision shape ...
EGE_DEBUG(" draw (02): BOX_SHAPE_PROXYTYPE");
const btBoxShape* boxShape = static_cast<const btBoxShape*>(_shape);
vec3 halfExtent = boxShape->getHalfExtentsWithMargin();
_draw->drawSquare(halfExtent, _transformationMatrix, tmpColor);
break;
}
case CONE_SHAPE_PROXYTYPE: {
// Cone collision shape ...
EGE_DEBUG(" draw (03): CONE_SHAPE_PROXYTYPE");
break;
}
case CAPSULE_SHAPE_PROXYTYPE: {
// Capsule collision shape ...
EGE_DEBUG(" draw (04): CAPSULE_SHAPE_PROXYTYPE");
break;
}
case CYLINDER_SHAPE_PROXYTYPE: {
// Cylinder collision shape ...
EGE_DEBUG(" draw (05): CYLINDER_SHAPE_PROXYTYPE");
break;
}
case CONVEX_HULL_SHAPE_PROXYTYPE: {
// Convex Hull collision shape ...
EGE_DEBUG(" draw (06): CONVEX_HULL_SHAPE_PROXYTYPE");
if (_shape->isConvex()) {
EGE_DEBUG(" shape->isConvex()");
const btConvexPolyhedron* poly = _shape->isPolyhedral() ? ((btPolyhedralConvexShape*) _shape)->getConvexPolyhedron() : 0;
if (null!=poly) {
EGE_DEBUG(" have poly");
/*
glBegin(GL_TRIANGLES);
for (int32_t iii=0 ; iii<poly->m_faces.size() ; iii++) {
btVector3 centroid(0,0,0);
int numVerts = poly->m_faces[iii].m_indices.size();
if (numVerts>2) {
btVector3 v1 = poly->m_vertices[poly->m_faces[iii].m_indices[0]];
for (int32_t vvv=0;vvv<poly->m_faces[iii].m_indices.size()-2;vvv++) {
btVector3 v2 = poly->m_vertices[poly->m_faces[iii].m_indices[vvv+1]];
btVector3 v3 = poly->m_vertices[poly->m_faces[iii].m_indices[vvv+2]];
btVector3 normal = (v3-v1).cross(v2-v1);
normal.normalize ();
glNormal3f(normal.getX(),normal.getY(),normal.getZ());
glVertex3f (v1.x(), v1.y(), v1.z());
glVertex3f (v2.x(), v2.y(), v2.z());
glVertex3f (v3.x(), v3.y(), v3.z());
}
}
}
glEnd();
*/
} else {
// TODO : set it back ...
/*
ShapeCache* sc=cache((btConvexShape*)_shape);
//glutSolidCube(1.0);
btShapeHull* hull = &sc->m_shapehull;
if (hull->numTriangles () > 0) {
int index = 0;
const unsigned int* idx = hull->getIndexPointer();
const btVector3* vtx = hull->getVertexPointer();
glBegin (GL_TRIANGLES);
for (int i = 0; i < hull->numTriangles(); i++) {
int i1 = index++;
int i2 = index++;
int i3 = index++;
btAssert(i1 < hull->numIndices() &&
i2 < hull->numIndices() &&
i3 < hull->numIndices());
int index1 = idx[i1];
int index2 = idx[i2];
int index3 = idx[i3];
btAssert(index1 < hull->numVertices() &&
index2 < hull->numVertices() &&
index3 < hull->numVertices());
btVector3 v1 = vtx[index1];
btVector3 v2 = vtx[index2];
btVector3 v3 = vtx[index3];
btVector3 normal = (v3-v1).cross(v2-v1);
normal.normalize();
glNormal3f(normal.getX(),normal.getY(),normal.getZ());
glVertex3f (v1.x(), v1.y(), v1.z());
glVertex3f (v2.x(), v2.y(), v2.z());
glVertex3f (v3.x(), v3.y(), v3.z());
}
glEnd ();
}
*/
}
} else {
EGE_DEBUG(" !!! shape is NOT Convex() !!!");
}
break;
}
case COMPOUND_SHAPE_PROXYTYPE: {
// Multiple sub element collision shape ...
EGE_DEBUG(" draw (07): COMPOUND_SHAPE_PROXYTYPE");
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(_shape);
for (int32_t iii=compoundShape->getNumChildShapes()-1;iii >= 0;iii--) {
btTransform childTrans = compoundShape->getChildTransform(iii);
const btCollisionShape* colShape = compoundShape->getChildShape(iii);
btScalar mmm[16];
childTrans.getOpenGLMatrix(mmm);
mat4 transformationMatrix(mmm);
transformationMatrix.transpose();
transformationMatrix = _transformationMatrix * transformationMatrix;
drawShape(colShape, _draw, transformationMatrix, _tmpVertices);
}
break;
}
case EMPTY_SHAPE_PROXYTYPE: {
// No collision shape ...
EGE_DEBUG(" draw (08): EMPTY_SHAPE_PROXYTYPE");
// nothing to display ...
break;
}
default: {
// must be done later ...
EGE_DEBUG(" draw (09): default");
}
}
#endif
}
void ege::ElementPhysic::draw(int32_t _pass) {
if (m_elementInPhysicsSystem == false) {
return;
}
/*
//EGE_INFO("draw : " << _pass );
if (_pass == 0) {
if( m_body != null
&& m_mesh != null) {
//EGE_INFO("element pos = " << getPosition());
float mmm[16];
// Get the interpolated transform of the rigid body
rp3d::Transform transform = m_body->getInterpolatedTransform();
// Get the OpenGL matrix array of the transform
transform.getOpenGLMatrix(matrix);
//EGE_INFO(" mat = " << mat4(mmm));
mat4 transformationMatrix(mmm);
//mat4 transformationMatrix = mat4(mmm) * etk::matScale(vec3(20,20,20));
// TODO: check this : transformationMatrix.transpose();
m_mesh->draw(transformationMatrix);
}
}
*/
}
void ege::ElementPhysic::dynamicEnable() {
if (m_elementInPhysicsSystem == true) {
return;
}
if(m_body != null) {
EGE_VERBOSE("dynamicEnable : RigidBody");
//m_env->getPhysicEngine().getDynamicWorld()->addRigidBody(m_body);
}
if(m_IA != null) {
EGE_VERBOSE("dynamicEnable : IA");
//m_env->getPhysicEngine().getDynamicWorld()->addAction(m_IA);
}
m_elementInPhysicsSystem = true;
}
void ege::ElementPhysic::dynamicDisable() {
if (m_elementInPhysicsSystem == false) {
return;
}
if(m_IA != null) {
EGE_VERBOSE("dynamicDisable : IA");
//m_env->getPhysicEngine().getDynamicWorld()->removeAction(m_IA);
}
if(m_body != null) {
EGE_VERBOSE("dynamicDisable : RigidBody");
// Unlink element from the engine
//m_env->getPhysicEngine().getDynamicWorld()->removeRigidBody(m_body);
//m_env->getPhysicEngine().getDynamicWorld()->removeCollisionObject(m_body);
}
m_elementInPhysicsSystem = false;
}
void ege::ElementPhysic::iaEnable() {
if (m_IA != null) {
// IA already started ...
return;
}
m_IA = ETK_NEW(localIA, *this);
if (m_IA == null) {
EGE_ERROR("Can not start the IA == > allocation error");
return;
}
if (m_elementInPhysicsSystem == true) {
//m_env->getPhysicEngine().getDynamicWorld()->addAction(m_IA);
}
}
void ege::ElementPhysic::iaDisable() {
if (m_IA == null) {
// IA already stopped ...
return;
}
if (m_elementInPhysicsSystem == true) {
//m_env->getPhysicEngine().getDynamicWorld()->removeAction(m_IA);
}
// remove IA:
ETK_DELETE(localIA, m_IA);
m_IA = null;
}
void ege::ElementPhysic::setMass(float _value) {
if (m_body == null) {
return;
}
/*
vec3 localInertia(0,0,0);
if (_value != 0.0f && getShape()!=null) {
//getShape()->calculateLocalInertia(_value, localInertia);
EWOL_ERROR("Update inertia calculated : " << localInertia);
}
m_body->setMassProps(_value, localInertia);
*/
}
void ege::ElementPhysic::setLinearVelocity(const vec3& _value) {
if (m_body == null) {
EGE_WARNING("no body");
return;
}
// Force vector (in Newton)
rp3d::Vector3 force(_value.x(), _value.y(), _value.z());
// Apply a force to the center of the body
m_body->applyForceToCenterOfMass(force);
}
void ege::ElementPhysic::setTorqueImpulse(const vec3& _value) {
if (m_body == null) {
EGE_WARNING("no body");
return;
}
// Torque vector
rp3d::Vector3 torque(_value.x(), _value.y(), _value.z());
// Apply a torque to the body
m_body->applyTorque(torque);
}
void ege::ElementPhysic::setAngularVelocity(const vec3& _value) {
if (m_body == null) {
EGE_WARNING("no body");
return;
}
//m_body->setAngularVelocity(_value);
}
/*
btQuaternion ege::ElementPhysic::getOrientation() const {
if (m_body == null) {
EGE_WARNING("no body");
return btQuaternion(0,0,0,0);
}
//return m_body->getOrientation();
return btQuaternion(0,0,0,0);
}
*/
void ege::ElementPhysic::setCollisionDetectionStatus(bool _status) {
if (m_body == null) {
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);
}
}
*/
}