在 ThreeJS 中缩放 OBJ 的一部分

Posted

技术标签:

【中文标题】在 ThreeJS 中缩放 OBJ 的一部分【英文标题】:Scale part of an OBJ in ThreeJS 【发布时间】:2018-03-26 16:14:15 【问题描述】:

我有一个如下所示的.obj 文件:

我需要做的是仅缩放手柄的特定部分 - 在这种情况下,手柄实际从顶部向下弯曲的点。因此,在这种情况下,我希望能够使它们更长。

有没有人有任何方向或例子来说明如何做到这一点?我看到的所有示例都只是缩放整个模型,而不仅仅是其中的一部分。

我在想我需要根据 obj 中的顶点创建一个样条线,然后操作创建的样条线,但我希望有更简单的选择,因为我不知道如何组合样条线模型

谢谢

编辑 我相信答案不在于样条线 - 实际上在于变形对象的目标属性。当我进一步了解时,我会在这里发帖,或者,如果有人知道我的意思,请指出我正确的方向。

编辑 2 按照 zero 的建议,我尝试将 SkinnedMeshes 与骨骼一起使用。我正试图用Vector4 对象填充skinIndicesskinWeights,但Typescript 抛出错误:

'Vector4' 类型的参数不能分配给number 类型的参数

我知道这是一个 Typescript 问题而不是 ThreeJS 问题,但我创建了一个具有相同代码的 jsfiddle,但其中 skinIndices 的数组类型为 Vector4. 我能想到的唯一原因是't 是因为我通过THREE.fromBufferGeometry 函数发送.obj 对象的BufferedGeometry

let geometry = new THREE.Geometry().fromBufferGeometry(frontHandle.children[0].geometry);

编辑 3

let geometry = new THREE.Geometry().fromBufferGeometry(frontHandle.children[0].geometry);

for ( let i = 0; i < geometry.vertices.length; i ++ ) 
  let vertex = geometry.vertices[ i ];
  let y = (vertex.y + sizing.halfHeight);

  let skinIndex = Math.floor( y / sizing.segmentHeight );
  let skinWeight = ( y % sizing.segmentHeight ) / sizing.segmentHeight;

  let vectorOne = new THREE.Vector4( skinIndex, skinIndex + 1, 0, 0);
  let vectorTwo = new THREE.Vector4( 1 - skinWeight, skinWeight, 0, 0);

  // Here's where the compliant is
  geometry.skinIndices.push(vectorOne);
  geometry.skinWeights.push(vectorTwo);
           

编辑 4

我解决了上面描述的问题,现在有了这个(蓝色手柄是蒙皮网格,里面有很多骨头,垂直的蓝绿色线是骨架助手):

我还添加了 DATGUI 帮助程序,如下所示:

但我似乎仍然无法恰到好处地缩放网格。屏幕截图中手柄的打结部分应始终保持相同大小。当我将它们按比例缩小时,我只需要它们下方的把手部分延伸,并希望当袋子变大时,打结的部分可以横向扩展。

【问题讨论】:

如何添加骨骼,对它们的手柄进行加权,然后将骨骼放大/缩小到您喜欢的大头模式? 我不明白你的意思 - 你能详细说明或提供一个例子的链接吗? Skinned Meshes 允许您对顶点进行分组,而不是单独变换顶点,而是变换骨骼。每个顶点都对骨骼进行加权,如果将多个变换应用于多个骨骼,则顶点会接收两个变换,这些变换都根据其相对于骨骼的权重进行缩放。链接中有演示。 谢谢 - 我现在去看看 @zero298 查看我的第二次编辑 【参考方案1】:

据我了解,您正在尝试使网格变形。网格变形主要有两种方式:

    Morph Targets Skeletal Animation

变形目标

变形目标允许您定义多个变换“目标”或关键帧,您可以在它们之间混合网格。这通常用于为网格设置动画。变形目标是冗长的。它们基本上是您的网格的复制品,但每个顶点都转换为您希望目标看起来的方式。它们允许对顶点进行非常细粒度的操作,因为您可以指定每个关键帧每个顶点的精确变换。但是,如上所述,它们很冗长。您必须使每个变形目标都以某种方式可用,以便您可以将目标混合在一起。

如果您有 2000 个顶点的多边形和 3 个变形目标,则必须保留 6000 个顶点的定义。

网格皮肤和骨骼

控制顶点变换的另一种方法是使用骨骼。骨骼允许您向一个顶点添加多个变换影响,并且以某种方式将顶点组合在一起,这样您就可以变换骨骼以获得所需的网格变形,而不必手动调整单个顶点。

您仍将定义变换关键帧,但您将为骨骼而不是单个顶点定义它们。这具有节省空间和实现转换重用的好处。您不必为网格中的每个顶点定义新的变换,而是定义将网格绑定到骨架的“皮肤”,并且骨架动画应该适当地动作。


在您的情况下,我不确定哪种技术更适合应用。我认为皮肤会有所帮助,因为您可以设置手柄中要转换为骨骼的所有顶点的权重,然后去掉结和袋子的权重。然后你可以应用你需要做的任何变换。

three.js 支持蒙皮网格。您可以在此处查看 API 和演示:Skinned Meshes。

【讨论】:

以上是关于在 ThreeJS 中缩放 OBJ 的一部分的主要内容,如果未能解决你的问题,请参考以下文章

在 ThreeJS 中缩放到对象

如何在加载到场景之前将 OBJ/FBX 转换为 GLTF(使用 Threejs)

在web端,three.js如何操作3d模型obj对象的子构件

ThreeJS 为 .obj 上传多个纹理

threejs加载geojson

three.js obj模型如何转成json 给threejs使用啊