#c# #bulletphysics
#c# #Физика пули
Вопрос:
Я разрабатываю игровой движок на c # и использую BulletSharp для физики. Он работает хорошо, за исключением кубов:
http://i.stack.imgur.com/EPfrw.png
(Ограничивающая рамка, выровненная по оси, — прозрачная красная, модель — белая)
В состоянии покоя они стоят на своих ребрах. Поскольку я загружаюсь из моделей Collada, я создаю ConvexHullShape()
и добавляю данные в виде векторного облака. Хотя использование BoxShape()
было бы более эффективным (и работало бы корректно), я не могу, поскольку не гарантируется, что все модели являются кубами. Я не могу понять, почему они опираются на вершины, а не на плоские ребра. Является ли моя реализация ConvexHullShape
неправильной или мне нужно использовать другой тип формы (для правильной работы физики)?
public RigidBody AddDynamicGeometry(ColladaGeometry geometry, Matrix4 transform)
{
List<Vector3> points = new List<Vector3>();
foreach (Triangle tri in geometry.triangles)
{
points.Add(tri.vertices[0]);
points.Add(tri.vertices[1]);
points.Add(tri.vertices[2]);
}
CollisionShape shape = new ConvexHullShape(points);
shape.UserObject = geometry;
collisionShapes.Add(shape);
RigidBody body = CreateRigidBody(geometry.triangles.Count * 10, transform, shape);
return body;
}
public RigidBody CreateRigidBody(float mass, Matrix4 startTransform, CollisionShape shape)
{
bool isDynamic = (mass != 0.0f);
Vector3 localInertia = Vector3.Zero;
if (isDynamic)
shape.CalculateLocalInertia(mass, out localInertia);
DefaultMotionState myMotionState = new DefaultMotionState(startTransform);
RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, myMotionState, shape, localInertia);
RigidBody body = new RigidBody(rbInfo);
physics_world.AddRigidBody(body);
return body;
}
Ответ №1:
ConvexHullShape ожидает, что центр масс (COM) будет равен (0,0,0), но куб смещен от центра, что приводит к его наклону к углу.
Вы можете найти правильный COM с помощью ConvexTriangleMeshShape.Вычислите первичную форму преобразования галактики. Затем вы можете вычесть COM из каждой вершины, чтобы вернуть COM обратно в 0. Однако проще создать CompoundShape с локальным центром для куба.
// Create a ConvexTriangleMeshShape from the points
const int indexStride = 3 * sizeof(int);
const int vertexStride = 12;
int vertexCount = points.Count;
int indexCount = vertexCount / 3;
TriangleIndexVertexArray vertexArray = new TriangleIndexVertexArray();
IndexedMesh mesh = new IndexedMesh();
mesh.Allocate(vertexCount, vertexStride, indexCount, indexStride);
Vector3Array vdata = mesh.Vertices;
IntArray idata = mesh.TriangleIndices;
for (int i = 0; i < vertexCount; i )
{
vdata[i] = points[i];
idata[i] = i;
}
vertexArray.AddIndexedMesh(mesh);
ConvexTriangleMeshShape shape = new ConvexTriangleMeshShape(vertexArray, true);
// Calculate center of mass
Matrix center = Matrix.Identity;
Vector3 inertia;
float volume;
shape.CalculatePrincipalAxisTransform(ref center, out inertia, out volume);
// Create a CompoundShape with COM offset
CompoundShape compound = new CompoundShape();
compound.AddChildShape(Matrix.Invert(center), shape);
Примечание: ConvexTriangleMeshShape.CalculatePrincipalAxisTransform работает в SVN trunk, но не в BulletSharp 2.82. Скоро будет выпущено исправление.