1165 lines
27 KiB
C++
1165 lines
27 KiB
C++
|
/*! \file btGImpactShape.h
|
|||
|
\author Francisco Len N<EFBFBD>jera
|
|||
|
*/
|
|||
|
/*
|
|||
|
This source file is part of GIMPACT Library.
|
|||
|
|
|||
|
For the latest info, see http://gimpact.sourceforge.net/
|
|||
|
|
|||
|
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
|
|||
|
email: projectileman@yahoo.com
|
|||
|
|
|||
|
|
|||
|
This software is provided 'as-is', without any express or implied warranty.
|
|||
|
In no event will the authors be held liable for any damages arising from the use of this software.
|
|||
|
Permission is granted to anyone to use this software for any purpose,
|
|||
|
including commercial applications, and to alter it and redistribute it freely,
|
|||
|
subject to the following restrictions:
|
|||
|
|
|||
|
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
|||
|
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
|||
|
3. This notice may not be removed or altered from any source distribution.
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
#ifndef GIMPACT_SHAPE_H
|
|||
|
#define GIMPACT_SHAPE_H
|
|||
|
|
|||
|
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
|||
|
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
|
|||
|
#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
|
|||
|
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
|
|||
|
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
|
|||
|
#include "BulletCollision/CollisionShapes/btConcaveShape.h"
|
|||
|
#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
|
|||
|
#include "LinearMath/btVector3.h"
|
|||
|
#include "LinearMath/btTransform.h"
|
|||
|
#include "LinearMath/btMatrix3x3.h"
|
|||
|
#include "LinearMath/btAlignedObjectArray.h"
|
|||
|
|
|||
|
#include "btGImpactQuantizedBvh.h" // box tree class
|
|||
|
|
|||
|
|
|||
|
//! declare Quantized trees, (you can change to float based trees)
|
|||
|
typedef btGImpactQuantizedBvh btGImpactBoxSet;
|
|||
|
|
|||
|
enum eGIMPACT_SHAPE_TYPE
|
|||
|
{
|
|||
|
CONST_GIMPACT_COMPOUND_SHAPE = 0,
|
|||
|
CONST_GIMPACT_TRIMESH_SHAPE_PART,
|
|||
|
CONST_GIMPACT_TRIMESH_SHAPE
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//! Helper class for tetrahedrons
|
|||
|
class btTetrahedronShapeEx:public btBU_Simplex1to4
|
|||
|
{
|
|||
|
public:
|
|||
|
btTetrahedronShapeEx()
|
|||
|
{
|
|||
|
m_numVertices = 4;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
SIMD_FORCE_INLINE void setVertices(
|
|||
|
const btVector3 & v0,const btVector3 & v1,
|
|||
|
const btVector3 & v2,const btVector3 & v3)
|
|||
|
{
|
|||
|
m_vertices[0] = v0;
|
|||
|
m_vertices[1] = v1;
|
|||
|
m_vertices[2] = v2;
|
|||
|
m_vertices[3] = v3;
|
|||
|
recalcLocalAabb();
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
//! Base class for gimpact shapes
|
|||
|
class btGImpactShapeInterface : public btConcaveShape
|
|||
|
{
|
|||
|
protected:
|
|||
|
btAABB m_localAABB;
|
|||
|
bool m_needs_update;
|
|||
|
btVector3 localScaling;
|
|||
|
btGImpactBoxSet m_box_set;// optionally boxset
|
|||
|
|
|||
|
//! use this function for perfofm refit in bounding boxes
|
|||
|
//! use this function for perfofm refit in bounding boxes
|
|||
|
virtual void calcLocalAABB()
|
|||
|
{
|
|||
|
lockChildShapes();
|
|||
|
if(m_box_set.getNodeCount() == 0)
|
|||
|
{
|
|||
|
m_box_set.buildSet();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
m_box_set.update();
|
|||
|
}
|
|||
|
unlockChildShapes();
|
|||
|
|
|||
|
m_localAABB = m_box_set.getGlobalBox();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public:
|
|||
|
btGImpactShapeInterface()
|
|||
|
{
|
|||
|
m_shapeType=GIMPACT_SHAPE_PROXYTYPE;
|
|||
|
m_localAABB.invalidate();
|
|||
|
m_needs_update = true;
|
|||
|
localScaling.setValue(1.f,1.f,1.f);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//! performs refit operation
|
|||
|
/*!
|
|||
|
Updates the entire Box set of this shape.
|
|||
|
\pre postUpdate() must be called for attemps to calculating the box set, else this function
|
|||
|
will does nothing.
|
|||
|
\post if m_needs_update == true, then it calls calcLocalAABB();
|
|||
|
*/
|
|||
|
SIMD_FORCE_INLINE void updateBound()
|
|||
|
{
|
|||
|
if(!m_needs_update) return;
|
|||
|
calcLocalAABB();
|
|||
|
m_needs_update = false;
|
|||
|
}
|
|||
|
|
|||
|
//! If the Bounding box is not updated, then this class attemps to calculate it.
|
|||
|
/*!
|
|||
|
\post Calls updateBound() for update the box set.
|
|||
|
*/
|
|||
|
void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
|
|||
|
{
|
|||
|
btAABB transformedbox = m_localAABB;
|
|||
|
transformedbox.appy_transform(t);
|
|||
|
aabbMin = transformedbox.m_min;
|
|||
|
aabbMax = transformedbox.m_max;
|
|||
|
}
|
|||
|
|
|||
|
//! Tells to this object that is needed to refit the box set
|
|||
|
virtual void postUpdate()
|
|||
|
{
|
|||
|
m_needs_update = true;
|
|||
|
}
|
|||
|
|
|||
|
//! Obtains the local box, which is the global calculated box of the total of subshapes
|
|||
|
SIMD_FORCE_INLINE const btAABB & getLocalBox()
|
|||
|
{
|
|||
|
return m_localAABB;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
virtual int getShapeType() const
|
|||
|
{
|
|||
|
return GIMPACT_SHAPE_PROXYTYPE;
|
|||
|
}
|
|||
|
|
|||
|
/*!
|
|||
|
\post You must call updateBound() for update the box set.
|
|||
|
*/
|
|||
|
virtual void setLocalScaling(const btVector3& scaling)
|
|||
|
{
|
|||
|
localScaling = scaling;
|
|||
|
postUpdate();
|
|||
|
}
|
|||
|
|
|||
|
virtual const btVector3& getLocalScaling() const
|
|||
|
{
|
|||
|
return localScaling;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
virtual void setMargin(btScalar margin)
|
|||
|
{
|
|||
|
m_collisionMargin = margin;
|
|||
|
int i = getNumChildShapes();
|
|||
|
while(i--)
|
|||
|
{
|
|||
|
btCollisionShape* child = getChildShape(i);
|
|||
|
child->setMargin(margin);
|
|||
|
}
|
|||
|
|
|||
|
m_needs_update = true;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//! Subshape member functions
|
|||
|
//!@{
|
|||
|
|
|||
|
//! Base method for determinig which kind of GIMPACT shape we get
|
|||
|
virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const = 0 ;
|
|||
|
|
|||
|
//! gets boxset
|
|||
|
SIMD_FORCE_INLINE const btGImpactBoxSet * getBoxSet() const
|
|||
|
{
|
|||
|
return &m_box_set;
|
|||
|
}
|
|||
|
|
|||
|
//! Determines if this class has a hierarchy structure for sorting its primitives
|
|||
|
SIMD_FORCE_INLINE bool hasBoxSet() const
|
|||
|
{
|
|||
|
if(m_box_set.getNodeCount() == 0) return false;
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
//! Obtains the primitive manager
|
|||
|
virtual const btPrimitiveManagerBase * getPrimitiveManager() const = 0;
|
|||
|
|
|||
|
|
|||
|
//! Gets the number of children
|
|||
|
virtual int getNumChildShapes() const = 0;
|
|||
|
|
|||
|
//! if true, then its children must get transforms.
|
|||
|
virtual bool childrenHasTransform() const = 0;
|
|||
|
|
|||
|
//! Determines if this shape has triangles
|
|||
|
virtual bool needsRetrieveTriangles() const = 0;
|
|||
|
|
|||
|
//! Determines if this shape has tetrahedrons
|
|||
|
virtual bool needsRetrieveTetrahedrons() const = 0;
|
|||
|
|
|||
|
virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const = 0;
|
|||
|
|
|||
|
virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const = 0;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//! call when reading child shapes
|
|||
|
virtual void lockChildShapes() const
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
virtual void unlockChildShapes() const
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
//! if this trimesh
|
|||
|
SIMD_FORCE_INLINE void getPrimitiveTriangle(int index,btPrimitiveTriangle & triangle) const
|
|||
|
{
|
|||
|
getPrimitiveManager()->get_primitive_triangle(index,triangle);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//! Retrieves the bound from a child
|
|||
|
/*!
|
|||
|
*/
|
|||
|
virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
|
|||
|
{
|
|||
|
btAABB child_aabb;
|
|||
|
getPrimitiveManager()->get_primitive_box(child_index,child_aabb);
|
|||
|
child_aabb.appy_transform(t);
|
|||
|
aabbMin = child_aabb.m_min;
|
|||
|
aabbMax = child_aabb.m_max;
|
|||
|
}
|
|||
|
|
|||
|
//! Gets the children
|
|||
|
virtual btCollisionShape* getChildShape(int index) = 0;
|
|||
|
|
|||
|
|
|||
|
//! Gets the child
|
|||
|
virtual const btCollisionShape* getChildShape(int index) const = 0;
|
|||
|
|
|||
|
//! Gets the children transform
|
|||
|
virtual btTransform getChildTransform(int index) const = 0;
|
|||
|
|
|||
|
//! Sets the children transform
|
|||
|
/*!
|
|||
|
\post You must call updateBound() for update the box set.
|
|||
|
*/
|
|||
|
virtual void setChildTransform(int index, const btTransform & transform) = 0;
|
|||
|
|
|||
|
//!@}
|
|||
|
|
|||
|
|
|||
|
//! virtual method for ray collision
|
|||
|
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
|
|||
|
{
|
|||
|
(void) rayFrom; (void) rayTo; (void) resultCallback;
|
|||
|
}
|
|||
|
|
|||
|
//! Function for retrieve triangles.
|
|||
|
/*!
|
|||
|
It gives the triangles in local space
|
|||
|
*/
|
|||
|
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
|
|||
|
{
|
|||
|
(void) callback; (void) aabbMin; (void) aabbMax;
|
|||
|
}
|
|||
|
|
|||
|
//! Function for retrieve triangles.
|
|||
|
/*!
|
|||
|
It gives the triangles in local space
|
|||
|
*/
|
|||
|
virtual void processAllTrianglesRay(btTriangleCallback* /*callback*/,const btVector3& /*rayFrom*/, const btVector3& /*rayTo*/) const
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//!@}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
//! btGImpactCompoundShape allows to handle multiple btCollisionShape objects at once
|
|||
|
/*!
|
|||
|
This class only can manage Convex subshapes
|
|||
|
*/
|
|||
|
class btGImpactCompoundShape : public btGImpactShapeInterface
|
|||
|
{
|
|||
|
public:
|
|||
|
//! compound primitive manager
|
|||
|
class CompoundPrimitiveManager:public btPrimitiveManagerBase
|
|||
|
{
|
|||
|
public:
|
|||
|
virtual ~CompoundPrimitiveManager() {}
|
|||
|
btGImpactCompoundShape * m_compoundShape;
|
|||
|
|
|||
|
|
|||
|
CompoundPrimitiveManager(const CompoundPrimitiveManager& compound)
|
|||
|
: btPrimitiveManagerBase()
|
|||
|
{
|
|||
|
m_compoundShape = compound.m_compoundShape;
|
|||
|
}
|
|||
|
|
|||
|
CompoundPrimitiveManager(btGImpactCompoundShape * compoundShape)
|
|||
|
{
|
|||
|
m_compoundShape = compoundShape;
|
|||
|
}
|
|||
|
|
|||
|
CompoundPrimitiveManager()
|
|||
|
{
|
|||
|
m_compoundShape = NULL;
|
|||
|
}
|
|||
|
|
|||
|
virtual bool is_trimesh() const
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
virtual int get_primitive_count() const
|
|||
|
{
|
|||
|
return (int )m_compoundShape->getNumChildShapes();
|
|||
|
}
|
|||
|
|
|||
|
virtual void get_primitive_box(int prim_index ,btAABB & primbox) const
|
|||
|
{
|
|||
|
btTransform prim_trans;
|
|||
|
if(m_compoundShape->childrenHasTransform())
|
|||
|
{
|
|||
|
prim_trans = m_compoundShape->getChildTransform(prim_index);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
prim_trans.setIdentity();
|
|||
|
}
|
|||
|
const btCollisionShape* shape = m_compoundShape->getChildShape(prim_index);
|
|||
|
shape->getAabb(prim_trans,primbox.m_min,primbox.m_max);
|
|||
|
}
|
|||
|
|
|||
|
virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const
|
|||
|
{
|
|||
|
btAssert(0);
|
|||
|
(void) prim_index; (void) triangle;
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
protected:
|
|||
|
CompoundPrimitiveManager m_primitive_manager;
|
|||
|
btAlignedObjectArray<btTransform> m_childTransforms;
|
|||
|
btAlignedObjectArray<btCollisionShape*> m_childShapes;
|
|||
|
|
|||
|
|
|||
|
public:
|
|||
|
|
|||
|
btGImpactCompoundShape(bool children_has_transform = true)
|
|||
|
{
|
|||
|
(void) children_has_transform;
|
|||
|
m_primitive_manager.m_compoundShape = this;
|
|||
|
m_box_set.setPrimitiveManager(&m_primitive_manager);
|
|||
|
}
|
|||
|
|
|||
|
virtual ~btGImpactCompoundShape()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//! if true, then its children must get transforms.
|
|||
|
virtual bool childrenHasTransform() const
|
|||
|
{
|
|||
|
if(m_childTransforms.size()==0) return false;
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//! Obtains the primitive manager
|
|||
|
virtual const btPrimitiveManagerBase * getPrimitiveManager() const
|
|||
|
{
|
|||
|
return &m_primitive_manager;
|
|||
|
}
|
|||
|
|
|||
|
//! Obtains the compopund primitive manager
|
|||
|
SIMD_FORCE_INLINE CompoundPrimitiveManager * getCompoundPrimitiveManager()
|
|||
|
{
|
|||
|
return &m_primitive_manager;
|
|||
|
}
|
|||
|
|
|||
|
//! Gets the number of children
|
|||
|
virtual int getNumChildShapes() const
|
|||
|
{
|
|||
|
return m_childShapes.size();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//! Use this method for adding children. Only Convex shapes are allowed.
|
|||
|
void addChildShape(const btTransform& localTransform,btCollisionShape* shape)
|
|||
|
{
|
|||
|
btAssert(shape->isConvex());
|
|||
|
m_childTransforms.push_back(localTransform);
|
|||
|
m_childShapes.push_back(shape);
|
|||
|
}
|
|||
|
|
|||
|
//! Use this method for adding children. Only Convex shapes are allowed.
|
|||
|
void addChildShape(btCollisionShape* shape)
|
|||
|
{
|
|||
|
btAssert(shape->isConvex());
|
|||
|
m_childShapes.push_back(shape);
|
|||
|
}
|
|||
|
|
|||
|
//! Gets the children
|
|||
|
virtual btCollisionShape* getChildShape(int index)
|
|||
|
{
|
|||
|
return m_childShapes[index];
|
|||
|
}
|
|||
|
|
|||
|
//! Gets the children
|
|||
|
virtual const btCollisionShape* getChildShape(int index) const
|
|||
|
{
|
|||
|
return m_childShapes[index];
|
|||
|
}
|
|||
|
|
|||
|
//! Retrieves the bound from a child
|
|||
|
/*!
|
|||
|
*/
|
|||
|
virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
|
|||
|
{
|
|||
|
|
|||
|
if(childrenHasTransform())
|
|||
|
{
|
|||
|
m_childShapes[child_index]->getAabb(t*m_childTransforms[child_index],aabbMin,aabbMax);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
m_childShapes[child_index]->getAabb(t,aabbMin,aabbMax);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//! Gets the children transform
|
|||
|
virtual btTransform getChildTransform(int index) const
|
|||
|
{
|
|||
|
btAssert(m_childTransforms.size() == m_childShapes.size());
|
|||
|
return m_childTransforms[index];
|
|||
|
}
|
|||
|
|
|||
|
//! Sets the children transform
|
|||
|
/*!
|
|||
|
\post You must call updateBound() for update the box set.
|
|||
|
*/
|
|||
|
virtual void setChildTransform(int index, const btTransform & transform)
|
|||
|
{
|
|||
|
btAssert(m_childTransforms.size() == m_childShapes.size());
|
|||
|
m_childTransforms[index] = transform;
|
|||
|
postUpdate();
|
|||
|
}
|
|||
|
|
|||
|
//! Determines if this shape has triangles
|
|||
|
virtual bool needsRetrieveTriangles() const
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
//! Determines if this shape has tetrahedrons
|
|||
|
virtual bool needsRetrieveTetrahedrons() const
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
|
|||
|
{
|
|||
|
(void) prim_index; (void) triangle;
|
|||
|
btAssert(0);
|
|||
|
}
|
|||
|
|
|||
|
virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const
|
|||
|
{
|
|||
|
(void) prim_index; (void) tetrahedron;
|
|||
|
btAssert(0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//! Calculates the exact inertia tensor for this shape
|
|||
|
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
|
|||
|
|
|||
|
virtual const char* getName()const
|
|||
|
{
|
|||
|
return "GImpactCompound";
|
|||
|
}
|
|||
|
|
|||
|
virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
|
|||
|
{
|
|||
|
return CONST_GIMPACT_COMPOUND_SHAPE;
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//! This class manages a sub part of a mesh supplied by the btStridingMeshInterface interface.
|
|||
|
/*!
|
|||
|
- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShapePart, then you must call updateBound() after creating the mesh
|
|||
|
- When making operations with this shape, you must call <b>lock</b> before accessing to the trimesh primitives, and then call <b>unlock</b>
|
|||
|
- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
|
|||
|
|
|||
|
*/
|
|||
|
class btGImpactMeshShapePart : public btGImpactShapeInterface
|
|||
|
{
|
|||
|
public:
|
|||
|
//! Trimesh primitive manager
|
|||
|
/*!
|
|||
|
Manages the info from btStridingMeshInterface object and controls the Lock/Unlock mechanism
|
|||
|
*/
|
|||
|
class TrimeshPrimitiveManager:public btPrimitiveManagerBase
|
|||
|
{
|
|||
|
public:
|
|||
|
btScalar m_margin;
|
|||
|
btStridingMeshInterface * m_meshInterface;
|
|||
|
btVector3 m_scale;
|
|||
|
int m_part;
|
|||
|
int m_lock_count;
|
|||
|
const unsigned char *vertexbase;
|
|||
|
int numverts;
|
|||
|
PHY_ScalarType type;
|
|||
|
int stride;
|
|||
|
const unsigned char *indexbase;
|
|||
|
int indexstride;
|
|||
|
int numfaces;
|
|||
|
PHY_ScalarType indicestype;
|
|||
|
|
|||
|
TrimeshPrimitiveManager()
|
|||
|
{
|
|||
|
m_meshInterface = NULL;
|
|||
|
m_part = 0;
|
|||
|
m_margin = 0.01f;
|
|||
|
m_scale = btVector3(1.f,1.f,1.f);
|
|||
|
m_lock_count = 0;
|
|||
|
vertexbase = 0;
|
|||
|
numverts = 0;
|
|||
|
stride = 0;
|
|||
|
indexbase = 0;
|
|||
|
indexstride = 0;
|
|||
|
numfaces = 0;
|
|||
|
}
|
|||
|
|
|||
|
TrimeshPrimitiveManager(const TrimeshPrimitiveManager & manager)
|
|||
|
: btPrimitiveManagerBase()
|
|||
|
{
|
|||
|
m_meshInterface = manager.m_meshInterface;
|
|||
|
m_part = manager.m_part;
|
|||
|
m_margin = manager.m_margin;
|
|||
|
m_scale = manager.m_scale;
|
|||
|
m_lock_count = 0;
|
|||
|
vertexbase = 0;
|
|||
|
numverts = 0;
|
|||
|
stride = 0;
|
|||
|
indexbase = 0;
|
|||
|
indexstride = 0;
|
|||
|
numfaces = 0;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
TrimeshPrimitiveManager(
|
|||
|
btStridingMeshInterface * meshInterface, int part)
|
|||
|
{
|
|||
|
m_meshInterface = meshInterface;
|
|||
|
m_part = part;
|
|||
|
m_scale = m_meshInterface->getScaling();
|
|||
|
m_margin = 0.1f;
|
|||
|
m_lock_count = 0;
|
|||
|
vertexbase = 0;
|
|||
|
numverts = 0;
|
|||
|
stride = 0;
|
|||
|
indexbase = 0;
|
|||
|
indexstride = 0;
|
|||
|
numfaces = 0;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
virtual ~TrimeshPrimitiveManager() {}
|
|||
|
|
|||
|
void lock()
|
|||
|
{
|
|||
|
if(m_lock_count>0)
|
|||
|
{
|
|||
|
m_lock_count++;
|
|||
|
return;
|
|||
|
}
|
|||
|
m_meshInterface->getLockedReadOnlyVertexIndexBase(
|
|||
|
&vertexbase,numverts,
|
|||
|
type, stride,&indexbase, indexstride, numfaces,indicestype,m_part);
|
|||
|
|
|||
|
m_lock_count = 1;
|
|||
|
}
|
|||
|
|
|||
|
void unlock()
|
|||
|
{
|
|||
|
if(m_lock_count == 0) return;
|
|||
|
if(m_lock_count>1)
|
|||
|
{
|
|||
|
--m_lock_count;
|
|||
|
return;
|
|||
|
}
|
|||
|
m_meshInterface->unLockReadOnlyVertexBase(m_part);
|
|||
|
vertexbase = NULL;
|
|||
|
m_lock_count = 0;
|
|||
|
}
|
|||
|
|
|||
|
virtual bool is_trimesh() const
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
virtual int get_primitive_count() const
|
|||
|
{
|
|||
|
return (int )numfaces;
|
|||
|
}
|
|||
|
|
|||
|
SIMD_FORCE_INLINE int get_vertex_count() const
|
|||
|
{
|
|||
|
return (int )numverts;
|
|||
|
}
|
|||
|
|
|||
|
SIMD_FORCE_INLINE void get_indices(int face_index,unsigned int &i0,unsigned int &i1,unsigned int &i2) const
|
|||
|
{
|
|||
|
if(indicestype == PHY_SHORT)
|
|||
|
{
|
|||
|
unsigned short* s_indices = (unsigned short *)(indexbase + face_index * indexstride);
|
|||
|
i0 = s_indices[0];
|
|||
|
i1 = s_indices[1];
|
|||
|
i2 = s_indices[2];
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
unsigned int * i_indices = (unsigned int *)(indexbase + face_index*indexstride);
|
|||
|
i0 = i_indices[0];
|
|||
|
i1 = i_indices[1];
|
|||
|
i2 = i_indices[2];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
SIMD_FORCE_INLINE void get_vertex(unsigned int vertex_index, btVector3 & vertex) const
|
|||
|
{
|
|||
|
if(type == PHY_DOUBLE)
|
|||
|
{
|
|||
|
double * dvertices = (double *)(vertexbase + vertex_index*stride);
|
|||
|
vertex[0] = btScalar(dvertices[0]*m_scale[0]);
|
|||
|
vertex[1] = btScalar(dvertices[1]*m_scale[1]);
|
|||
|
vertex[2] = btScalar(dvertices[2]*m_scale[2]);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
float * svertices = (float *)(vertexbase + vertex_index*stride);
|
|||
|
vertex[0] = svertices[0]*m_scale[0];
|
|||
|
vertex[1] = svertices[1]*m_scale[1];
|
|||
|
vertex[2] = svertices[2]*m_scale[2];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
virtual void get_primitive_box(int prim_index ,btAABB & primbox) const
|
|||
|
{
|
|||
|
btPrimitiveTriangle triangle;
|
|||
|
get_primitive_triangle(prim_index,triangle);
|
|||
|
primbox.calc_from_triangle_margin(
|
|||
|
triangle.m_vertices[0],
|
|||
|
triangle.m_vertices[1],triangle.m_vertices[2],triangle.m_margin);
|
|||
|
}
|
|||
|
|
|||
|
virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const
|
|||
|
{
|
|||
|
unsigned int indices[3];
|
|||
|
get_indices(prim_index,indices[0],indices[1],indices[2]);
|
|||
|
get_vertex(indices[0],triangle.m_vertices[0]);
|
|||
|
get_vertex(indices[1],triangle.m_vertices[1]);
|
|||
|
get_vertex(indices[2],triangle.m_vertices[2]);
|
|||
|
triangle.m_margin = m_margin;
|
|||
|
}
|
|||
|
|
|||
|
SIMD_FORCE_INLINE void get_bullet_triangle(int prim_index,btTriangleShapeEx & triangle) const
|
|||
|
{
|
|||
|
unsigned int indices[3];
|
|||
|
get_indices(prim_index,indices[0],indices[1],indices[2]);
|
|||
|
get_vertex(indices[0],triangle.m_vertices1[0]);
|
|||
|
get_vertex(indices[1],triangle.m_vertices1[1]);
|
|||
|
get_vertex(indices[2],triangle.m_vertices1[2]);
|
|||
|
triangle.setMargin(m_margin);
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
protected:
|
|||
|
TrimeshPrimitiveManager m_primitive_manager;
|
|||
|
public:
|
|||
|
|
|||
|
btGImpactMeshShapePart()
|
|||
|
{
|
|||
|
m_box_set.setPrimitiveManager(&m_primitive_manager);
|
|||
|
}
|
|||
|
|
|||
|
btGImpactMeshShapePart( btStridingMeshInterface * meshInterface, int part );
|
|||
|
virtual ~btGImpactMeshShapePart();
|
|||
|
|
|||
|
//! if true, then its children must get transforms.
|
|||
|
virtual bool childrenHasTransform() const
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//! call when reading child shapes
|
|||
|
virtual void lockChildShapes() const;
|
|||
|
virtual void unlockChildShapes() const;
|
|||
|
|
|||
|
//! Gets the number of children
|
|||
|
virtual int getNumChildShapes() const
|
|||
|
{
|
|||
|
return m_primitive_manager.get_primitive_count();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//! Gets the children
|
|||
|
virtual btCollisionShape* getChildShape(int index)
|
|||
|
{
|
|||
|
(void) index;
|
|||
|
btAssert(0);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//! Gets the child
|
|||
|
virtual const btCollisionShape* getChildShape(int index) const
|
|||
|
{
|
|||
|
(void) index;
|
|||
|
btAssert(0);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
//! Gets the children transform
|
|||
|
virtual btTransform getChildTransform(int index) const
|
|||
|
{
|
|||
|
(void) index;
|
|||
|
btAssert(0);
|
|||
|
return btTransform();
|
|||
|
}
|
|||
|
|
|||
|
//! Sets the children transform
|
|||
|
/*!
|
|||
|
\post You must call updateBound() for update the box set.
|
|||
|
*/
|
|||
|
virtual void setChildTransform(int index, const btTransform & transform)
|
|||
|
{
|
|||
|
(void) index;
|
|||
|
(void) transform;
|
|||
|
btAssert(0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//! Obtains the primitive manager
|
|||
|
virtual const btPrimitiveManagerBase * getPrimitiveManager() const
|
|||
|
{
|
|||
|
return &m_primitive_manager;
|
|||
|
}
|
|||
|
|
|||
|
SIMD_FORCE_INLINE TrimeshPrimitiveManager * getTrimeshPrimitiveManager()
|
|||
|
{
|
|||
|
return &m_primitive_manager;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
virtual const char* getName()const
|
|||
|
{
|
|||
|
return "GImpactMeshShapePart";
|
|||
|
}
|
|||
|
|
|||
|
virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
|
|||
|
{
|
|||
|
return CONST_GIMPACT_TRIMESH_SHAPE_PART;
|
|||
|
}
|
|||
|
|
|||
|
//! Determines if this shape has triangles
|
|||
|
virtual bool needsRetrieveTriangles() const
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
//! Determines if this shape has tetrahedrons
|
|||
|
virtual bool needsRetrieveTetrahedrons() const
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
|
|||
|
{
|
|||
|
m_primitive_manager.get_bullet_triangle(prim_index,triangle);
|
|||
|
}
|
|||
|
|
|||
|
virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const
|
|||
|
{
|
|||
|
(void) prim_index;
|
|||
|
(void) tetrahedron;
|
|||
|
btAssert(0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
SIMD_FORCE_INLINE int getVertexCount() const
|
|||
|
{
|
|||
|
return m_primitive_manager.get_vertex_count();
|
|||
|
}
|
|||
|
|
|||
|
SIMD_FORCE_INLINE void getVertex(int vertex_index, btVector3 & vertex) const
|
|||
|
{
|
|||
|
m_primitive_manager.get_vertex(vertex_index,vertex);
|
|||
|
}
|
|||
|
|
|||
|
SIMD_FORCE_INLINE void setMargin(btScalar margin)
|
|||
|
{
|
|||
|
m_primitive_manager.m_margin = margin;
|
|||
|
postUpdate();
|
|||
|
}
|
|||
|
|
|||
|
SIMD_FORCE_INLINE btScalar getMargin() const
|
|||
|
{
|
|||
|
return m_primitive_manager.m_margin;
|
|||
|
}
|
|||
|
|
|||
|
virtual void setLocalScaling(const btVector3& scaling)
|
|||
|
{
|
|||
|
m_primitive_manager.m_scale = scaling;
|
|||
|
postUpdate();
|
|||
|
}
|
|||
|
|
|||
|
virtual const btVector3& getLocalScaling() const
|
|||
|
{
|
|||
|
return m_primitive_manager.m_scale;
|
|||
|
}
|
|||
|
|
|||
|
SIMD_FORCE_INLINE int getPart() const
|
|||
|
{
|
|||
|
return (int)m_primitive_manager.m_part;
|
|||
|
}
|
|||
|
|
|||
|
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
|||
|
virtual void processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom,const btVector3& rayTo) const;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
//! This class manages a mesh supplied by the btStridingMeshInterface interface.
|
|||
|
/*!
|
|||
|
Set of btGImpactMeshShapePart parts
|
|||
|
- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShape, then you must call updateBound() after creating the mesh
|
|||
|
|
|||
|
- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
|
|||
|
|
|||
|
*/
|
|||
|
class btGImpactMeshShape : public btGImpactShapeInterface
|
|||
|
{
|
|||
|
btStridingMeshInterface* m_meshInterface;
|
|||
|
|
|||
|
protected:
|
|||
|
btAlignedObjectArray<btGImpactMeshShapePart*> m_mesh_parts;
|
|||
|
void buildMeshParts(btStridingMeshInterface * meshInterface)
|
|||
|
{
|
|||
|
for (int i=0;i<meshInterface->getNumSubParts() ;++i )
|
|||
|
{
|
|||
|
btGImpactMeshShapePart * newpart = new btGImpactMeshShapePart(meshInterface,i);
|
|||
|
m_mesh_parts.push_back(newpart);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//! use this function for perfofm refit in bounding boxes
|
|||
|
virtual void calcLocalAABB()
|
|||
|
{
|
|||
|
m_localAABB.invalidate();
|
|||
|
int i = m_mesh_parts.size();
|
|||
|
while(i--)
|
|||
|
{
|
|||
|
m_mesh_parts[i]->updateBound();
|
|||
|
m_localAABB.merge(m_mesh_parts[i]->getLocalBox());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public:
|
|||
|
btGImpactMeshShape(btStridingMeshInterface * meshInterface)
|
|||
|
{
|
|||
|
m_meshInterface = meshInterface;
|
|||
|
buildMeshParts(meshInterface);
|
|||
|
}
|
|||
|
|
|||
|
virtual ~btGImpactMeshShape()
|
|||
|
{
|
|||
|
int i = m_mesh_parts.size();
|
|||
|
while(i--)
|
|||
|
{
|
|||
|
btGImpactMeshShapePart * part = m_mesh_parts[i];
|
|||
|
delete part;
|
|||
|
}
|
|||
|
m_mesh_parts.clear();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
btStridingMeshInterface* getMeshInterface()
|
|||
|
{
|
|||
|
return m_meshInterface;
|
|||
|
}
|
|||
|
|
|||
|
const btStridingMeshInterface* getMeshInterface() const
|
|||
|
{
|
|||
|
return m_meshInterface;
|
|||
|
}
|
|||
|
|
|||
|
int getMeshPartCount() const
|
|||
|
{
|
|||
|
return m_mesh_parts.size();
|
|||
|
}
|
|||
|
|
|||
|
btGImpactMeshShapePart * getMeshPart(int index)
|
|||
|
{
|
|||
|
return m_mesh_parts[index];
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
const btGImpactMeshShapePart * getMeshPart(int index) const
|
|||
|
{
|
|||
|
return m_mesh_parts[index];
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
virtual void setLocalScaling(const btVector3& scaling)
|
|||
|
{
|
|||
|
localScaling = scaling;
|
|||
|
|
|||
|
int i = m_mesh_parts.size();
|
|||
|
while(i--)
|
|||
|
{
|
|||
|
btGImpactMeshShapePart * part = m_mesh_parts[i];
|
|||
|
part->setLocalScaling(scaling);
|
|||
|
}
|
|||
|
|
|||
|
m_needs_update = true;
|
|||
|
}
|
|||
|
|
|||
|
virtual void setMargin(btScalar margin)
|
|||
|
{
|
|||
|
m_collisionMargin = margin;
|
|||
|
|
|||
|
int i = m_mesh_parts.size();
|
|||
|
while(i--)
|
|||
|
{
|
|||
|
btGImpactMeshShapePart * part = m_mesh_parts[i];
|
|||
|
part->setMargin(margin);
|
|||
|
}
|
|||
|
|
|||
|
m_needs_update = true;
|
|||
|
}
|
|||
|
|
|||
|
//! Tells to this object that is needed to refit all the meshes
|
|||
|
virtual void postUpdate()
|
|||
|
{
|
|||
|
int i = m_mesh_parts.size();
|
|||
|
while(i--)
|
|||
|
{
|
|||
|
btGImpactMeshShapePart * part = m_mesh_parts[i];
|
|||
|
part->postUpdate();
|
|||
|
}
|
|||
|
|
|||
|
m_needs_update = true;
|
|||
|
}
|
|||
|
|
|||
|
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
|
|||
|
|
|||
|
|
|||
|
//! Obtains the primitive manager
|
|||
|
virtual const btPrimitiveManagerBase * getPrimitiveManager() const
|
|||
|
{
|
|||
|
btAssert(0);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//! Gets the number of children
|
|||
|
virtual int getNumChildShapes() const
|
|||
|
{
|
|||
|
btAssert(0);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//! if true, then its children must get transforms.
|
|||
|
virtual bool childrenHasTransform() const
|
|||
|
{
|
|||
|
btAssert(0);
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
//! Determines if this shape has triangles
|
|||
|
virtual bool needsRetrieveTriangles() const
|
|||
|
{
|
|||
|
btAssert(0);
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
//! Determines if this shape has tetrahedrons
|
|||
|
virtual bool needsRetrieveTetrahedrons() const
|
|||
|
{
|
|||
|
btAssert(0);
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
|
|||
|
{
|
|||
|
(void) prim_index; (void) triangle;
|
|||
|
btAssert(0);
|
|||
|
}
|
|||
|
|
|||
|
virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const
|
|||
|
{
|
|||
|
(void) prim_index; (void) tetrahedron;
|
|||
|
btAssert(0);
|
|||
|
}
|
|||
|
|
|||
|
//! call when reading child shapes
|
|||
|
virtual void lockChildShapes() const
|
|||
|
{
|
|||
|
btAssert(0);
|
|||
|
}
|
|||
|
|
|||
|
virtual void unlockChildShapes() const
|
|||
|
{
|
|||
|
btAssert(0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//! Retrieves the bound from a child
|
|||
|
/*!
|
|||
|
*/
|
|||
|
virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
|
|||
|
{
|
|||
|
(void) child_index; (void) t; (void) aabbMin; (void) aabbMax;
|
|||
|
btAssert(0);
|
|||
|
}
|
|||
|
|
|||
|
//! Gets the children
|
|||
|
virtual btCollisionShape* getChildShape(int index)
|
|||
|
{
|
|||
|
(void) index;
|
|||
|
btAssert(0);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//! Gets the child
|
|||
|
virtual const btCollisionShape* getChildShape(int index) const
|
|||
|
{
|
|||
|
(void) index;
|
|||
|
btAssert(0);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
//! Gets the children transform
|
|||
|
virtual btTransform getChildTransform(int index) const
|
|||
|
{
|
|||
|
(void) index;
|
|||
|
btAssert(0);
|
|||
|
return btTransform();
|
|||
|
}
|
|||
|
|
|||
|
//! Sets the children transform
|
|||
|
/*!
|
|||
|
\post You must call updateBound() for update the box set.
|
|||
|
*/
|
|||
|
virtual void setChildTransform(int index, const btTransform & transform)
|
|||
|
{
|
|||
|
(void) index; (void) transform;
|
|||
|
btAssert(0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
|
|||
|
{
|
|||
|
return CONST_GIMPACT_TRIMESH_SHAPE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
virtual const char* getName()const
|
|||
|
{
|
|||
|
return "GImpactMesh";
|
|||
|
}
|
|||
|
|
|||
|
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const;
|
|||
|
|
|||
|
//! Function for retrieve triangles.
|
|||
|
/*!
|
|||
|
It gives the triangles in local space
|
|||
|
*/
|
|||
|
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
|||
|
|
|||
|
virtual void processAllTrianglesRay (btTriangleCallback* callback,const btVector3& rayFrom,const btVector3& rayTo) const;
|
|||
|
|
|||
|
virtual int calculateSerializeBufferSize() const;
|
|||
|
|
|||
|
///fills the dataBuffer and returns the struct name (and 0 on failure)
|
|||
|
virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
|
|||
|
struct btGImpactMeshShapeData
|
|||
|
{
|
|||
|
btCollisionShapeData m_collisionShapeData;
|
|||
|
|
|||
|
btStridingMeshInterfaceData m_meshInterface;
|
|||
|
|
|||
|
btVector3FloatData m_localScaling;
|
|||
|
|
|||
|
float m_collisionMargin;
|
|||
|
|
|||
|
int m_gimpactSubType;
|
|||
|
};
|
|||
|
|
|||
|
SIMD_FORCE_INLINE int btGImpactMeshShape::calculateSerializeBufferSize() const
|
|||
|
{
|
|||
|
return sizeof(btGImpactMeshShapeData);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#endif //GIMPACT_MESH_SHAPE_H
|