如何在复合身体部位设置不同的碰撞过滤器

问题描述 投票:0回答:1

我正在尝试使用 2D 物理引擎来模拟边缘带有销钉的旋转圆盘。销钉可能会与其他物体碰撞,从而阻止圆盘进一步旋转,或者将其他物体推开。光盘本身不会与任何东西碰撞(因为它在另一个平面上)。

Ahmer, Syed Mohammad & Khan, Nusratullah & Shah, S. Inayat & Jan, lal said. (2019). Experimental Results of the Tribology of Aluminum in the Presence of Polytron Additive. 10.5772/intechopen.84620.

我一直在努力在 Matter.js 中实现这一目标,但我以前从未使用过它。

首先,我将圆盘的

collisionFilter = { .mask: 0 }
以及销钉和驱动对象设置为
collisionFilter: { .category: 1, .mask: 1 }
。圆盘不应与任何物体碰撞,并且销轴和从动物体应碰撞。

然后我尝试了两种形成圆盘和销钉的方法:

  1. 创建一个由两部分组成的复合体。然而,根据本期2017,“零件不能有自己的

    collisionFilter
    ,只有父母受到尊重。”

  2. 创建两个独立的实体,它们之间有刚性约束,以固定圆盘和销钉的相对位置。这成功地达到了预期的效果,当圆盘旋转时,销钉随之移动(反之亦然)。

    但是,这里的问题是销钉仍然可以绕其中心旋转。如果引脚是方形的,则最明显。

    (另外我不确定这个方法是否可以让我控制圆盘的转动惯量?)

这可以实现吗?法学硕士试图让我设置一个

beforeUpdate
事件来抵消销钉的角速度。但我的预感是我正在做的事情不应该那么复杂?

matter.js
1个回答
0
投票

几个小时后,我无法确定如何使用 Matter.js 来做到这一点。我切换到 Planck.js 它解决了我使用 Matter.js 的两个问题:

  1. 我可以在构成单个主体的固定装置(物理部件)上定义不同的碰撞属性。

  2. 我可以使用不同类型的关节,例如

    WeldJoint
    RevoluteJoint
    ,这使得对身体之间的复杂关系进行建模变得更容易。

在以下可以在Playground上运行的示例中,我创建了三个圆盘和销钉主体,如我的问题中所述,以模拟密码锁的轮组。尸体同心堆叠。每个光盘都有一个销钉,与下一张光盘上的苍蝇(基本上是另一个销钉)连接以驱动它。

planck.testbed('WheelPack', function(testbed) {
  let pl = planck, Vec2 = pl.Vec2, Transform = pl.Transform;
  let world = new pl.World(Vec2(0, 0)); // no gravity

  // unsure how to disable the mouse in testbed mode
  testbed.mouseForce = 0.01;

  let discRadius = 2;
  let pinSize = 0.2;
  let flySize = 0.2;

  function createWheel(position, angle, index) {
    let discFixture = pl.Circle(discRadius);
    let pinFixture = pl.Box(pinSize, pinSize, Vec2(discRadius - pinSize, 0));
    let flyFixture = pl.Box(flySize, flySize, Vec2(-(discRadius - flySize), 0));

    let wheel = world.createBody({
      type: 'dynamic',
      position: position,
      angle: angle,

      // prevent wheels from spinning when force is removed
      angularDamping: 20,
    });

    wheel.createFixture(discFixture, {
      density: 1,
      filterMaskBits: 0,
    });

    wheel.createFixture(pinFixture, {
      density: 1,
      filterCategoryBits: 1 << index,
      filterMaskBits: 1 << index,
    });

    wheel.createFixture(flyFixture, {
      density: 1,
      filterCategoryBits: 1 << (index + 1),
      filterMaskBits: 1 << (index + 1),
    });


    // Add a revolute joint to fix wheel in place
    world.createJoint(pl.RevoluteJoint({
      enableMotor: false
    }, world.createBody(), wheel, wheel.getPosition()));

    return wheel;
  }

  let wheel1 = createWheel(Vec2(0, 0), 0, 1);
  let wheel2 = createWheel(Vec2(0, 0), Math.PI / 3, 2); // offset by 60 degrees
  let wheel3 = createWheel(Vec2(0, 0), -Math.PI / 3, 3); // offset by -60 degrees

  testbed.step = function() {
    let format = (angle) => ((100 + 50 * angle / Math.PI) % 100).toFixed(1)
    testbed.status('wheel 1', format(wheel1.getAngle()));
    testbed.status('wheel 2', format(wheel2.getAngle()));
    testbed.status('wheel 3', format(wheel3.getAngle()));
    if (testbed.activeKeys.right) {
      wheel3.setAngularVelocity(-2);
    } else if (testbed.activeKeys.left) {
      wheel3.setAngularVelocity(2);
    } else {
        wheel3.setAngularVelocity(0);
    }
  };

  testbed.info('Use arrow keys to rotate wheel 3.');

  return world;
})

一些补充意见:

  1. 调整主体的

    angularDamping
    来控制销钉不再被驱动后圆盘减速的速度。

  2. 我使用

    filterMaskBits: 0
    来防止与给定夹具(光盘)发生任何碰撞。

  3. 我使用

    filterCategoryBits
    filterMaskBits
    来控制哪些对象由给定引脚驱动,就像这些对象位于不同的平面上一样。

  4. 轮体上的

    RevoluteJoint
    使其能够像风车一样绕其中心点旋转,而不会旋转到太空中。

© www.soinside.com 2019 - 2024. All rights reserved.