pioneerspacesim/pioneer — Issue #667: UVs exported from Blender 2.5 messed up
Author: Luomu
Created: 2011-10-16 12:15:37+00:00
State: open

Simple cube, unwrapped and textured, and smoothed. Then exported. The .obj written by Blender 2.59 is short enough to be pasted here:

```
# www.blender.org
o Cube
#Eight vertices
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
#Fourteen UVs
vt 0.500000 0.500001
vt 0.499999 0.750000
vt 0.249999 0.750000
vt 0.250000 0.500000
vt 0.500000 0.250000
vt 0.250000 0.250000
vt 0.250000 0.000000
vt 0.500000 0.000000
vt 0.750000 0.250000
vt 0.750000 0.000000
vt 0.499997 1.000000
vt 0.249998 0.999999
vt 0.000000 0.000000
vt 0.000000 0.250000
#Eight normals
vn 0.577349 -0.577349 -0.577349
vn 0.577349 -0.577349 0.577349
vn -0.577349 -0.577349 0.577349
vn -0.577349 -0.577349 -0.577349
vn 0.577349 0.577349 -0.577349
vn -0.577349 0.577349 -0.577349
vn -0.577349 0.577349 0.577349
vn 0.577349 0.577349 0.577349
#Six quads, four vertices earch
#(numbers are indices to previously defined v/vt/vn values)
f 1/1/1 2/2/2 3/3/3 4/4/4
f 5/5/5 8/6/6 7/7/7 6/8/8
f 1/9/1 5/5/5 6/8/8 2/10/2
f 2/2/2 6/11/8 7/12/7 3/3/3
f 3/13/3 7/7/7 8/6/6 4/14/4
f 5/5/5 1/1/1 4/4/4 8/6/6
```

How it looks like in game:

Normals are OK. Texture coordinates are not OK. If you don't export normals, the model is unsmoothed, but texture coords are fine.

After poking at LmrModel.cpp for a while, I believe this is the problem (comments original :))

```c++
for (int i=0; i, int>::iterator it = vtxmap.find(std::pair(vi[i], ni[i]));
if (it == vtxmap.end()) {
// insert the horrible thing
int vtxStart = s_curBuf->AllocVertices(1);
if (texcoords.empty()) {
// no UV coords
s_curBuf->SetVertex(vtxStart, vertices[vi[i]], normals[ni[i]]);
} else {
s_curBuf->SetVertex(vtxStart, vertices[vi[i]], normals[ni[i]], texcoords[ti[i]].x, texcoords[ti[i]].y);
}
vtxmap[std::pair(vi[i], ni[i])] = vtxStart;
realVtxIdx[i] = vtxStart;
} else {
realVtxIdx[i] = (*it).second;
}
}
```

This path is only taken if the .obj has normals. The logic here is that faces should reuse vertices (using vertex indices) instead storing four per face individually. You can only do that if two triangles sharing a vertex can use the same vertex normal and texture UVs. The above only does the sharing check for vertex and normal indices and not UVs.

At the same time I would like to point out that the Blender 2.5 export settings on our wiki are wrong - normals are not exported at all using those.