|
60 | 60 | #include <algorithm> |
61 | 61 | #include <vector> |
62 | 62 |
|
| 63 | +#include <cmath> |
| 64 | + |
63 | 65 | namespace dart { |
64 | 66 | namespace collision { |
65 | 67 |
|
@@ -91,17 +93,15 @@ std::unique_ptr<btCollisionShape> createBulletEllipsoidMesh( |
91 | 93 | std::unique_ptr<btCollisionShape> createBulletEllipsoidMultiSphere( |
92 | 94 | const Eigen::Vector3d& radii); |
93 | 95 |
|
94 | | -std::unique_ptr<btCollisionShape> createBulletCollisionShapeFromAssimpScene( |
95 | | - const Eigen::Vector3d& scale, const aiScene* scene); |
96 | | - |
97 | | -std::unique_ptr<btCollisionShape> createBulletCollisionShapeFromAssimpMesh( |
98 | | - const aiMesh* mesh); |
| 96 | +std::unique_ptr<btCollisionShape> createBulletCollisionShapeFromTriMesh( |
| 97 | + const Eigen::Vector3d& scale, |
| 98 | + const std::shared_ptr<math::TriMesh<double>>& mesh); |
99 | 99 |
|
100 | 100 | template <typename HeightmapShapeT> |
101 | 101 | std::unique_ptr<BulletCollisionShape> createBulletCollisionShapeFromHeightmap( |
102 | 102 | const HeightmapShapeT* heightMap); |
103 | 103 |
|
104 | | -bool isConvex(const aiMesh* mesh, float threshold = 0.001); |
| 104 | +bool isConvex(const math::TriMesh<double>& mesh, float threshold = 0.001f); |
105 | 105 |
|
106 | 106 | } // anonymous namespace |
107 | 107 |
|
@@ -649,17 +649,19 @@ BulletCollisionDetector::createBulletCollisionShape( |
649 | 649 | std::move(bulletCollisionShape)); |
650 | 650 | } else if (const auto shapeMesh = shape->as<MeshShape>()) { |
651 | 651 | const auto scale = shapeMesh->getScale(); |
652 | | - const auto mesh = shapeMesh->getMesh(); |
| 652 | + const auto triMesh = shapeMesh->getTriMesh(); |
653 | 653 |
|
654 | 654 | auto bulletCollisionShape |
655 | | - = createBulletCollisionShapeFromAssimpScene(scale, mesh); |
| 655 | + = createBulletCollisionShapeFromTriMesh(scale, triMesh); |
656 | 656 |
|
657 | 657 | return std::make_unique<BulletCollisionShape>( |
658 | 658 | std::move(bulletCollisionShape)); |
659 | 659 | } else if (const auto softMeshShape = shape->as<SoftMeshShape>()) { |
660 | | - const auto mesh = softMeshShape->getAssimpMesh(); |
| 660 | + const auto triMesh = softMeshShape->getTriMesh(); |
| 661 | + const Eigen::Vector3d scale = Eigen::Vector3d::Ones(); |
661 | 662 |
|
662 | | - auto bulletCollisionShape = createBulletCollisionShapeFromAssimpMesh(mesh); |
| 663 | + auto bulletCollisionShape |
| 664 | + = createBulletCollisionShapeFromTriMesh(scale, triMesh); |
663 | 665 |
|
664 | 666 | return std::make_unique<BulletCollisionShape>( |
665 | 667 | std::move(bulletCollisionShape)); |
@@ -1015,62 +1017,40 @@ std::unique_ptr<btCollisionShape> createBulletEllipsoidMultiSphere( |
1015 | 1017 | } |
1016 | 1018 |
|
1017 | 1019 | //============================================================================== |
1018 | | -std::unique_ptr<btCollisionShape> createBulletCollisionShapeFromAssimpScene( |
1019 | | - const Eigen::Vector3d& scale, const aiScene* scene) |
| 1020 | +std::unique_ptr<btCollisionShape> createBulletCollisionShapeFromTriMesh( |
| 1021 | + const Eigen::Vector3d& scale, |
| 1022 | + const std::shared_ptr<math::TriMesh<double>>& mesh) |
1020 | 1023 | { |
1021 | | - auto triMesh = new btTriangleMesh(); |
1022 | | - |
1023 | | - for (auto i = 0u; i < scene->mNumMeshes; ++i) { |
1024 | | - for (auto j = 0u; j < scene->mMeshes[i]->mNumFaces; ++j) { |
1025 | | - btVector3 vertices[3]; |
1026 | | - for (auto k = 0u; k < 3; ++k) { |
1027 | | - const aiVector3D& vertex |
1028 | | - = scene->mMeshes[i] |
1029 | | - ->mVertices[scene->mMeshes[i]->mFaces[j].mIndices[k]]; |
1030 | | - vertices[k] = btVector3( |
1031 | | - vertex.x * scale[0], vertex.y * scale[1], vertex.z * scale[2]); |
1032 | | - } |
1033 | | - triMesh->addTriangle(vertices[0], vertices[1], vertices[2]); |
1034 | | - } |
1035 | | - } |
1036 | | - const bool makeConvexMesh |
1037 | | - = scene->mNumMeshes == 1 && isConvex(scene->mMeshes[0]); |
1038 | | - if (makeConvexMesh) { |
1039 | | - auto convexMeshShape = std::make_unique<btConvexTriangleMeshShape>(triMesh); |
1040 | | - convexMeshShape->setMargin(0.0f); |
1041 | | - convexMeshShape->setUserPointer(triMesh); |
1042 | | - return convexMeshShape; |
1043 | | - } else { |
1044 | | - auto gimpactMeshShape = std::make_unique<btGImpactMeshShape>(triMesh); |
1045 | | - gimpactMeshShape->updateBound(); |
1046 | | - gimpactMeshShape->setUserPointer(triMesh); |
1047 | | - return gimpactMeshShape; |
| 1024 | + if (!mesh) { |
| 1025 | + return nullptr; |
1048 | 1026 | } |
1049 | | -} |
1050 | 1027 |
|
1051 | | -//============================================================================== |
1052 | | -std::unique_ptr<btCollisionShape> createBulletCollisionShapeFromAssimpMesh( |
1053 | | - const aiMesh* mesh) |
1054 | | -{ |
1055 | 1028 | auto triMesh = new btTriangleMesh(); |
1056 | 1029 |
|
1057 | | - for (auto i = 0u; i < mesh->mNumFaces; ++i) { |
1058 | | - btVector3 vertices[3]; |
1059 | | - for (auto j = 0u; j < 3; ++j) { |
1060 | | - const aiVector3D& vertex = mesh->mVertices[mesh->mFaces[i].mIndices[j]]; |
1061 | | - vertices[j] = btVector3(vertex.x, vertex.y, vertex.z); |
| 1030 | + const auto& vertices = mesh->getVertices(); |
| 1031 | + const auto& triangles = mesh->getTriangles(); |
| 1032 | + |
| 1033 | + for (const auto& triangle : triangles) { |
| 1034 | + btVector3 btVertices[3]; |
| 1035 | + for (auto k = 0u; k < 3; ++k) { |
| 1036 | + const auto& vertex = vertices[triangle[k]]; |
| 1037 | + btVertices[k] = btVector3( |
| 1038 | + vertex.x() * scale[0], vertex.y() * scale[1], vertex.z() * scale[2]); |
1062 | 1039 | } |
1063 | | - triMesh->addTriangle(vertices[0], vertices[1], vertices[2]); |
| 1040 | + triMesh->addTriangle(btVertices[0], btVertices[1], btVertices[2]); |
1064 | 1041 | } |
1065 | 1042 |
|
1066 | | - const bool makeConvexMesh = isConvex(mesh); |
| 1043 | + const bool makeConvexMesh = isConvex(*mesh); |
| 1044 | + |
1067 | 1045 | if (makeConvexMesh) { |
1068 | 1046 | auto convexMeshShape = std::make_unique<btConvexTriangleMeshShape>(triMesh); |
1069 | 1047 | convexMeshShape->setMargin(0.0f); |
| 1048 | + convexMeshShape->setUserPointer(triMesh); |
1070 | 1049 | return convexMeshShape; |
1071 | 1050 | } else { |
1072 | 1051 | auto gimpactMeshShape = std::make_unique<btGImpactMeshShape>(triMesh); |
1073 | 1052 | gimpactMeshShape->updateBound(); |
| 1053 | + gimpactMeshShape->setUserPointer(triMesh); |
1074 | 1054 | return gimpactMeshShape; |
1075 | 1055 | } |
1076 | 1056 | } |
@@ -1144,43 +1124,54 @@ std::unique_ptr<BulletCollisionShape> createBulletCollisionShapeFromHeightmap( |
1144 | 1124 | } |
1145 | 1125 |
|
1146 | 1126 | //============================================================================== |
1147 | | -bool isConvex(const aiMesh* mesh, float threshold) |
| 1127 | +bool isConvex(const math::TriMesh<double>& mesh, float threshold) |
1148 | 1128 | { |
1149 | | - // Check whether all the other vertices on the mesh is on the internal side of |
1150 | | - // the face, assuming that the direction of the normal of the face is pointing |
1151 | | - // external side. |
| 1129 | + // Check whether all the other vertices on the mesh are on the internal side |
| 1130 | + // of the face, assuming that the direction of the normal of the face is |
| 1131 | + // pointing to the external side. |
1152 | 1132 | // |
1153 | 1133 | // Reference: https://stackoverflow.com/a/40056279/3122234 |
| 1134 | + const auto& points = mesh.getVertices(); |
| 1135 | + const auto& triangles = mesh.getTriangles(); |
| 1136 | + |
| 1137 | + if (points.empty() || triangles.empty()) { |
| 1138 | + return false; |
| 1139 | + } |
1154 | 1140 |
|
1155 | | - const auto points = mesh->mVertices; |
1156 | 1141 | btVector3 vertices[3]; |
1157 | | - for (auto i = 0u; i < mesh->mNumFaces; ++i) { |
| 1142 | + for (const auto& triangle : triangles) { |
1158 | 1143 | for (auto j = 0u; j < 3; ++j) { |
1159 | | - const aiVector3D& vertex = mesh->mVertices[mesh->mFaces[i].mIndices[j]]; |
1160 | | - vertices[j] = btVector3(vertex.x, vertex.y, vertex.z); |
| 1144 | + const auto& vertex = points[triangle[j]]; |
| 1145 | + vertices[j] = btVector3(vertex.x(), vertex.y(), vertex.z()); |
1161 | 1146 | } |
1162 | 1147 | const btVector3& A = vertices[0]; |
1163 | 1148 | const btVector3 B = vertices[1] - A; |
1164 | 1149 | const btVector3 C = vertices[2] - A; |
1165 | 1150 |
|
1166 | | - const btVector3 BCNorm = B.cross(C).normalized(); |
| 1151 | + const btVector3 BCNormRaw = B.cross(C); |
| 1152 | + const btScalar normSquared = BCNormRaw.length2(); |
| 1153 | + if (normSquared <= btScalar(0.0)) { |
| 1154 | + continue; |
| 1155 | + } |
| 1156 | + const btVector3 BCNorm = BCNormRaw / btSqrt(normSquared); |
1167 | 1157 |
|
1168 | | - const float checkPoint |
1169 | | - = btVector3( |
1170 | | - points[0].x - A.x(), points[0].y - A.y(), points[0].z - A.z()) |
1171 | | - .dot(BCNorm); |
| 1158 | + const float checkPoint = btVector3( |
| 1159 | + points[0].x() - A.x(), |
| 1160 | + points[0].y() - A.y(), |
| 1161 | + points[0].z() - A.z()) |
| 1162 | + .dot(BCNorm); |
1172 | 1163 |
|
1173 | | - for (auto j = 0u; j < mesh->mNumVertices; ++j) { |
1174 | | - float dist |
1175 | | - = btVector3( |
1176 | | - points[j].x - A.x(), points[j].y - A.y(), points[j].z - A.z()) |
| 1164 | + for (const auto& point : points) { |
| 1165 | + const float dist |
| 1166 | + = btVector3(point.x() - A.x(), point.y() - A.y(), point.z() - A.z()) |
1177 | 1167 | .dot(BCNorm); |
1178 | 1168 | if ((std::abs(checkPoint) > threshold) && (std::abs(dist) > threshold) |
1179 | 1169 | && (checkPoint * dist < 0.0f)) { |
1180 | 1170 | return false; |
1181 | 1171 | } |
1182 | 1172 | } |
1183 | 1173 | } |
| 1174 | + |
1184 | 1175 | return true; |
1185 | 1176 | } |
1186 | 1177 |
|
|
0 commit comments