const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) { btCollisionShape* shape = NULL; int type = info.getType(); switch(type) { case SHAPE_TYPE_BOX: { shape = new btBoxShape(glmToBullet(info.getHalfExtents())); } break; case SHAPE_TYPE_SPHERE: { glm::vec3 halfExtents = info.getHalfExtents(); float radius = glm::max(halfExtents.x, glm::max(halfExtents.y, halfExtents.z)); shape = new btSphereShape(radius); } break; case SHAPE_TYPE_ELLIPSOID: { glm::vec3 halfExtents = info.getHalfExtents(); float radius = halfExtents.x; const float MIN_RADIUS = 0.001f; const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; if (radius > MIN_RADIUS && fabsf(radius - halfExtents.y) / radius < MIN_RELATIVE_SPHERICAL_ERROR && fabsf(radius - halfExtents.z) / radius < MIN_RELATIVE_SPHERICAL_ERROR) { // close enough to true sphere shape = new btSphereShape(radius); } else { ShapeInfo::PointList points; points.reserve(NUM_UNIT_SPHERE_DIRECTIONS); for (uint32_t i = 0; i < NUM_UNIT_SPHERE_DIRECTIONS; ++i) { points.push_back(bulletToGLM(_unitSphereDirections[i]) * halfExtents); } shape = createConvexHull(points); } } break; case SHAPE_TYPE_CAPSULE_Y: { glm::vec3 halfExtents = info.getHalfExtents(); float radius = halfExtents.x; float height = 2.0f * halfExtents.y; shape = new btCapsuleShape(radius, height); } break; case SHAPE_TYPE_COMPOUND: case SHAPE_TYPE_SIMPLE_HULL: { const ShapeInfo::PointCollection& pointCollection = info.getPointCollection(); uint32_t numSubShapes = info.getNumSubShapes(); if (numSubShapes == 1) { shape = createConvexHull(pointCollection[0]); } else { auto compound = new btCompoundShape(); btTransform trans; trans.setIdentity(); foreach (const ShapeInfo::PointList& hullPoints, pointCollection) { btConvexHullShape* hull = createConvexHull(hullPoints); compound->addChildShape(trans, hull); } shape = compound; } } break; case SHAPE_TYPE_SIMPLE_COMPOUND: { const ShapeInfo::PointCollection& pointCollection = info.getPointCollection(); const ShapeInfo::TriangleIndices& triangleIndices = info.getTriangleIndices(); uint32_t numIndices = triangleIndices.size(); uint32_t numMeshes = info.getNumSubShapes(); const uint32_t MIN_NUM_SIMPLE_COMPOUND_INDICES = 2; // END_OF_MESH_PART + END_OF_MESH if (numMeshes > 0 && numIndices > MIN_NUM_SIMPLE_COMPOUND_INDICES) { uint32_t i = 0; std::vector<btConvexHullShape*> hulls; for (auto& points : pointCollection) { // build a hull around each part while (i < numIndices) { ShapeInfo::PointList hullPoints; hullPoints.reserve(points.size()); while (i < numIndices) { int32_t j = triangleIndices[i]; ++i; if (j == END_OF_MESH_PART) { // end of part break; } hullPoints.push_back(points[j]); } if (hullPoints.size() > 0) { btConvexHullShape* hull = createConvexHull(hullPoints); hulls.push_back(hull); } assert(i < numIndices); if (triangleIndices[i] == END_OF_MESH) { // end of mesh ++i; break; } } } uint32_t numHulls = (uint32_t)hulls.size(); if (numHulls == 1) { shape = hulls[0]; } else { auto compound = new btCompoundShape(); btTransform trans; trans.setIdentity(); for (auto hull : hulls) { compound->addChildShape(trans, hull); } shape = compound; } } } break; case SHAPE_TYPE_STATIC_MESH: { btTriangleIndexVertexArray* dataArray = createStaticMeshArray(info); if (dataArray) { shape = new StaticMeshShape(dataArray); } } break; }
PhysicsObject* PhysicsMgr::createConvexHull(GfxObject* object,Ogre::Vector3 pos) { return createConvexHull(object->getEntity()->getMesh()->getName(),pos); }