0

I have an .obj file

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

And I need to create THREE.Mesh. I do

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);

I suppose I need to have follow data in arrays:

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 = // ... ?

I don't understand what do I need to store in indices array?

Mike_Device
  • 634
  • 2
  • 8
  • 25
  • Why you don't use the `OBJLoader`? You can find the js files in the examples folder. https://threejs.org/examples/#webgl_loader_obj – Brakebein Mar 28 '17 at 12:34
  • @Brakebein Yes, I saw it. But I want to understand how it works – Mike_Device Mar 28 '17 at 12:53
  • I just see, that the second face has vertex #1 twice. So, this face wouldn't really span a triangle. And face #1 want's to use a third `vt` which isn't defined. – Brakebein Mar 28 '17 at 14:59

2 Answers2

1

For this particular example:

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

which would create a degenerate triangle as index 1 appears twice for same (i.e. second) triangle.

There are several ways to define face elements in the .obj format:

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

As buffers use vertex indices for their attributes you would pick the first number (value1) out of your triplet value1/value2/value3 and form your indices array.

gaitat
  • 12,449
  • 4
  • 52
  • 76
  • Thanks. I've understood `indices = [v11, v12, v13, v21, v22, v23, ...]` And what to do with `vt` and `vn` values? – Mike_Device Mar 28 '17 at 13:36
  • in your obj model ... they better be the same as v. – gaitat Mar 28 '17 at 13:43
  • Hm... I don't understand. Do I need to add it to `geometry` using `addAttribute` or something else? – Mike_Device Mar 28 '17 at 13:56
  • there is no support for different indices for vertex attributes, all vertex attributes have to use the same index. so you would only use the v indices, ignoring the vn and vt indices. – gaitat Mar 28 '17 at 14:45
  • Okay. Thank you. And one more question. Why `vn` and `vt` need in in face parameters in .obj file if we don't use it – Mike_Device Mar 28 '17 at 14:54
  • the definition of the format has nothing to do with the implementation. obj is not specific to webgl. – gaitat Mar 28 '17 at 15:02
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/139281/discussion-between-mike-device-and-gaitat). – Mike_Device Mar 28 '17 at 16:35
1

Here is my example on how it should look like. The definition of the faces shows, that there are no vertices, which have the same texture AND normals indices. So, other as in normal Geometry, we cannot reuse any vertices, because in BufferGeometry a index defined in the indices array apply to vertices, uvs, and normals array. (I think, that's what @gaitat tried to explain.)

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

Edit: In the example above, the second vertex of the first face (2/2/2) is indexed with 1. So, we will get the second item set from vertices, uvs, and normals array: 4,5,6 0.5,0.5 0,1,0. The second vertex of the second face (2/2/3) is indexed with 4. So, we will get 5th item set from each array: 4,5,6 0.5,0.5 1,0,0. The vertex position and uvs of both are the same but the normals are different, so they cannot be reused. Because the index array stores only one index for all and not three for each vertex position, uv, and normal.

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

In this example, the second vertices of both faces are the same (2/2/2). In this case, the values can be reused. The arrays are shorter and the index of the vertex in the second face is 1, too.

Brakebein
  • 2,197
  • 1
  • 16
  • 21