1
Vote

newIndices and tuple comparisons in writeMesh

description

There is a section of code in writeMesh that does not appear to be working correctly:
 
<code>

If this index is already mapped scan our entries to see if

there is already a position/normal/textureCoordinate set

which matches.

for i in indexMap[index]:
if positions[i] == position and normals[i] == normal and textureCoordinates[i] == textureCoordinate:
        newIndices.append(index)
            continue
</code>
 
The position/normal/textureCoordinate vectors are being compared to tuples in the corresponding lists, but the type difference seems to be causing the condition to evaluate false everytime. Putting in a trace statement gives a clue as to what might be wrong:
 
trace("%s==%s" % (positions[i], position))
(1.0, 0.99999994039535522, -1.0)==1.000000, 1.000000, -1.000000
 
Altering this and comparing tuples to tuples fixes it (e.g., positions[i] == tuple(position), ...) , but then an array out of bounds error will occur when textureCoordinates[i] is evaluated if mesh.faceUV was false.
 
However, it does not seem that appending to newIndices in this location and continuing to the top of the inner for loop is going to produce the desired effect anyway, i.e. if the goal is to reuse an existing "new index" for the face and not map the same vertex again. Instead of appending a new position/normal/uv to the WPF verts in the code that comes afterward, it should skip the appending part if newIndex was already found in the map, so that duplicate verts are not mapped twice. Something like the following:
 
<code>
            newIndex = -1

            if not indexMap.has_key(index):
                indexMap[index] = []
            else:
                # If this index is already mapped scan our entries to see if
                # there is already a position/normal/textureCoordinate set
                # which matches.
                for i in indexMap[index]:
                    if positions[i] == tuple(position) and normals[i] == tuple(normal) and (mesh.faceUV == False or textureCoordinates[i] == tuple(textureCoordinate)):                            
                        newIndex = i
                        break;

            if newIndex >= 0:
                newIndices.append(newIndex)
            else:                    
                # We do not already have a matching position/normal/textureCoordinate
                # for this index so we create one and add it to our indexMap.
                indexMap[index].append(len(positions))
                newIndices.append(len(positions))
                positions.append(tuple(position))
                normals.append(tuple(normal))

                if mesh.faceUV:
                    textureCoordinates.append(tuple(textureCoordinate))
</code>

comments

TheRHogue wrote Jan 8, 2009 at 10:51 PM

After some investigation, Blender is creating duplicates for UV purposes. In the case of a Cube, 3 duplicates per vertex are needed to set a unique UV position.

In the case of solid color, duplicates can be removed, but normals would need to be averaged.

So, it appears the code should just be removed. Blender should be removing duplicates, not the exporter.

wrote Feb 14, 2013 at 7:42 PM