子弹物理碰撞检测
Bullet physics collision detection
我正在使用 bulletsharp(子弹物理学的 C# 包装器)进行一些碰撞检测。一切顺利,直到我试图在运行时将现有刚体的碰撞形状从盒子更改为复合。我这样做是为了更准确地再次模拟碰撞。问题是:未检测到复合形状的碰撞。
场景:
DicreteDynamicsWorld
包含一些 RigidBody
和 BoxShape
- 两个运动学
RigidBody
与 BoxShape
发生碰撞(并被检测到)
- 使用凸分解的HACD算法将这两个
RigidBody
的形状改为CompoundShape
- 从
DicreteDynamicsWorld
中删除 RigidBody
RigidBody.CollisionShape
= CompoundShape
- 使用
RigidBody.MotionState.WorldTransform
设置位置
- 将
RigidBody
添加到 DicreteDynamicsWorld
- 撤消引起碰撞的运动(一个对象不包含另一个)
- 重复动作
- 未检测到碰撞
备注:
- 将
CollisionShape
从 BoxShape
更改为 CompoundShape
成功(正确的 CollisionShape
和正确的位置)
- 对于碰撞检测,我在
DicreteDynamicsWorld.StepSimulation(...)
之后使用 DicreteDynamicsWorld.Dispatcher.NumManifolds > 0
请求的一些代码片段:
如果您需要什么特别的东西,请告诉我。我的解决方案太大太复杂,无法 post 完整代码...
刚体创建:
// Create rigid body
MotionState motionState = new DefaultMotionState(startTransform);
RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(0.0f, motionState, collisionShape);
RigidBody rigidBody = new RigidBody(rbInfo);
rbInfo.Dispose();
// Kinematic body: mass=0 -> static/kinematic -> use flag
bool isKinematicBody = (compModel.Children[i].Type ==...) || ... ;
rigidBody.CollisionFlags = isKinematicBody ? CollisionFlags.KinematicObject : CollisionFlags.StaticObject;
rigidBody.ActivationState = ActivationState.DisableDeactivation;
基本步骤:
// Get old collision data
if (compModel.Children[i].Container.TryGetValue(ContainerType.Collision, out container))
collisionData = ((ContainerCollision) container).CollisionData;
// Get geometry
if (compModel.Children[i].Container.TryGetValue(ContainerType.Geometry, out container))
{
verticesGeo = ((ContainerGeometry) container).GeometryData.Vertices;
trianglesGeo = ((ContainerGeometry) container).GeometryData.Triangles;
}
// Remove rigid body from world
_world.RemoveRigidBody(collisionData.RigidBody);
// Create new shape
List<Vector3> vertices = Utility.ToBulletVector3List(verticesGeo);
List<int> indices = Utility.ListIntArrayToListInt(trianglesGeo);
CompoundShape collisionShape = ConvexDecomposition(compModel.Children[i].Id, vertices, indices);
// Set collision shape
collisionData.RigidBody.CollisionShape = collisionShape;
// Set position
collisionData.RigidBody.MotionState.WorldTransform *= collisionData.PositionDifference;
// Add rigid body to world
_world.AddRigidBody(collisionData.RigidBody, collisionData.CollisionGroup, collisionData.CollisionMask);
碰撞容器:
public interface IContainer
{
ContainerType Type { get; }
}
public struct ContainerCollision : IContainer
{
public ContainerType Type
{
get { return ContainerType.Collision; }
}
public CollisionData CollisionData;
}
结构碰撞数据:
public struct CollisionData
{
public BulletSharp.RigidBody RigidBody;
public BulletSharp.Matrix PositionDifference;
public BulletSharp.Vector3 ZeroPosition;
public short CollisionGroup;
public short CollisionMask;
}
任何想法,我做错了什么?
谢谢。
假设你所有的造型变化都发生在这里
CompoundShape collisionShape = ConvexDecomposition(compModel.Children[i].Id, vertices, indices);
// Set collision shape
collisionData.RigidBody.CollisionShape = collisionShape;
// Set position
collisionData.RigidBody.MotionState.WorldTransform *= collisionData.PositionDifference;
// Add rigid body to world
_world.AddRigidBody(collisionData.RigidBody, collisionData.CollisionGroup, collisionData.CollisionMask);
可能您必须从头开始重新计算整个 RigidBody,我不知道您一开始是怎么做到的,所以我将向您展示我是如何做到的。
public virtual RigidBody LocalCreateRigidBody(float mass, Matrix startTransform, CollisionShape shape)
{
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.0f);
Vector3 localInertia = Vector3.Zero;
if (isDynamic)
shape.CalculateLocalInertia(mass, out localInertia);
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
DefaultMotionState myMotionState = new DefaultMotionState(startTransform);
RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, myMotionState, shape, localInertia);
RigidBody body = new RigidBody(rbInfo);
rbInfo.Dispose();
return body;
}
话虽如此,请记下您的 "collisionData"(我猜它是 class?)和 RigidBody 的命名(它可能与 BulletSharp class?)
祝您进步愉快,如有任何问题,请随时与我联系!
我正在使用 bulletsharp(子弹物理学的 C# 包装器)进行一些碰撞检测。一切顺利,直到我试图在运行时将现有刚体的碰撞形状从盒子更改为复合。我这样做是为了更准确地再次模拟碰撞。问题是:未检测到复合形状的碰撞。
场景:
DicreteDynamicsWorld
包含一些RigidBody
和BoxShape
- 两个运动学
RigidBody
与BoxShape
发生碰撞(并被检测到) - 使用凸分解的HACD算法将这两个
RigidBody
的形状改为CompoundShape
- 从
DicreteDynamicsWorld
中删除 RigidBody.CollisionShape
=CompoundShape
- 使用
RigidBody.MotionState.WorldTransform
设置位置
- 将
RigidBody
添加到DicreteDynamicsWorld
- 撤消引起碰撞的运动(一个对象不包含另一个)
- 重复动作
- 未检测到碰撞
RigidBody
备注:
- 将
CollisionShape
从BoxShape
更改为CompoundShape
成功(正确的CollisionShape
和正确的位置) - 对于碰撞检测,我在
DicreteDynamicsWorld.StepSimulation(...)
之后使用
DicreteDynamicsWorld.Dispatcher.NumManifolds > 0
请求的一些代码片段:
如果您需要什么特别的东西,请告诉我。我的解决方案太大太复杂,无法 post 完整代码...
刚体创建:
// Create rigid body
MotionState motionState = new DefaultMotionState(startTransform);
RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(0.0f, motionState, collisionShape);
RigidBody rigidBody = new RigidBody(rbInfo);
rbInfo.Dispose();
// Kinematic body: mass=0 -> static/kinematic -> use flag
bool isKinematicBody = (compModel.Children[i].Type ==...) || ... ;
rigidBody.CollisionFlags = isKinematicBody ? CollisionFlags.KinematicObject : CollisionFlags.StaticObject;
rigidBody.ActivationState = ActivationState.DisableDeactivation;
基本步骤:
// Get old collision data
if (compModel.Children[i].Container.TryGetValue(ContainerType.Collision, out container))
collisionData = ((ContainerCollision) container).CollisionData;
// Get geometry
if (compModel.Children[i].Container.TryGetValue(ContainerType.Geometry, out container))
{
verticesGeo = ((ContainerGeometry) container).GeometryData.Vertices;
trianglesGeo = ((ContainerGeometry) container).GeometryData.Triangles;
}
// Remove rigid body from world
_world.RemoveRigidBody(collisionData.RigidBody);
// Create new shape
List<Vector3> vertices = Utility.ToBulletVector3List(verticesGeo);
List<int> indices = Utility.ListIntArrayToListInt(trianglesGeo);
CompoundShape collisionShape = ConvexDecomposition(compModel.Children[i].Id, vertices, indices);
// Set collision shape
collisionData.RigidBody.CollisionShape = collisionShape;
// Set position
collisionData.RigidBody.MotionState.WorldTransform *= collisionData.PositionDifference;
// Add rigid body to world
_world.AddRigidBody(collisionData.RigidBody, collisionData.CollisionGroup, collisionData.CollisionMask);
碰撞容器:
public interface IContainer
{
ContainerType Type { get; }
}
public struct ContainerCollision : IContainer
{
public ContainerType Type
{
get { return ContainerType.Collision; }
}
public CollisionData CollisionData;
}
结构碰撞数据:
public struct CollisionData
{
public BulletSharp.RigidBody RigidBody;
public BulletSharp.Matrix PositionDifference;
public BulletSharp.Vector3 ZeroPosition;
public short CollisionGroup;
public short CollisionMask;
}
任何想法,我做错了什么?
谢谢。
假设你所有的造型变化都发生在这里
CompoundShape collisionShape = ConvexDecomposition(compModel.Children[i].Id, vertices, indices);
// Set collision shape
collisionData.RigidBody.CollisionShape = collisionShape;
// Set position
collisionData.RigidBody.MotionState.WorldTransform *= collisionData.PositionDifference;
// Add rigid body to world
_world.AddRigidBody(collisionData.RigidBody, collisionData.CollisionGroup, collisionData.CollisionMask);
可能您必须从头开始重新计算整个 RigidBody,我不知道您一开始是怎么做到的,所以我将向您展示我是如何做到的。
public virtual RigidBody LocalCreateRigidBody(float mass, Matrix startTransform, CollisionShape shape)
{
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.0f);
Vector3 localInertia = Vector3.Zero;
if (isDynamic)
shape.CalculateLocalInertia(mass, out localInertia);
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
DefaultMotionState myMotionState = new DefaultMotionState(startTransform);
RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, myMotionState, shape, localInertia);
RigidBody body = new RigidBody(rbInfo);
rbInfo.Dispose();
return body;
}
话虽如此,请记下您的 "collisionData"(我猜它是 class?)和 RigidBody 的命名(它可能与 BulletSharp class?)
祝您进步愉快,如有任何问题,请随时与我联系!