|
|
|
|
@@ -16,6 +16,9 @@ subject to the following restrictions:
|
|
|
|
|
#include "CcdPhysicsController.h"
|
|
|
|
|
#include "btBulletDynamicsCommon.h"
|
|
|
|
|
#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
|
|
|
|
|
|
|
|
|
|
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
|
|
|
|
|
|
|
|
|
|
#include "PHY_IMotionState.h"
|
|
|
|
|
#include "CcdPhysicsEnvironment.h"
|
|
|
|
|
#include "RAS_MeshObject.h"
|
|
|
|
|
@@ -1276,150 +1279,212 @@ CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mes
|
|
|
|
|
|
|
|
|
|
bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bool useGimpact)
|
|
|
|
|
{
|
|
|
|
|
int numpolys;
|
|
|
|
|
|
|
|
|
|
m_useGimpact = useGimpact;
|
|
|
|
|
|
|
|
|
|
// assume no shape information
|
|
|
|
|
// no support for dynamic change of shape yet
|
|
|
|
|
assert(IsUnused());
|
|
|
|
|
m_shapeType = PHY_SHAPE_NONE;
|
|
|
|
|
m_vertexArray.clear();
|
|
|
|
|
m_polygonIndexArray.clear();
|
|
|
|
|
m_meshObject = NULL;
|
|
|
|
|
|
|
|
|
|
if (!meshobj)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// Mesh has no polygons!
|
|
|
|
|
int numpolys = meshobj->NumPolygons();
|
|
|
|
|
if (!numpolys)
|
|
|
|
|
{
|
|
|
|
|
// No mesh object or mesh has no polys
|
|
|
|
|
if (!meshobj || meshobj->HasColliderPolygon()==false) {
|
|
|
|
|
m_vertexArray.clear();
|
|
|
|
|
m_polygonIndexArray.clear();
|
|
|
|
|
m_triFaceArray.clear();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check that we have at least one colliding polygon
|
|
|
|
|
int numvalidpolys = 0;
|
|
|
|
|
|
|
|
|
|
for (int p=0; p<numpolys; p++)
|
|
|
|
|
{
|
|
|
|
|
RAS_Polygon* poly = meshobj->GetPolygon(p);
|
|
|
|
|
|
|
|
|
|
// only add polygons that have the collisionflag set
|
|
|
|
|
if (poly->IsCollider())
|
|
|
|
|
{
|
|
|
|
|
numvalidpolys++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// No collision polygons
|
|
|
|
|
if (numvalidpolys < 1)
|
|
|
|
|
return false;
|
|
|
|
|
numpolys = meshobj->NumPolygons();
|
|
|
|
|
|
|
|
|
|
m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH;
|
|
|
|
|
|
|
|
|
|
numvalidpolys = 0;
|
|
|
|
|
/* Convert blender geometry into bullet mesh, need these vars for mapping */
|
|
|
|
|
vector<bool> vert_tag_array(meshobj->GetMesh()->totvert, false);
|
|
|
|
|
unsigned int tot_bt_verts= 0;
|
|
|
|
|
unsigned int orig_index;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (polytope)
|
|
|
|
|
{
|
|
|
|
|
Mesh *blen_mesh= meshobj->GetMesh();
|
|
|
|
|
vector<bool> vuser_array(blen_mesh->totvert, false);
|
|
|
|
|
|
|
|
|
|
unsigned int tot_bt_verts= 0;
|
|
|
|
|
unsigned int orig_index;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
// Tag verts we're using
|
|
|
|
|
for (int p2=0; p2<numpolys; p2++)
|
|
|
|
|
{
|
|
|
|
|
RAS_Polygon* poly= meshobj->GetPolygon(p2);
|
|
|
|
|
|
|
|
|
|
// only add polygons that have the collisionflag set
|
|
|
|
|
|
|
|
|
|
// only add polygons that have the collision flag set
|
|
|
|
|
if (poly->IsCollider())
|
|
|
|
|
{
|
|
|
|
|
for (i=0;i<poly->VertexCount();i++)
|
|
|
|
|
{
|
|
|
|
|
for(i=0; i<poly->VertexCount(); i++) {
|
|
|
|
|
orig_index= poly->GetVertex(i)->getOrigIndex();
|
|
|
|
|
|
|
|
|
|
if (vuser_array[orig_index]==false)
|
|
|
|
|
if (vert_tag_array[orig_index]==false)
|
|
|
|
|
{
|
|
|
|
|
vuser_array[orig_index]= true;
|
|
|
|
|
vert_tag_array[orig_index]= true;
|
|
|
|
|
tot_bt_verts++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_vertexArray.resize(tot_bt_verts);
|
|
|
|
|
|
|
|
|
|
// Copy used verts directly from the meshes vert location to the bullet vector array
|
|
|
|
|
MVert *mv= blen_mesh->mvert;
|
|
|
|
|
|
|
|
|
|
btVector3 *bt= &m_vertexArray[0];
|
|
|
|
|
|
|
|
|
|
for (i=0;i<vuser_array.size();i++, mv++)
|
|
|
|
|
{
|
|
|
|
|
if (vuser_array[i]==true)
|
|
|
|
|
{
|
|
|
|
|
bt->setX( mv->co[0] );
|
|
|
|
|
bt->setY( mv->co[1] );
|
|
|
|
|
bt->setZ( mv->co[2] );
|
|
|
|
|
bt++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
numvalidpolys++;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
|
|
for (int p2=0; p2<numpolys; p2++)
|
|
|
|
|
{
|
|
|
|
|
RAS_Polygon* poly = meshobj->GetPolygon(p2);
|
|
|
|
|
RAS_Polygon* poly= meshobj->GetPolygon(p2);
|
|
|
|
|
|
|
|
|
|
// only add polygons that have the collisionflag set
|
|
|
|
|
if (poly->IsCollider())
|
|
|
|
|
{
|
|
|
|
|
//Bullet can raycast any shape, so
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const float* vtx = poly->GetVertex(2)->getXYZ();
|
|
|
|
|
btVector3 vertex0(vtx[0],vtx[1],vtx[2]);
|
|
|
|
|
{
|
|
|
|
|
for(i=0; i<poly->VertexCount(); i++) {
|
|
|
|
|
RAS_TexVert *v= poly->GetVertex(i);
|
|
|
|
|
orig_index= v->getOrigIndex();
|
|
|
|
|
|
|
|
|
|
vtx = poly->GetVertex(1)->getXYZ();
|
|
|
|
|
btVector3 vertex1(vtx[0],vtx[1],vtx[2]);
|
|
|
|
|
if (vert_tag_array[orig_index]==true)
|
|
|
|
|
{
|
|
|
|
|
const float* vtx = v->getXYZ();
|
|
|
|
|
vert_tag_array[orig_index]= false;
|
|
|
|
|
|
|
|
|
|
vtx = poly->GetVertex(0)->getXYZ();
|
|
|
|
|
btVector3 vertex2(vtx[0],vtx[1],vtx[2]);
|
|
|
|
|
|
|
|
|
|
m_vertexArray.push_back(vertex0);
|
|
|
|
|
m_vertexArray.push_back(vertex1);
|
|
|
|
|
m_vertexArray.push_back(vertex2);
|
|
|
|
|
m_polygonIndexArray.push_back(p2);
|
|
|
|
|
numvalidpolys++;
|
|
|
|
|
}
|
|
|
|
|
if (poly->VertexCount() == 4)
|
|
|
|
|
{
|
|
|
|
|
const float* vtx = poly->GetVertex(3)->getXYZ();
|
|
|
|
|
btVector3 vertex0(vtx[0],vtx[1],vtx[2]);
|
|
|
|
|
|
|
|
|
|
vtx = poly->GetVertex(2)->getXYZ();
|
|
|
|
|
btVector3 vertex1(vtx[0],vtx[1],vtx[2]);
|
|
|
|
|
|
|
|
|
|
vtx = poly->GetVertex(0)->getXYZ();
|
|
|
|
|
btVector3 vertex2(vtx[0],vtx[1],vtx[2]);
|
|
|
|
|
|
|
|
|
|
m_vertexArray.push_back(vertex0);
|
|
|
|
|
m_vertexArray.push_back(vertex1);
|
|
|
|
|
m_vertexArray.push_back(vertex2);
|
|
|
|
|
m_polygonIndexArray.push_back(p2);
|
|
|
|
|
numvalidpolys++;
|
|
|
|
|
bt->setX(vtx[0]); bt->setY(vtx[1]); bt->setZ(vtx[2]);
|
|
|
|
|
bt++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
unsigned int tot_bt_tris= 0;
|
|
|
|
|
vector<int> vert_remap_array(meshobj->GetMesh()->totvert, 0);
|
|
|
|
|
|
|
|
|
|
// Tag verts we're using
|
|
|
|
|
for (int p2=0; p2<numpolys; p2++)
|
|
|
|
|
{
|
|
|
|
|
RAS_Polygon* poly= meshobj->GetPolygon(p2);
|
|
|
|
|
|
|
|
|
|
if (!numvalidpolys)
|
|
|
|
|
// only add polygons that have the collision flag set
|
|
|
|
|
if (poly->IsCollider())
|
|
|
|
|
{
|
|
|
|
|
for(i=0; i<poly->VertexCount(); i++) {
|
|
|
|
|
orig_index= poly->GetVertex(i)->getOrigIndex();
|
|
|
|
|
if (vert_tag_array[orig_index]==false)
|
|
|
|
|
{
|
|
|
|
|
vert_tag_array[orig_index]= true;
|
|
|
|
|
vert_remap_array[orig_index]= tot_bt_verts;
|
|
|
|
|
tot_bt_verts++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tot_bt_tris += (i==4 ? 2:1); /* a quad or a tri */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_vertexArray.resize(tot_bt_verts);
|
|
|
|
|
m_polygonIndexArray.resize(tot_bt_tris);
|
|
|
|
|
m_triFaceArray.resize(tot_bt_tris*3);
|
|
|
|
|
|
|
|
|
|
btVector3 *bt= &m_vertexArray[0];
|
|
|
|
|
int *poly_index_pt= &m_polygonIndexArray[0];
|
|
|
|
|
int *tri_pt= &m_triFaceArray[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int p2=0; p2<numpolys; p2++)
|
|
|
|
|
{
|
|
|
|
|
RAS_Polygon* poly= meshobj->GetPolygon(p2);
|
|
|
|
|
|
|
|
|
|
// only add polygons that have the collisionflag set
|
|
|
|
|
if (poly->IsCollider())
|
|
|
|
|
{
|
|
|
|
|
RAS_TexVert *v1= poly->GetVertex(0);
|
|
|
|
|
RAS_TexVert *v2= poly->GetVertex(1);
|
|
|
|
|
RAS_TexVert *v3= poly->GetVertex(2);
|
|
|
|
|
int i1= v1->getOrigIndex();
|
|
|
|
|
int i2= v2->getOrigIndex();
|
|
|
|
|
int i3= v3->getOrigIndex();
|
|
|
|
|
const float* vtx;
|
|
|
|
|
|
|
|
|
|
// the face indicies
|
|
|
|
|
tri_pt[0]= vert_remap_array[i1];
|
|
|
|
|
tri_pt[1]= vert_remap_array[i2];
|
|
|
|
|
tri_pt[2]= vert_remap_array[i3];
|
|
|
|
|
tri_pt= tri_pt+3;
|
|
|
|
|
|
|
|
|
|
// m_polygonIndexArray
|
|
|
|
|
*poly_index_pt= p2;
|
|
|
|
|
poly_index_pt++;
|
|
|
|
|
|
|
|
|
|
// the vertex location
|
|
|
|
|
if (vert_tag_array[i1]==true) { /* *** v1 *** */
|
|
|
|
|
vert_tag_array[i1]= false;
|
|
|
|
|
vtx = v1->getXYZ();
|
|
|
|
|
bt->setX(vtx[0]); bt->setY( vtx[1]); bt->setZ(vtx[2]);
|
|
|
|
|
bt++;
|
|
|
|
|
}
|
|
|
|
|
if (vert_tag_array[i2]==true) { /* *** v2 *** */
|
|
|
|
|
vert_tag_array[i2]= false;
|
|
|
|
|
vtx = v2->getXYZ();
|
|
|
|
|
bt->setX(vtx[0]); bt->setY(vtx[1]); bt->setZ(vtx[2]);
|
|
|
|
|
bt++;
|
|
|
|
|
}
|
|
|
|
|
if (vert_tag_array[i3]==true) { /* *** v3 *** */
|
|
|
|
|
vert_tag_array[i3]= false;
|
|
|
|
|
vtx = v3->getXYZ();
|
|
|
|
|
bt->setX(vtx[0]); bt->setY(vtx[1]); bt->setZ(vtx[2]);
|
|
|
|
|
bt++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (poly->VertexCount()==4)
|
|
|
|
|
{
|
|
|
|
|
RAS_TexVert *v4= poly->GetVertex(3);
|
|
|
|
|
int i4= v4->getOrigIndex();
|
|
|
|
|
|
|
|
|
|
tri_pt[0]= vert_remap_array[i1];
|
|
|
|
|
tri_pt[1]= vert_remap_array[i3];
|
|
|
|
|
tri_pt[2]= vert_remap_array[i4];
|
|
|
|
|
tri_pt= tri_pt+3;
|
|
|
|
|
|
|
|
|
|
// m_polygonIndexArray
|
|
|
|
|
*poly_index_pt= p2;
|
|
|
|
|
poly_index_pt++;
|
|
|
|
|
|
|
|
|
|
// the vertex location
|
|
|
|
|
if (vert_tag_array[i4]==true) { /* *** v4 *** */
|
|
|
|
|
vert_tag_array[i4]= false;
|
|
|
|
|
vtx = v4->getXYZ();
|
|
|
|
|
bt->setX(vtx[0]); bt->setY(vtx[1]); bt->setZ(vtx[2]);
|
|
|
|
|
bt++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* If this ever gets confusing, print out an OBJ file for debugging */
|
|
|
|
|
#if 0
|
|
|
|
|
printf("# vert count %d\n", m_vertexArray.size());
|
|
|
|
|
for(i=0; i<m_vertexArray.size(); i+=1) {
|
|
|
|
|
printf("v %.6f %.6f %.6f\n", m_vertexArray[i].x(), m_vertexArray[i].y(), m_vertexArray[i].z());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("# face count %d\n", m_triFaceArray.size());
|
|
|
|
|
for(i=0; i<m_triFaceArray.size(); i+=3) {
|
|
|
|
|
printf("f %d %d %d\n", m_triFaceArray[i]+1, m_triFaceArray[i+1]+1, m_triFaceArray[i+2]+1);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
if (validpolys==false)
|
|
|
|
|
{
|
|
|
|
|
// should not happen
|
|
|
|
|
m_shapeType = PHY_SHAPE_NONE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
m_meshObject = meshobj;
|
|
|
|
|
if (!polytope)
|
|
|
|
|
{
|
|
|
|
|
@@ -1444,7 +1509,6 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
|
|
|
|
|
{
|
|
|
|
|
btCollisionShape* collisionShape = 0;
|
|
|
|
|
btTriangleMeshShape* concaveShape = 0;
|
|
|
|
|
btTriangleMesh* collisionMeshData = 0;
|
|
|
|
|
btCompoundShape* compoundShape = 0;
|
|
|
|
|
CcdShapeConstructionInfo* nextShapeInfo;
|
|
|
|
|
|
|
|
|
|
@@ -1485,18 +1549,17 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
|
|
|
|
|
// One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1
|
|
|
|
|
// and btScaledBvhTriangleMeshShape otherwise.
|
|
|
|
|
if (m_useGimpact)
|
|
|
|
|
{
|
|
|
|
|
collisionMeshData = new btTriangleMesh();
|
|
|
|
|
{
|
|
|
|
|
btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray(
|
|
|
|
|
m_polygonIndexArray.size(),
|
|
|
|
|
&m_triFaceArray[0],
|
|
|
|
|
3*sizeof(int),
|
|
|
|
|
m_vertexArray.size(),
|
|
|
|
|
(btScalar*) &m_vertexArray[0].x(),
|
|
|
|
|
sizeof(btVector3)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
bool removeDuplicateVertices=true;
|
|
|
|
|
|
|
|
|
|
// m_vertexArray is necessarily a multiple of 3
|
|
|
|
|
for (int i=0;i<m_vertexArray.size(); i+=3 )
|
|
|
|
|
{
|
|
|
|
|
collisionMeshData->addTriangle(m_vertexArray[i+2],m_vertexArray[i+1],m_vertexArray[i],removeDuplicateVertices);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(collisionMeshData);
|
|
|
|
|
btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(indexVertexArrays);
|
|
|
|
|
|
|
|
|
|
collisionShape = gimpactShape;
|
|
|
|
|
gimpactShape->updateBound();
|
|
|
|
|
@@ -1505,17 +1568,18 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
|
|
|
|
|
{
|
|
|
|
|
if (!m_unscaledShape)
|
|
|
|
|
{
|
|
|
|
|
collisionMeshData = new btTriangleMesh(true,false);
|
|
|
|
|
collisionMeshData->m_weldingThreshold = m_weldingThreshold;
|
|
|
|
|
|
|
|
|
|
bool removeDuplicateVertices=true;
|
|
|
|
|
// m_vertexArray is necessarily a multiple of 3
|
|
|
|
|
for (int i=0;i<m_vertexArray.size(); i+=3 )
|
|
|
|
|
{
|
|
|
|
|
collisionMeshData->addTriangle(m_vertexArray[i+2],m_vertexArray[i+1],m_vertexArray[i],removeDuplicateVertices);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray(
|
|
|
|
|
m_polygonIndexArray.size(),
|
|
|
|
|
&m_triFaceArray[0],
|
|
|
|
|
3*sizeof(int),
|
|
|
|
|
m_vertexArray.size(),
|
|
|
|
|
(btScalar*) &m_vertexArray[0].x(),
|
|
|
|
|
sizeof(btVector3)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// this shape will be shared and not deleted until shapeInfo is deleted
|
|
|
|
|
m_unscaledShape = new btBvhTriangleMeshShape( collisionMeshData, true );
|
|
|
|
|
m_unscaledShape = new btBvhTriangleMeshShape( indexVertexArrays, true );
|
|
|
|
|
m_unscaledShape->recalcLocalAabb();
|
|
|
|
|
}
|
|
|
|
|
collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f));
|
|
|
|
|
|