【问题标题】:How to create mesh with Three.js如何使用 Three.js 创建网格
【发布时间】:2017-08-21 08:59:15
【问题描述】:

我有一个 .obj 文件

v 1 2 3
v 4 5 6
v 7 8 9

vt 0 1
vt 1 0

vn 0 0 1
vn 0 1 0
vn 0 0 1

f 1/1/1 2/2/2 3/3/3
f 1/1/2 2/2/3 1/2/3

我需要创建 THREE.Mesh。我愿意

var geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3));
geometry.addAttribute('normal', new THREE.BufferAttribute(normals, 3));
geometry.addAttribute('uv', new THREE.BufferAttribute(uvs, 2));
geometry.setIndex(new THREE.BufferAttribute(indices, 1));

var mesh = new THREE.Mesh(geometry, material);

我想我需要在数组中包含以下数据:

var vertices = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var normals = [0, 0, 1, 0, 1, 0, 0, 0, 1];
var uvs = [0, 1, 1, 0]
var indices = // ... ?

我不明白我需要在索引数组中存储什么?

【问题讨论】:

  • 为什么不使用OBJLoader?您可以在示例文件夹中找到 js 文件。 threejs.org/examples/#webgl_loader_obj
  • @Brakebein 是的,我看到了。但我想了解它是如何工作的
  • 我刚刚看到,第二个面有两次顶点#1。所以,这张脸不会真的跨越一个三角形。面对 #1 想要使用第三个未定义的 vt

标签: javascript three.js mesh .obj buffer-geometry


【解决方案1】:

对于这个特定的例子:

var indices = [1, 2, 3, 1, 2, 1];

这将创建一个退化的三角形,因为索引 1 出现两次相同(即第二个)三角形。

有几种方法可以定义.obj格式的人脸元素:

f v1 v2 v3 ....                        // vertex indices
f v1/vt1 v2/vt2 v3/vt3 ...             // adding texture indices
f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3 ... // adding normal indices
f v1//vn1 v2//vn2 v3//vn3 ...          // eliminating texture indices

由于缓冲区使用顶点索引作为它们的属性,您可以从三元组 value1/value2/value3 中选择第一个数字 (value1) 并形成您的 indices 数组。

【讨论】:

  • 谢谢。我已经了解indices = [v11, v12, v13, v21, v22, v23, ...] 以及如何处理vtvn 值?
  • 在你的 obj 模型中......它们最好与 v 相同。
  • 嗯...我不明白。我是否需要使用addAttribute 或其他方式将其添加到geometry
  • 不支持顶点属性的不同索引,所有顶点属性必须使用相同的索引。所以你只会使用 v 索引,忽略 vn 和 vt 索引。
  • 好的。谢谢你。还有一个问题。为什么vnvt不用在.obj文件中需要in face参数
【解决方案2】:

这是我的示例,说明它的外观。面的定义表明,没有顶点具有相同的纹理和法线索引。因此,与普通Geometry 不同,我们不能重用任何顶点,因为在BufferGeometry 中,indices 数组中定义的索引适用于顶点、uvs 和法线数组。 (我认为,这就是@gaitat 试图解释的。)

v 1 2 3
v 4 5 6
v 7 8 9

vt 0 1
vt 0.5 0.5
vt 1 0

vn 0 0 1
vn 0 1 0
vn 1 0 0

f 1/1/1 2/2/2 3/3/3
f 1/1/2 2/2/3 1/2/3    

var vertices = [1,2,3,  4,5,6,    7,8,9,  1,2,3,  4,5,6,    1,2,1];   // itemSize: 3
var uvs =      [0,1,    0.5,0.5,  1,0,    0,1,    0.5,0.5,  0.5,0.5]; // itemSize: 2
var normals =  [0,0,1,  0,1,0,    1,0,0,  0,1,0,  1,0,0,    1,0,0];   // itemSize: 3

var indices = [0,1,2, 3,4,5]; // itemSize: 1

编辑: 在上面的示例中,第一个面 (2/2/2) 的第二个顶点使用 1 进行索引。因此,我们将从顶点、uvs 和法线数组中获取第二个项目集:4,5,60.5,0.50,1,0。第二个面 (2/2/3) 的第二个顶点使用4 进行索引。因此,我们将从每个数组中获得第 5 个项集:4,5,60.5,0.51,0,0。两者的顶点位置和uvs是一样的,但是法线不同,所以不能复用。因为索引数组只存储了所有的索引,而不是每个顶点位置、uv、法线的三个索引。

f 1/1/1 2/2/2 3/3/3
f 1/1/2 2/2/2 1/2/3    

var vertices = [1,2,3,  4,5,6,    7,8,9,  1,2,3,  1,2,1];   // itemSize: 3
var uvs =      [0,1,    0.5,0.5,  1,0,    0,1,    0.5,0.5]; // itemSize: 2
var normals =  [0,0,1,  0,1,0,    1,0,0,  0,1,0,  1,0,0];   // itemSize: 3

var indices = [0,1,2, 3,1,5]; // itemSize: 1

在本例中,两个面的第二个顶点相同(2/2/2)。在这种情况下,可以重复使用这些值。数组更短,第二个面的顶点索引也是1

【讨论】:

  • 你能解释一下,你是怎么得到这个数组的,更准确地说是它们的后半部分?
  • 我编辑了我的帖子。我希望,现在更清楚了。
猜你喜欢
  • 2016-12-18
  • 2012-03-04
  • 1970-01-01
  • 2013-10-11
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 2021-08-18
  • 1970-01-01
相关资源
最近更新 更多