在不更正网格位置的情况下,沿一个方向原地缩放Three.js几何体。

3
我们正在尝试构建“编辑手柄”,允许用户通过在8个位置之一拖动来调整(投影的)平面的大小(4个角落+4个边缘)。这种调整大小只应在拖动方向上缩放/拉伸表面,因此three.js的默认比例机制不适用,因为它会同时沿着两个相反的方向进行缩放,就像在此示例中看到的那样。
我已经阅读并尝试了很多内容,特别是这两篇文章:
- 仅将Three.js几何体缩放 - 以顶部为参考在一个方向上缩放几何体 按照这些方法,我得到了以下结果:
// preparing to resize into -x direction aka "left edge"
// moving the geometry center to the right edge
mesh.geometry.translate(width/2, 0, 0);
mesh.geometry.scale(scaleX, 1, 1);
// moving the geometry center back to the middle 
// as more resizing might happen, into another direction, as per comment here: 
// https://dev59.com/KIXca4cB1Zd3GeqPCAFG#PlYdoYgBc1ULPQZFJVAG
mesh.geometry.translate(-(width/2 * scaleX), 0, 0);

结果与我的期望不符: 缩放发生在两个相反的方向,因此平移彼此抵消 - 因此,如果将中心/原点放置在右边缘,则缩放不会发生,或者是我有误解。 另一方面,这个可以正常工作。
mesh.scale.set(scaleX, 1, 1);
mesh.position.x = (-width / 2);

但是反复重置网格的位置真的很不专业,而且我曾经看过缩放网格的性能较差,因为这种转换需要每一帧都重新应用(但我可能记错了:Three.js - Scale model with scale.set() or increase model size?),而对基础几何图形的变换则已被融入数据中。
我还查看了TransformControls源代码,但由于它不能按我们想要的方式工作,并且我还没有完全理解四元数的概念,所以我就放弃了。
那么我的问题是:有没有一种方法可以进行单向调整大小而不必纠正网格的位置?
1个回答

3

你发现了解决这个问题的两种方法。

  1. 缩放几何体。
  2. 缩放网格并调整其中心位置。

首先,让我们讨论选项1,但我不推荐使用,原因稍后会说明。

要在线性单方向上缩放几何体,仍然需要将所有顶点朝着缩放方向移动。因此,对于每个顶点,您需要根据该顶点将接收到的缩放量计算其新位置(最靠近缩放面的顶点移动最多,中间的顶点移动一半,而在缩放相反侧的顶点几乎不移动)。如果您正在进行实时缩放,则可能需要进行大量计算。

现在考虑选项2:您更改整个网格的矩阵(包括其新位置)。就是这样。该矩阵被发送到 GPU,由 GPU 处理其余部分。如您所知,GPU 在数学方面(包括矩阵数学)非常出色,而 JavaScript 则... 不太擅长,或者至少要慢得多。执行矩阵操作对 GPU 来说是小菜一碟。

更不用说,有了变换矩阵,您始终可以获得顶点的世界位置:

vertexCopy.set(myMesh.geometry.attributes.position.getX(index),
    myMesh.geometry.attributes.position.getY(index).
    myMesh.geometry.attributes.position.getZ(index));
myMesh.localToWorld(vertexCopy);

简介:

如果说操作变换矩阵是“hacky”,那么操纵几何形状就更加“hacky”了。这就好比你要告诉系统如何绘制正方形的每个像素,而实际上你只需要告诉它绘制一个正方形。

  1. 更新几何形状计算成本很高。尽管顶点在此之后基本上已经“烤”好了,但下一次操作仍会触发更多的计算。

  2. 更新网格的矩阵很简单,并将计算复杂度转移到了GPU上,GPU处理这些信息时不会有任何问题。

你可以选择适合你需求的任何方法,但根据你提供的信息,我非常推荐第二种选项。

第三个想法:

你可以使用Morph Targets来实现所需效果,但我没有太多的经验。 这里有一个通过morphing变形的立方体示例。 你需要影响多个morph targets才能达到你想要的效果,但这仍然比操纵几何形状要好,因为morph manipulations将在GPU上完成。


好的,为了避免混淆 - 结尾的选项与开头的选项相反是有意为之吗? - Benjamin Seiller
写完评论后无法更改...... 首先,非常感谢您详细的回答。 为了避免混淆:最后的选项是有意与开头相反吗?_...(见上文)_ 接着,您能给我指出如何调整网格的中心位置的示例吗? 我不知道这也是可能的。 除非您是指使用 .translate 等来更改位置。 - Benjamin Seiller
  1. 抱歉,我为了更清晰地调整选项的顺序。怪一天太长了。 :)
  2. 是的,我只是想将网格转换以补偿新比例。
  3. 我马上会再进行编辑...
- TheJim01

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接