【问题标题】:Bullet physics collision detection子弹物理碰撞检测
【发布时间】:2018-01-08 14:21:27
【问题描述】:

我正在使用 bulletsharp(子弹物理的 C# 包装器)进行一些碰撞检测。一切都很顺利,直到我尝试在运行时将现有刚体的碰撞形状从盒子更改为复合。我这样做是为了再次以更高的精度模拟碰撞。问题是:没有检测到复合形状的碰撞。

场景:

  • DicreteDynamicsWorld 包含一些 RigidBodyBoxShape
  • 两个运动学RigidBodyBoxShape 发生碰撞(并被检测到)
  • 使用 HACD 算法将这两个 RigidBody 的形状更改为 CompoundShape 进行凸分解
  • DicreteDynamicsWorld 中删除RigidBody
  • RigidBody.CollisionShape = CompoundShape
  • 使用RigidBody.MotionState.WorldTransform设置位置
  • RigidBody 添加到DicreteDynamicsWorld
  • 撤消导致碰撞的移动(一个对象不包含另一个)
  • 重复动作
  • 未检测到碰撞

备注:

  • CollisionShapeBoxShape 更改为CompoundShape 成功(正确的CollisionShape 和正确的位置)
  • 对于碰撞检测,我在DicreteDynamicsWorld.StepSimulation(...) 之后使用DicreteDynamicsWorld.Dispatcher.NumManifolds > 0

按要求提供一些代码 sn-ps:

如果你需要一些特别的东西,请告诉我。我的解决方案太大太复杂,无法发布完整代码...

刚体创建:

// 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;
}

任何想法,我做错了什么?

谢谢。

【问题讨论】:

  • 欢迎来到 SO。你能发布一些代码而不是伪代码吗?
  • 请发布实际代码。

标签: c# collision-detection bulletphysics bullet


【解决方案1】:

假设你所有的形状变化都发生在这里

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”(我猜它是一个类?)和 RigidBody 的命名(它可能与 BulletSharp 类冲突?)

为您的进步提供最好的保护,如果您有任何问题,请随时与我联系!

【讨论】:

  • 感谢您的回答。我添加了RigidBody 创建和我的CollisionData 结构的代码sn-p...重新计算RigidBody 并不能解决问题。我还尝试了对结构中 RigidBody 元素的不同命名,没有变化...
  • 最近几天我尝试了很多不同的东西,似乎重新计算RigidBody确实解决了问题!我刚刚发现我犯了一个非常愚蠢的错误:我用旧的RigidBody 实现了我的CollisionContainer,而不是重新计算的...
  • 很高兴能为您提供帮助,祝您进步!
猜你喜欢
  • 2018-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多