Yo @Raggar … you got any specifics on using the triangle normal instead of the collision normal ??
FYI… I saw previous about the internal edge problem and was trying a solution if found using generateInternalEdgeInfo … so i was setting that up like so
const world:any = BABYLON.SceneManager.GetPhysicsWorld(scene);
if (world != null && world.generateInternalEdgeInfo) {
const collisionShape:any = colobj.getCollisionShape();
if (collisionShape != null && collisionShape.getShapeType) {
const shapeType:number = collisionShape.getShapeType();
if (shapeType === 21) { // TRIANGLE_MESH_SHAPE_PROXYTYPE
const triangleShape:any = Ammo.castObject(collisionShape, Ammo.btBvhTriangleMeshShape);
colobj.triangleMapInfo = new Ammo.btTriangleInfoMap();
world.generateInternalEdgeInfo(triangleShape, colobj.triangleMapInfo);
}
}
}
Then i use the Ammo.addFunction to setup a collision call back to adjust the internal edge info
const addFunctionSignature:string = "iiiiiiii";
const contactAddedCallbackPtr:any = Ammo.addFunction((cp:any, colObj0Wrap:any, partId0:number, index0:number, colObj1Wrap:any, partId1:number, index1:number) => {
if (physicsplugin.world.adjustInternalEdgeContacts) {
physicsplugin.world.adjustInternalEdgeContacts(cp, colObj1Wrap, colObj0Wrap, partId1, index1);
return true;
} else {
return false;
}
}, addFunctionSignature);
if (contactAddedCallbackPtr != null) {
physicsplugin.world.setContactAddedCallback(contactAddedCallbackPtr);
BABYLON.Tools.Log("Ammo.js internal edges supported");
}
But apparently that is not working…
But you said something about replacing the collision normal with the triangle normal…
Well i just so happen to have the triangle normal available … I am using that with me btSmoothRaycastVehicle… i use barry coordinates to smooth out mesh collision contact… is Pretty kool take a look
Here is my header file for btSmoothVehicleRaycaster
class btSmoothVehicleRaycaster : public btVehicleRaycaster
{
btDynamicsWorld* m_dynamicsWorld;
public:
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
bool m_interpolateNormals;
bool m_shapeTestingMode;
int m_testPointCount;
btScalar m_sweepPenetration;
btScalar m_shapeTestingSize;
btSmoothVehicleRaycaster(btDynamicsWorld* world)
: m_dynamicsWorld(world),
m_interpolateNormals(false),
m_shapeTestingMode(false),
m_testPointCount(32), // shall be enough, but can be higher
m_shapeTestingSize(btScalar(0.2f)), // should be half of wheel radius
m_sweepPenetration(btScalar(0.0f)), // default to zero
m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::StaticFilter) { }
virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result);
void* performLineTest(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result);
void* performShapeTest(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result);
};
The main thing is the performLineTest function
void* btSmoothVehicleRaycaster::performLineTest(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result)
{
SmoothRayCastResultCallback rayCallback(from, to);
rayCallback.m_collisionFilterMask = this->m_collisionFilterMask;
rayCallback.m_collisionFilterGroup = this->m_collisionFilterGroup;
// If this is a rigid body, m_collision_object is NULL, and the
// rigid body is the actual collision object.
// btCollisionWorld::rayTestSingle(from, to, m_collision_object ? m_collision_object : body, m_collision_shape, world_trans, ray_callback);
m_dynamicsWorld->rayTest(from, to, rayCallback);
if (rayCallback.hasHit())
{
const btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject);
if (body && body->hasContactResponse())
{
result.m_distFraction = rayCallback.m_closestHitFraction;
result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld;
result.m_hitNormalInWorld.normalize();
// printf("Perform Line Test - Hit Fraction (%f) -> Hit Point (%f x %f x %f) -> Hit Normal: (%f x %f x %f)\n", result.m_distFraction,
// result.m_hitPointInWorld.x(), result.m_hitPointInWorld.y(), result.m_hitPointInWorld.z(),
// result.m_hitNormalInWorld.x(), result.m_hitNormalInWorld.y(), result.m_hitNormalInWorld.z()
// );
if (this->m_interpolateNormals == true)
{
btCollisionShape* shape = (btCollisionShape*)body->getCollisionShape();
if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
btTriangleMeshShape *mesh_shape = static_cast<btTriangleMeshShape *>(shape);
btStridingMeshInterface *mesh_interface = mesh_shape->getMeshInterface();
btSmoothTriangleMesh *mesh_smoothing = dynamic_cast<btSmoothTriangleMesh*>(mesh_interface);
if (mesh_smoothing != NULL && mesh_smoothing->hasVertexNormals())
{
// btVector3 n1 = btVector3(result.m_hitNormalInWorld.x(), result.m_hitNormalInWorld.y(), result.m_hitNormalInWorld.z());
// ..
result.m_hitNormalInWorld = mesh_smoothing->interpolateMeshNormal(body->getWorldTransform(), mesh_interface, rayCallback.m_shapePart, rayCallback.m_triangleIndex, rayCallback.m_hitPointWorld);
// ..
// btVector3 n2 = btVector3(result.m_hitNormalInWorld.x(), result.m_hitNormalInWorld.y(), result.m_hitNormalInWorld.z());
// printf("Perform Line Test - Hit Normal (%f x %f x %f) -> Bary Normal: (%f x %f x %f)\n", n1.x(), n1.y(), n1.z(), n2.x(), n2.y(), n2.z());
}
}
}
return (void*)body;
}
}
return 0;
}
And this is the actual interoplation functions that make all the driving Smooth as a baby’s but
// shape, subpart and triangle come from the ray callback.
// transform is the mesh shape's world transform
// position is the world space hit point of the ray
btVector3 btSmoothTriangleMesh::interpolateMeshNormal(const btTransform &transform, btStridingMeshInterface *mesh_interface, int subpart, int triangle, const btVector3 &position)
{
const unsigned char *vertexbase;
int num_verts;
PHY_ScalarType type;
int stride;
const unsigned char *indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
int numverts = 0;
mesh_interface->getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, subpart);
// Calculate new barycentric coordinates
const unsigned int *indices = (const unsigned int *)(indexbase + triangle * indexstride);
unsigned int i = indices[0], j = indices[1], k = indices[2];
StrideVertexAccessor positions(vertexbase, stride, 0);
btVector3 barry = this->barycentricCoordinates(transform.invXform(position), positions[i], positions[j], positions[k]);
// ..
// btVector3 n1 = this->getVertexNormal(i);
// btVector3 n2 = this->getVertexNormal(j);
// btVector3 n3 = this->getVertexNormal(k);
// printf("SmoothVehicleRaycaster: Trace Mesh Vertex Normals I: (%f x %f x %f) -> J: (%f x %f x %f) -> K: (%f x %f x %f)\n", n1.x(), n1.y(), n1.z(), n2.x(), n2.y(), n2.z(), n3.x(), n3.y(), n3.z());
// ..
// Interpolate from barycentric coordinates
// ..
btVector3 result = barry.x() * this->getVertexNormal(i) + barry.y() * this->getVertexNormal(j) + barry.z() * this->getVertexNormal(k);
// ..
// Transform back into world space
// ..
result = transform.getBasis() * result;
result.normalize();
mesh_interface->unLockReadOnlyVertexBase(subpart);
return result;
}
btVector3 btSmoothTriangleMesh::barycentricCoordinates(const btVector3 &position, const btVector3 &p1, const btVector3 &p2, const btVector3 &p3)
{
btVector3 edge1 = p2 - p1;
btVector3 edge2 = p3 - p1;
// Area of triangle ABC
btScalar p1p2p3 = edge1.cross(edge2).length2();
// Area of BCP
btScalar p2p3p = (p3 - p2).cross(position - p2).length2(); // Area of CAP
btScalar p3p1p = edge2.cross(position - p3).length2();
btScalar s = btSqrt(p2p3p / p1p2p3);
btScalar t = btSqrt(p3p1p / p1p2p3);
btScalar w = 1.0f - s - t;
return btVector3(s, t, w);
}
So you can see i have the vertex normal (triangle normal) right here
btVector3 result = barry.x() * this->getVertexNormal(i) + barry.y() * this->getVertexNormal(j) + barry.z() * this->getVertexNormal(k);
So you are saying somehow (if you can help with the how)… use that vertex normal instead of the collision normal… How and where would i do that ?
For you reference i am including a copy of the modified bullet classes i made so you can look them over… All my stuff starts with btSmooth at the bottom of each file
btRacycastVehicle.zip (11.7 KB)