@@ -1101,13 +1101,13 @@ void CcdPhysicsEnvironment::RemoveConstraintById(int constraintId, bool free)
1101
1101
1102
1102
struct FilterClosestRayResultCallback : public btCollisionWorld ::ClosestRayResultCallback {
1103
1103
PHY_IRayCastFilterCallback& m_phyRayFilter;
1104
- const btCollisionShape *m_hitTriangleShape ;
1104
+ int m_hitChildIndex ;
1105
1105
int m_hitTriangleIndex;
1106
1106
1107
1107
FilterClosestRayResultCallback (PHY_IRayCastFilterCallback& phyRayFilter, const btVector3& rayFrom, const btVector3& rayTo)
1108
1108
:btCollisionWorld::ClosestRayResultCallback(rayFrom, rayTo),
1109
1109
m_phyRayFilter (phyRayFilter),
1110
- m_hitTriangleShape( nullptr ),
1110
+ m_hitChildIndex(- 1 ),
1111
1111
m_hitTriangleIndex(0 )
1112
1112
{
1113
1113
}
@@ -1134,21 +1134,18 @@ struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResu
1134
1134
1135
1135
virtual btScalar addSingleResult (btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
1136
1136
{
1137
- // CcdPhysicsController* curHit = static_cast<CcdPhysicsController*>(rayResult.m_collisionObject->getUserPointer());
1138
- // save shape information as ClosestRayResultCallback::AddSingleResult() does not do it
1137
+ m_hitChildIndex = rayResult.m_childIndex ;
1139
1138
if (rayResult.m_localShapeInfo ) {
1140
- m_hitTriangleShape = rayResult.m_collisionObject ->getCollisionShape ();
1141
1139
m_hitTriangleIndex = rayResult.m_localShapeInfo ->m_triangleIndex ;
1142
1140
}
1143
1141
else {
1144
- m_hitTriangleShape = nullptr ;
1145
1142
m_hitTriangleIndex = 0 ;
1146
1143
}
1147
1144
return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace);
1148
1145
}
1149
1146
};
1150
1147
1151
- static bool GetHitTriangle (btCollisionShape *shape, CcdShapeConstructionInfo *shapeInfo, int hitTriangleIndex, btVector3 triangle[])
1148
+ static bool GetHitTriangle (const btCollisionShape *shape, CcdShapeConstructionInfo *shapeInfo, int hitTriangleIndex, btVector3 triangle[])
1152
1149
{
1153
1150
// this code is copied from Bullet
1154
1151
const unsigned char *vertexbase;
@@ -1198,132 +1195,119 @@ PHY_IPhysicsController *CcdPhysicsEnvironment::RayTest(PHY_IRayCastFilterCallbac
1198
1195
1199
1196
// Either Ray Cast with or without filtering
1200
1197
1201
- // btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom,rayTo);
1202
1198
FilterClosestRayResultCallback rayCallback (filterCallback, rayFrom, rayTo);
1203
-
1204
1199
PHY_RayCastResult result;
1205
1200
1206
1201
// don't collision with sensor object
1207
1202
rayCallback.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
1208
1203
// use faster (less accurate) ray callback, works better with 0 collision margins
1209
1204
rayCallback.m_flags |= btTriangleRaycastCallback::kF_UseSubSimplexConvexCastRaytest ;
1210
- // , ,filterCallback.m_faceNormal);
1211
1205
1212
1206
m_dynamicsWorld->rayTest (rayFrom, rayTo, rayCallback);
1213
1207
if (rayCallback.hasHit ()) {
1208
+ const btCollisionObject *object = rayCallback.m_collisionObject ;
1209
+ const btCollisionShape *shape = object->getCollisionShape ();
1210
+
1214
1211
CcdPhysicsController *controller = static_cast <CcdPhysicsController *>(rayCallback.m_collisionObject ->getUserPointer ());
1215
1212
result.m_controller = controller;
1216
- result.m_hitPoint [0 ] = rayCallback.m_hitPointWorld .getX ();
1217
- result.m_hitPoint [1 ] = rayCallback.m_hitPointWorld .getY ();
1218
- result.m_hitPoint [2 ] = rayCallback.m_hitPointWorld .getZ ();
1219
-
1220
- if (rayCallback.m_hitTriangleShape != nullptr ) {
1221
- // identify the mesh polygon
1222
- CcdShapeConstructionInfo *shapeInfo = controller->m_shapeInfo ;
1223
- if (shapeInfo) {
1224
- btCollisionShape *shape = controller->GetCollisionObject ()->getCollisionShape ();
1225
- if (shape->isCompound ()) {
1226
- btCompoundShape *compoundShape = (btCompoundShape *)shape;
1227
- CcdShapeConstructionInfo *compoundShapeInfo = shapeInfo;
1228
- // need to search which sub-shape has been hit
1229
- for (int i = 0 ; i < compoundShape->getNumChildShapes (); i++) {
1230
- shapeInfo = compoundShapeInfo->GetChildShape (i);
1231
- shape = compoundShape->getChildShape (i);
1232
- if (shape == rayCallback.m_hitTriangleShape ) {
1233
- break ;
1213
+ result.m_hitPoint = ToMt (rayCallback.m_hitPointWorld );
1214
+
1215
+ if (shape) {
1216
+ if (shape->isCompound ()) {
1217
+ const btCompoundShape *compoundShape = static_cast <const btCompoundShape *>(shape);
1218
+ shape = compoundShape->getChildShape (rayCallback.m_hitChildIndex );
1219
+ }
1220
+
1221
+ CcdShapeConstructionInfo *shapeInfo = static_cast <CcdShapeConstructionInfo *>(shape->getUserPointer ());
1222
+ if (shapeInfo && rayCallback.m_hitTriangleIndex < shapeInfo->m_polygonIndexArray .size ()) {
1223
+ // save original collision shape triangle for soft body
1224
+ const int hitTriangleIndex = rayCallback.m_hitTriangleIndex ;
1225
+
1226
+ result.m_meshObject = shapeInfo->GetMesh ();
1227
+ if (shape->isSoftBody ()) {
1228
+ // soft body using different face numbering because of randomization
1229
+ // hopefully we have stored the original face number in m_tag
1230
+ const btSoftBody *softBody = static_cast <const btSoftBody *>(object);
1231
+ if (softBody->m_faces [hitTriangleIndex].m_tag != 0 ) {
1232
+ rayCallback.m_hitTriangleIndex = (int )((uintptr_t )(softBody->m_faces [hitTriangleIndex].m_tag ) - 1 );
1233
+ }
1234
+ }
1235
+ // retrieve the original mesh polygon (in case of quad->tri conversion)
1236
+ result.m_polygon = shapeInfo->m_polygonIndexArray [rayCallback.m_hitTriangleIndex ];
1237
+ // hit triangle in world coordinate, for face normal and UV coordinate
1238
+ btVector3 triangle[3 ];
1239
+ bool triangleOK = false ;
1240
+ if (filterCallback.m_faceUV && (3 * rayCallback.m_hitTriangleIndex ) < shapeInfo->m_triFaceUVcoArray .size ()) {
1241
+ // interpolate the UV coordinate of the hit point
1242
+ CcdShapeConstructionInfo::UVco *uvCo = &shapeInfo->m_triFaceUVcoArray [3 * rayCallback.m_hitTriangleIndex ];
1243
+ // 1. get the 3 coordinate of the triangle in world space
1244
+ btVector3 v1, v2, v3;
1245
+ if (shape->isSoftBody ()) {
1246
+ // soft body give points directly in world coordinate
1247
+ const btSoftBody *softBody = static_cast <const btSoftBody *>(object);
1248
+ v1 = softBody->m_faces [hitTriangleIndex].m_n [0 ]->m_x ;
1249
+ v2 = softBody->m_faces [hitTriangleIndex].m_n [1 ]->m_x ;
1250
+ v3 = softBody->m_faces [hitTriangleIndex].m_n [2 ]->m_x ;
1251
+ }
1252
+ else {
1253
+ // for rigid body we must apply the world transform
1254
+ triangleOK = GetHitTriangle (shape, shapeInfo, hitTriangleIndex, triangle);
1255
+ if (!triangleOK) {
1256
+ // if we cannot get the triangle, no use to continue
1257
+ goto SKIP_UV_NORMAL;
1234
1258
}
1259
+ const btTransform& trans = object->getWorldTransform ();
1260
+ v1 = trans (triangle[0 ]);
1261
+ v2 = trans (triangle[1 ]);
1262
+ v3 = trans (triangle[2 ]);
1235
1263
}
1264
+ // 2. compute barycentric coordinate of the hit point
1265
+ btVector3 v = v2 - v1;
1266
+ btVector3 w = v3 - v1;
1267
+ btVector3 u = v.cross (w);
1268
+ btScalar A = u.length ();
1269
+
1270
+ v = v2 - rayCallback.m_hitPointWorld ;
1271
+ w = v3 - rayCallback.m_hitPointWorld ;
1272
+ u = v.cross (w);
1273
+ btScalar A1 = u.length ();
1274
+
1275
+ v = rayCallback.m_hitPointWorld - v1;
1276
+ w = v3 - v1;
1277
+ u = v.cross (w);
1278
+ btScalar A2 = u.length ();
1279
+
1280
+ btVector3 baryCo;
1281
+ baryCo.setX (A1 / A);
1282
+ baryCo.setY (A2 / A);
1283
+ baryCo.setZ (1 .0f - baryCo.getX () - baryCo.getY ());
1284
+ // 3. compute UV coordinate
1285
+ result.m_hitUV [0 ] = baryCo.getX () * uvCo[0 ].uv [0 ] + baryCo.getY () * uvCo[1 ].uv [0 ] + baryCo.getZ () * uvCo[2 ].uv [0 ];
1286
+ result.m_hitUV [1 ] = baryCo.getX () * uvCo[0 ].uv [1 ] + baryCo.getY () * uvCo[1 ].uv [1 ] + baryCo.getZ () * uvCo[2 ].uv [1 ];
1287
+ result.m_hitUVOK = 1 ;
1236
1288
}
1237
- if (shape == rayCallback.m_hitTriangleShape &&
1238
- rayCallback.m_hitTriangleIndex < shapeInfo->m_polygonIndexArray .size ()) {
1239
- // save original collision shape triangle for soft body
1240
- int hitTriangleIndex = rayCallback.m_hitTriangleIndex ;
1241
1289
1242
- result.m_meshObject = shapeInfo->GetMesh ();
1290
+ // Bullet returns the normal from "outside".
1291
+ // If the user requests the real normal, compute it now
1292
+ if (filterCallback.m_faceNormal ) {
1243
1293
if (shape->isSoftBody ()) {
1244
- // soft body using different face numbering because of randomization
1245
- // hopefully we have stored the original face number in m_tag
1294
+ // we can get the real normal directly from the body
1246
1295
const btSoftBody *softBody = static_cast <const btSoftBody *>(rayCallback.m_collisionObject );
1247
- if (softBody->m_faces [hitTriangleIndex].m_tag != 0 ) {
1248
- rayCallback.m_hitTriangleIndex = (int )((uintptr_t )(softBody->m_faces [hitTriangleIndex].m_tag ) - 1 );
1249
- }
1296
+ rayCallback.m_hitNormalWorld = softBody->m_faces [hitTriangleIndex].m_normal ;
1250
1297
}
1251
- // retrieve the original mesh polygon (in case of quad->tri conversion)
1252
- result.m_polygon = shapeInfo->m_polygonIndexArray [rayCallback.m_hitTriangleIndex ];
1253
- // hit triangle in world coordinate, for face normal and UV coordinate
1254
- btVector3 triangle[3 ];
1255
- bool triangleOK = false ;
1256
- if (filterCallback.m_faceUV && (3 * rayCallback.m_hitTriangleIndex ) < shapeInfo->m_triFaceUVcoArray .size ()) {
1257
- // interpolate the UV coordinate of the hit point
1258
- CcdShapeConstructionInfo::UVco *uvCo = &shapeInfo->m_triFaceUVcoArray [3 * rayCallback.m_hitTriangleIndex ];
1259
- // 1. get the 3 coordinate of the triangle in world space
1260
- btVector3 v1, v2, v3;
1261
- if (shape->isSoftBody ()) {
1262
- // soft body give points directly in world coordinate
1263
- const btSoftBody *softBody = static_cast <const btSoftBody *>(rayCallback.m_collisionObject );
1264
- v1 = softBody->m_faces [hitTriangleIndex].m_n [0 ]->m_x ;
1265
- v2 = softBody->m_faces [hitTriangleIndex].m_n [1 ]->m_x ;
1266
- v3 = softBody->m_faces [hitTriangleIndex].m_n [2 ]->m_x ;
1267
- }
1268
- else {
1269
- // for rigid body we must apply the world transform
1298
+ else {
1299
+ if (!triangleOK) {
1270
1300
triangleOK = GetHitTriangle (shape, shapeInfo, hitTriangleIndex, triangle);
1271
- if (!triangleOK) {
1272
- // if we cannot get the triangle, no use to continue
1273
- goto SKIP_UV_NORMAL;
1274
- }
1275
- v1 = rayCallback.m_collisionObject ->getWorldTransform ()(triangle[0 ]);
1276
- v2 = rayCallback.m_collisionObject ->getWorldTransform ()(triangle[1 ]);
1277
- v3 = rayCallback.m_collisionObject ->getWorldTransform ()(triangle[2 ]);
1278
1301
}
1279
- // 2. compute barycentric coordinate of the hit point
1280
- btVector3 v = v2 - v1;
1281
- btVector3 w = v3 - v1;
1282
- btVector3 u = v.cross (w);
1283
- btScalar A = u.length ();
1284
-
1285
- v = v2 - rayCallback.m_hitPointWorld ;
1286
- w = v3 - rayCallback.m_hitPointWorld ;
1287
- u = v.cross (w);
1288
- btScalar A1 = u.length ();
1289
-
1290
- v = rayCallback.m_hitPointWorld - v1;
1291
- w = v3 - v1;
1292
- u = v.cross (w);
1293
- btScalar A2 = u.length ();
1294
-
1295
- btVector3 baryCo;
1296
- baryCo.setX (A1 / A);
1297
- baryCo.setY (A2 / A);
1298
- baryCo.setZ (1 .0f - baryCo.getX () - baryCo.getY ());
1299
- // 3. compute UV coordinate
1300
- result.m_hitUV [0 ] = baryCo.getX () * uvCo[0 ].uv [0 ] + baryCo.getY () * uvCo[1 ].uv [0 ] + baryCo.getZ () * uvCo[2 ].uv [0 ];
1301
- result.m_hitUV [1 ] = baryCo.getX () * uvCo[0 ].uv [1 ] + baryCo.getY () * uvCo[1 ].uv [1 ] + baryCo.getZ () * uvCo[2 ].uv [1 ];
1302
- result.m_hitUVOK = 1 ;
1303
- }
1304
-
1305
- // Bullet returns the normal from "outside".
1306
- // If the user requests the real normal, compute it now
1307
- if (filterCallback.m_faceNormal ) {
1308
- if (shape->isSoftBody ()) {
1309
- // we can get the real normal directly from the body
1310
- const btSoftBody *softBody = static_cast <const btSoftBody *>(rayCallback.m_collisionObject );
1311
- rayCallback.m_hitNormalWorld = softBody->m_faces [hitTriangleIndex].m_normal ;
1312
- }
1313
- else {
1314
- if (!triangleOK) {
1315
- triangleOK = GetHitTriangle (shape, shapeInfo, hitTriangleIndex, triangle);
1316
- }
1317
- if (triangleOK) {
1318
- btVector3 triangleNormal;
1319
- triangleNormal = (triangle[1 ] - triangle[0 ]).cross (triangle[2 ] - triangle[0 ]);
1320
- rayCallback.m_hitNormalWorld = rayCallback.m_collisionObject ->getWorldTransform ().getBasis () * triangleNormal;
1321
- }
1302
+ if (triangleOK) {
1303
+ btVector3 triangleNormal;
1304
+ triangleNormal = (triangle[1 ] - triangle[0 ]).cross (triangle[2 ] - triangle[0 ]);
1305
+ rayCallback.m_hitNormalWorld = rayCallback.m_collisionObject ->getWorldTransform ().getBasis () * triangleNormal;
1322
1306
}
1323
1307
}
1324
- SKIP_UV_NORMAL:
1325
- ;
1326
1308
}
1309
+ SKIP_UV_NORMAL:
1310
+ ;
1327
1311
}
1328
1312
}
1329
1313
if (rayCallback.m_hitNormalWorld .length2 () > (SIMD_EPSILON * SIMD_EPSILON)) {
@@ -1332,9 +1316,8 @@ PHY_IPhysicsController *CcdPhysicsEnvironment::RayTest(PHY_IRayCastFilterCallbac
1332
1316
else {
1333
1317
rayCallback.m_hitNormalWorld .setValue (1 .0f , 0 .0f , 0 .0f );
1334
1318
}
1335
- result.m_hitNormal [0 ] = rayCallback.m_hitNormalWorld .getX ();
1336
- result.m_hitNormal [1 ] = rayCallback.m_hitNormalWorld .getY ();
1337
- result.m_hitNormal [2 ] = rayCallback.m_hitNormalWorld .getZ ();
1319
+
1320
+ result.m_hitNormal = ToMt (rayCallback.m_hitNormalWorld );
1338
1321
filterCallback.reportHit (&result);
1339
1322
}
1340
1323
@@ -3004,6 +2987,7 @@ void CcdPhysicsEnvironment::ConvertObject(BL_SceneConverter& converter, KX_GameO
3004
2987
// create the compound shape manually as we already have the child shape
3005
2988
btCompoundShape *compoundShape = new btCompoundShape ();
3006
2989
compoundShape->addChildShape (shapeInfo->m_childTrans , bm);
2990
+ compoundShape->setUserPointer (compoundShapeInfo);
3007
2991
// now replace the shape
3008
2992
bm = compoundShape;
3009
2993
shapeInfo->Release ();
0 commit comments