【问题标题】:Three.js add: keep position [duplicate]三.js添加:保持位置[重复]
【发布时间】:2016-11-21 22:08:26
【问题描述】:

当我将 Object3D 添加到另一个 Object3D(“add”方法)时,子级会根据父级更改其变换。

在将孩子添加到父母后,有没有办法保持孩子的位置/旋转/比例?

小提琴:https://jsfiddle.net/pqfzd8a2/1/

mesh = new THREE.Mesh(geometry, material);    
mesh.position.y = 25;

var mesh2 = mesh.clone();
mesh2.position.y = 80;

var mesh3 = mesh2.clone();

mesh.rotation.z = Math.PI*0.25;

scene.add(mesh);    
mesh.add(mesh2);
scene.add(mesh3);

做了什么?

  1. 网格已旋转。
  2. mesh2 和mesh3 是彼此相同位置的克隆。
  3. mesh2 已添加到网格中,而 mesh3 已添加到场景中。

mesh2 和mesh3 的区别在于它们被添加(父级)到不同的父级(相应地添加到网格和直接添加到场景中)。在被添加(父母)之前,他们处于相同的位置。关键是将对象保持在添加(父级)之前的位置。

预期结果:mesh2 和mesh3 应该在相同的位置。

实际结果:mesh2添加后改变了位置/旋转/缩放。

如何使对象在成为父对象后保持其全局变换?

【问题讨论】:

  • 具体的用例是什么?为什么你真的需要一个子对象,它应该在层次结构中的父级?为什么你不能把孩子移到另一个层次?
  • 移动子对象在物理和传感器系统中很重要,这些对象可能会改变它们的放置位置(即使在运行时)。对象(世界)的位置应该始终保持不变。本地矩阵应该反映父关系(这就是为什么它是本地空间)。改变层次结构是没有问题的,事实上世界矩阵正在被修改,因此每次移动它时,你都需要有一个前后行为来维护它。这是一个典型的场景图错误,使管理对象变得极其困难。
  • 对 q 的回应:我建议您实现自己的 Push/Pop 堆栈并创建自己的子/父层次结构。否则管理动态实体的大型场景结构将非常困难。如果您想要更“松散”的层次结构,可以使用轻量级位置数据库。我已经为此目的实施了 OpenSteers LQ DB。

标签: three.js transform reparenting


【解决方案1】:

嗯,这就是定义的行为,至少是这些层次结构存在的原因。如果您不想将父级的变换应用于子级,则没有理由将这些项设置为父级。

使用这种方法可以更轻松地处理由较小对象组成的复杂对象,例如带轮子的汽车。不是移动汽车,然后移动每个车轮,而是让车轮成为汽车的孩子,它们将一直移动/旋转/缩放。这就是父母的转变是如何被所有孩子“继承”的。所以他们的变换是相对于他们各自的父母。就像月亮绕着地球转,地球绕着太阳转,又绕着太阳转……

如果你真的需要在孩子内部取消父母变换,那么你需要将父母变换的逆应用于孩子的变换,但正如我所说,这没有多大意义,因为你只是不需要为他们做父母,你就完成了。

【讨论】:

  • 这是一个错误的陈述。你是说当你改变孩子的父母时改变一个对象的世界矩阵是“好的”。世界矩阵应该保持不变,本地矩阵(对于孩子)应该根据父母的关系而改变。这是一个普通层次的场景图(甚至回到SGI Performer,它应该是这样工作的)。如果您每次从父级添加/删除子级时更改子级的世界位置,则当对象重新设置为父级时,您需要具有前置和后置行为。这显然是不正确的。
【解决方案2】:

不,它们不应该处于相同的位置,因为您正在更改网格和网格 2 的位置和旋转。如果要将网格添加到另一个网格,则将其添加到父上下文中。

mesh.add(mesh2); // <-- mesh is translated and rotated, mesh2 will inherit the same context

在这个小提琴中,您会看到网格上的旋转也适用于 mesh2:https://jsfiddle.net/r57opdgn/

【讨论】:

  • 是的,我将它添加到父上下文中。但是如何让孩子保持它的位置呢?
  • 当你将mesh2 添加到mesh 时,你也在改变上下文(mesh 是原点),如果你想在你的场景中保持mesh2 在空间中的相同翻译的mesh,将position.y 重置为零:mesh2.position.y = 0。如果要使用全局轴,则不应将 mesh2 设置为 mesh 的子级。
  • 当您更改对象的父级时,世界矩阵应该永远被更改。 ThreeJS 在这种方式上很奇怪——当它变成一个孩子时,你不会找到移动对象的世界位置的其他引擎。这样做的问题是,在世界位置下方被复制到本地位置 - 这是不正确的数学行为。子世界矩阵应保持 the_same 并且其局部矩阵会根据其父关系发生变化。
猜你喜欢
  • 2011-02-13
  • 2012-04-27
  • 1970-01-01
  • 2013-04-18
  • 1970-01-01
  • 2013-07-02
  • 2018-07-03
  • 2014-12-05
  • 2019-02-17
相关资源
最近更新 更多