PyBullet: add support for internal edge filtering for height field terrains
This commit is contained in:
@@ -612,6 +612,11 @@ btTransform ConvertURDF2BulletInternal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (compoundShape->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
|
||||||
|
{
|
||||||
|
col->setCollisionFlags(col->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
|
||||||
|
}
|
||||||
|
|
||||||
btTransform tr;
|
btTransform tr;
|
||||||
tr.setIdentity();
|
tr.setIdentity();
|
||||||
tr = linkTransformInWorldSpace;
|
tr = linkTransformInWorldSpace;
|
||||||
|
|||||||
@@ -2805,6 +2805,14 @@ void PhysicsServerCommandProcessor::deleteDynamicsWorld()
|
|||||||
delete trimesh->getTriangleInfoMap();
|
delete trimesh->getTriangleInfoMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (shape->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
|
||||||
|
{
|
||||||
|
btHeightfieldTerrainShape* terrain = (btHeightfieldTerrainShape*)shape;
|
||||||
|
if (terrain->getTriangleInfoMap())
|
||||||
|
{
|
||||||
|
delete terrain->getTriangleInfoMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
delete shape;
|
delete shape;
|
||||||
}
|
}
|
||||||
for (int j = 0; j < m_data->m_heightfieldDatas.size(); j++)
|
for (int j = 0; j < m_data->m_heightfieldDatas.size(); j++)
|
||||||
@@ -4546,12 +4554,19 @@ bool PhysicsServerCommandProcessor::processCreateCollisionShapeCommand(const str
|
|||||||
|
|
||||||
bool flipQuadEdges = false;
|
bool flipQuadEdges = false;
|
||||||
int upAxis = 2;
|
int upAxis = 2;
|
||||||
btHeightfieldTerrainShape* heightfieldShape = worldImporter->createHeightfieldShape( width, height,
|
/*btHeightfieldTerrainShape* heightfieldShape = worldImporter->createHeightfieldShape( width, height,
|
||||||
heightfieldData,
|
heightfieldData,
|
||||||
gridHeightScale,
|
gridHeightScale,
|
||||||
minHeight, maxHeight,
|
minHeight, maxHeight,
|
||||||
upAxis, int(scalarType), flipQuadEdges);
|
upAxis, int(scalarType), flipQuadEdges);
|
||||||
|
*/
|
||||||
|
btHeightfieldTerrainShape* heightfieldShape = new btHeightfieldTerrainShape( width, height,
|
||||||
|
heightfieldData,
|
||||||
|
gridHeightScale,
|
||||||
|
minHeight, maxHeight,
|
||||||
|
upAxis, scalarType, flipQuadEdges);
|
||||||
|
m_data->m_collisionShapes.push_back(heightfieldShape);
|
||||||
|
|
||||||
heightfieldShape->setUserValue3(clientCmd.m_createUserShapeArgs.m_shapes[i].m_heightfieldTextureScaling);
|
heightfieldShape->setUserValue3(clientCmd.m_createUserShapeArgs.m_shapes[i].m_heightfieldTextureScaling);
|
||||||
shape = heightfieldShape;
|
shape = heightfieldShape;
|
||||||
if (upAxis == 2)
|
if (upAxis == 2)
|
||||||
@@ -4565,6 +4580,9 @@ bool PhysicsServerCommandProcessor::processCreateCollisionShapeCommand(const str
|
|||||||
clientCmd.m_createUserShapeArgs.m_shapes[i].m_meshScale[2]);
|
clientCmd.m_createUserShapeArgs.m_shapes[i].m_meshScale[2]);
|
||||||
|
|
||||||
heightfieldShape->setLocalScaling(localScaling);
|
heightfieldShape->setLocalScaling(localScaling);
|
||||||
|
|
||||||
|
btTriangleInfoMap* triangleInfoMap = new btTriangleInfoMap();
|
||||||
|
btGenerateInternalEdgeInfo(heightfieldShape, triangleInfoMap);
|
||||||
|
|
||||||
this->m_data->m_heightfieldDatas.push_back(heightfieldData);
|
this->m_data->m_heightfieldDatas.push_back(heightfieldData);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "btInternalEdgeUtility.h"
|
#include "btInternalEdgeUtility.h"
|
||||||
|
|
||||||
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
|
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
|
||||||
|
|
||||||
#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
|
#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
|
||||||
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
|
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
|
||||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||||
@@ -290,6 +292,39 @@ struct btConnectivityProcessor : public btTriangleCallback
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct b3ProcessAllTrianglesHeightfield: public btTriangleCallback
|
||||||
|
{
|
||||||
|
btHeightfieldTerrainShape* m_heightfieldShape;
|
||||||
|
btTriangleInfoMap* m_triangleInfoMap;
|
||||||
|
|
||||||
|
|
||||||
|
b3ProcessAllTrianglesHeightfield(btHeightfieldTerrainShape* heightFieldShape, btTriangleInfoMap* triangleInfoMap)
|
||||||
|
:m_heightfieldShape(heightFieldShape),
|
||||||
|
m_triangleInfoMap(triangleInfoMap)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
|
||||||
|
{
|
||||||
|
btConnectivityProcessor connectivityProcessor;
|
||||||
|
connectivityProcessor.m_partIdA = partId;
|
||||||
|
connectivityProcessor.m_triangleIndexA = triangleIndex;
|
||||||
|
connectivityProcessor.m_triangleVerticesA = triangle;
|
||||||
|
connectivityProcessor.m_triangleInfoMap = m_triangleInfoMap;
|
||||||
|
btVector3 aabbMin, aabbMax;
|
||||||
|
aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
|
||||||
|
aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
|
||||||
|
aabbMin.setMin(triangle[0]);
|
||||||
|
aabbMax.setMax(triangle[0]);
|
||||||
|
aabbMin.setMin(triangle[1]);
|
||||||
|
aabbMax.setMax(triangle[1]);
|
||||||
|
aabbMin.setMin(triangle[2]);
|
||||||
|
aabbMax.setMax(triangle[2]);
|
||||||
|
|
||||||
|
m_heightfieldShape->processAllTriangles(&connectivityProcessor, aabbMin, aabbMax);
|
||||||
|
}
|
||||||
|
};
|
||||||
/////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////
|
||||||
/////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -361,6 +396,28 @@ void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangle
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void btGenerateInternalEdgeInfo(btHeightfieldTerrainShape* heightfieldShape, btTriangleInfoMap* triangleInfoMap)
|
||||||
|
{
|
||||||
|
|
||||||
|
//the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
|
||||||
|
if (heightfieldShape->getTriangleInfoMap())
|
||||||
|
return;
|
||||||
|
|
||||||
|
heightfieldShape->setTriangleInfoMap(triangleInfoMap);
|
||||||
|
|
||||||
|
//get all the triangles of the heightfield
|
||||||
|
|
||||||
|
btVector3 aabbMin, aabbMax;
|
||||||
|
|
||||||
|
aabbMax.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
|
||||||
|
aabbMin.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
|
||||||
|
|
||||||
|
b3ProcessAllTrianglesHeightfield processHeightfield(heightfieldShape, triangleInfoMap);
|
||||||
|
heightfieldShape->processAllTriangles(&processHeightfield, aabbMin, aabbMax);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Given a point and a line segment (defined by two points), compute the closest point
|
// Given a point and a line segment (defined by two points), compute the closest point
|
||||||
// in the line. Cap the point at the endpoints of the line segment.
|
// in the line. Cap the point at the endpoints of the line segment.
|
||||||
void btNearestPointInLineSegment(const btVector3& point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint)
|
void btNearestPointInLineSegment(const btVector3& point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint)
|
||||||
@@ -426,6 +483,32 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWr
|
|||||||
if (colObj0Wrap->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
|
if (colObj0Wrap->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
btTriangleInfoMap* triangleInfoMapPtr = 0;
|
||||||
|
|
||||||
|
if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
|
||||||
|
{
|
||||||
|
btHeightfieldTerrainShape* heightfield = (btHeightfieldTerrainShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
|
||||||
|
triangleInfoMapPtr = heightfield->getTriangleInfoMap();
|
||||||
|
|
||||||
|
//#define USE_HEIGHTFIELD_TRIANGLES
|
||||||
|
#ifdef USE_HEIGHTFIELD_TRIANGLES
|
||||||
|
btVector3 newNormal = btVector3(0, 0, 1);
|
||||||
|
|
||||||
|
const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
|
||||||
|
btVector3 tri_normal;
|
||||||
|
tri_shape->calcNormal(tri_normal);
|
||||||
|
newNormal = tri_normal;
|
||||||
|
// cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
|
||||||
|
cp.m_normalWorldOnB = newNormal;
|
||||||
|
// Reproject collision point along normal. (what about cp.m_distance1?)
|
||||||
|
cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
|
||||||
|
cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
btBvhTriangleMeshShape* trimesh = 0;
|
btBvhTriangleMeshShape* trimesh = 0;
|
||||||
|
|
||||||
if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
|
if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
|
||||||
@@ -439,10 +522,12 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWr
|
|||||||
trimesh = (btBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
|
trimesh = (btBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (trimesh == 0)
|
if (trimesh)
|
||||||
return;
|
{
|
||||||
|
triangleInfoMapPtr = (btTriangleInfoMap*)trimesh->getTriangleInfoMap();
|
||||||
btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*)trimesh->getTriangleInfoMap();
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!triangleInfoMapPtr)
|
if (!triangleInfoMapPtr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class btCollisionObject;
|
|||||||
struct btCollisionObjectWrapper;
|
struct btCollisionObjectWrapper;
|
||||||
class btManifoldPoint;
|
class btManifoldPoint;
|
||||||
class btIDebugDraw;
|
class btIDebugDraw;
|
||||||
|
class btHeightfieldTerrainShape;
|
||||||
|
|
||||||
enum btInternalEdgeAdjustFlags
|
enum btInternalEdgeAdjustFlags
|
||||||
{
|
{
|
||||||
@@ -26,6 +27,8 @@ enum btInternalEdgeAdjustFlags
|
|||||||
///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'
|
///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'
|
||||||
void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
|
void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
|
||||||
|
|
||||||
|
void btGenerateInternalEdgeInfo(btHeightfieldTerrainShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
|
||||||
|
|
||||||
///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo)
|
///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo)
|
||||||
///If this info map is missing, or the triangle is not store in this map, nothing will be done
|
///If this info map is missing, or the triangle is not store in this map, nothing will be done
|
||||||
void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* trimeshColObj0Wrap, const btCollisionObjectWrapper* otherColObj1Wrap, int partId0, int index0, int normalAdjustFlags = 0);
|
void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* trimeshColObj0Wrap, const btCollisionObjectWrapper* otherColObj1Wrap, int partId0, int index0, int normalAdjustFlags = 0);
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ btHeightfieldTerrainShape::btHeightfieldTerrainShape(
|
|||||||
btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
|
btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
|
||||||
PHY_ScalarType hdt, bool flipQuadEdges)
|
PHY_ScalarType hdt, bool flipQuadEdges)
|
||||||
:m_userIndex2(-1),
|
:m_userIndex2(-1),
|
||||||
m_userValue3(0)
|
m_userValue3(0),
|
||||||
|
m_triangleInfoMap(0)
|
||||||
{
|
{
|
||||||
initialize(heightStickWidth, heightStickLength, heightfieldData,
|
initialize(heightStickWidth, heightStickLength, heightfieldData,
|
||||||
heightScale, minHeight, maxHeight, upAxis, hdt,
|
heightScale, minHeight, maxHeight, upAxis, hdt,
|
||||||
@@ -31,7 +32,8 @@ btHeightfieldTerrainShape::btHeightfieldTerrainShape(
|
|||||||
|
|
||||||
btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar maxHeight, int upAxis, bool useFloatData, bool flipQuadEdges)
|
btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar maxHeight, int upAxis, bool useFloatData, bool flipQuadEdges)
|
||||||
:m_userIndex2(-1),
|
:m_userIndex2(-1),
|
||||||
m_userValue3(0)
|
m_userValue3(0),
|
||||||
|
m_triangleInfoMap(0)
|
||||||
{
|
{
|
||||||
// legacy constructor: support only float or unsigned char,
|
// legacy constructor: support only float or unsigned char,
|
||||||
// and min height is zero
|
// and min height is zero
|
||||||
@@ -353,12 +355,12 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
|
|||||||
getVertex(x, j, vertices[indices[0]]);
|
getVertex(x, j, vertices[indices[0]]);
|
||||||
getVertex(x, j + 1, vertices[indices[1]]);
|
getVertex(x, j + 1, vertices[indices[1]]);
|
||||||
getVertex(x + 1, j + 1, vertices[indices[2]]);
|
getVertex(x + 1, j + 1, vertices[indices[2]]);
|
||||||
callback->processTriangle(vertices, x, j);
|
callback->processTriangle(vertices, 2 * x, j);
|
||||||
//second triangle
|
//second triangle
|
||||||
// getVertex(x,j,vertices[0]);//already got this vertex before, thanks to Danny Chapman
|
// getVertex(x,j,vertices[0]);//already got this vertex before, thanks to Danny Chapman
|
||||||
getVertex(x + 1, j + 1, vertices[indices[1]]);
|
getVertex(x + 1, j + 1, vertices[indices[1]]);
|
||||||
getVertex(x + 1, j, vertices[indices[2]]);
|
getVertex(x + 1, j, vertices[indices[2]]);
|
||||||
callback->processTriangle(vertices, x, j);
|
callback->processTriangle(vertices, 2 * x+1, j);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -366,12 +368,12 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
|
|||||||
getVertex(x, j, vertices[indices[0]]);
|
getVertex(x, j, vertices[indices[0]]);
|
||||||
getVertex(x, j + 1, vertices[indices[1]]);
|
getVertex(x, j + 1, vertices[indices[1]]);
|
||||||
getVertex(x + 1, j, vertices[indices[2]]);
|
getVertex(x + 1, j, vertices[indices[2]]);
|
||||||
callback->processTriangle(vertices, x, j);
|
callback->processTriangle(vertices, 2 * x, j);
|
||||||
//second triangle
|
//second triangle
|
||||||
getVertex(x + 1, j, vertices[indices[0]]);
|
getVertex(x + 1, j, vertices[indices[0]]);
|
||||||
//getVertex(x,j+1,vertices[1]);
|
//getVertex(x,j+1,vertices[1]);
|
||||||
getVertex(x + 1, j + 1, vertices[indices[2]]);
|
getVertex(x + 1, j + 1, vertices[indices[2]]);
|
||||||
callback->processTriangle(vertices, x, j);
|
callback->processTriangle(vertices, 2 * x+1, j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,6 +117,8 @@ protected:
|
|||||||
int m_userIndex2;
|
int m_userIndex2;
|
||||||
btScalar m_userValue3;
|
btScalar m_userValue3;
|
||||||
|
|
||||||
|
struct btTriangleInfoMap* m_triangleInfoMap;
|
||||||
|
|
||||||
virtual btScalar getRawHeightFieldValue(int x, int y) const;
|
virtual btScalar getRawHeightFieldValue(int x, int y) const;
|
||||||
void quantizeWithClamp(int* out, const btVector3& point, int isMax) const;
|
void quantizeWithClamp(int* out, const btVector3& point, int isMax) const;
|
||||||
|
|
||||||
@@ -206,6 +208,18 @@ public:
|
|||||||
{
|
{
|
||||||
return m_userValue3;
|
return m_userValue3;
|
||||||
}
|
}
|
||||||
|
const struct btTriangleInfoMap* getTriangleInfoMap() const
|
||||||
|
{
|
||||||
|
return m_triangleInfoMap;
|
||||||
|
}
|
||||||
|
struct btTriangleInfoMap* getTriangleInfoMap()
|
||||||
|
{
|
||||||
|
return m_triangleInfoMap;
|
||||||
|
}
|
||||||
|
void setTriangleInfoMap(btTriangleInfoMap* map)
|
||||||
|
{
|
||||||
|
m_triangleInfoMap = map;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H
|
#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H
|
||||||
Reference in New Issue
Block a user