@@ -1101,13 +1101,13 @@ void CcdPhysicsEnvironment::RemoveConstraintById(int constraintId, bool free)
11011101
11021102struct FilterClosestRayResultCallback : public btCollisionWorld ::ClosestRayResultCallback {
11031103 PHY_IRayCastFilterCallback& m_phyRayFilter;
1104- const btCollisionShape *m_hitTriangleShape ;
1104+ int m_hitChildIndex ;
11051105 int m_hitTriangleIndex;
11061106
11071107 FilterClosestRayResultCallback (PHY_IRayCastFilterCallback& phyRayFilter, const btVector3& rayFrom, const btVector3& rayTo)
11081108 :btCollisionWorld::ClosestRayResultCallback(rayFrom, rayTo),
11091109 m_phyRayFilter (phyRayFilter),
1110- m_hitTriangleShape( nullptr ),
1110+ m_hitChildIndex(- 1 ),
11111111 m_hitTriangleIndex(0 )
11121112 {
11131113 }
@@ -1134,21 +1134,18 @@ struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResu
11341134
11351135 virtual btScalar addSingleResult (btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
11361136 {
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 ;
11391138 if (rayResult.m_localShapeInfo ) {
1140- m_hitTriangleShape = rayResult.m_collisionObject ->getCollisionShape ();
11411139 m_hitTriangleIndex = rayResult.m_localShapeInfo ->m_triangleIndex ;
11421140 }
11431141 else {
1144- m_hitTriangleShape = nullptr ;
11451142 m_hitTriangleIndex = 0 ;
11461143 }
11471144 return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace);
11481145 }
11491146};
11501147
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[])
11521149{
11531150 // this code is copied from Bullet
11541151 const unsigned char *vertexbase;
@@ -1198,132 +1195,119 @@ PHY_IPhysicsController *CcdPhysicsEnvironment::RayTest(PHY_IRayCastFilterCallbac
11981195
11991196 // Either Ray Cast with or without filtering
12001197
1201- // btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom,rayTo);
12021198 FilterClosestRayResultCallback rayCallback (filterCallback, rayFrom, rayTo);
1203-
12041199 PHY_RayCastResult result;
12051200
12061201 // don't collision with sensor object
12071202 rayCallback.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
12081203 // use faster (less accurate) ray callback, works better with 0 collision margins
12091204 rayCallback.m_flags |= btTriangleRaycastCallback::kF_UseSubSimplexConvexCastRaytest ;
1210- // , ,filterCallback.m_faceNormal);
12111205
12121206 m_dynamicsWorld->rayTest (rayFrom, rayTo, rayCallback);
12131207 if (rayCallback.hasHit ()) {
1208+ const btCollisionObject *object = rayCallback.m_collisionObject ;
1209+ const btCollisionShape *shape = object->getCollisionShape ();
1210+
12141211 CcdPhysicsController *controller = static_cast <CcdPhysicsController *>(rayCallback.m_collisionObject ->getUserPointer ());
12151212 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;
12341258 }
1259+ const btTransform& trans = object->getWorldTransform ();
1260+ v1 = trans (triangle[0 ]);
1261+ v2 = trans (triangle[1 ]);
1262+ v3 = trans (triangle[2 ]);
12351263 }
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 ;
12361288 }
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 ;
12411289
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 ) {
12431293 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
12461295 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 ;
12501297 }
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) {
12701300 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 ]);
12781301 }
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;
13221306 }
13231307 }
1324- SKIP_UV_NORMAL:
1325- ;
13261308 }
1309+ SKIP_UV_NORMAL:
1310+ ;
13271311 }
13281312 }
13291313 if (rayCallback.m_hitNormalWorld .length2 () > (SIMD_EPSILON * SIMD_EPSILON)) {
@@ -1332,9 +1316,8 @@ PHY_IPhysicsController *CcdPhysicsEnvironment::RayTest(PHY_IRayCastFilterCallbac
13321316 else {
13331317 rayCallback.m_hitNormalWorld .setValue (1 .0f , 0 .0f , 0 .0f );
13341318 }
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 );
13381321 filterCallback.reportHit (&result);
13391322 }
13401323
@@ -3004,6 +2987,7 @@ void CcdPhysicsEnvironment::ConvertObject(BL_SceneConverter& converter, KX_GameO
30042987 // create the compound shape manually as we already have the child shape
30052988 btCompoundShape *compoundShape = new btCompoundShape ();
30062989 compoundShape->addChildShape (shapeInfo->m_childTrans , bm);
2990+ compoundShape->setUserPointer (compoundShapeInfo);
30072991 // now replace the shape
30082992 bm = compoundShape;
30092993 shapeInfo->Release ();
0 commit comments