Skip to content

Draco library fails to decode the data of the DracoMesh that was encoded by itself #3

@huliaknazarii

Description

@huliaknazarii

When decoding a Draco-encoded mesh that includes additional vertex attributes (e.g., normals, colors), decoding fails with:

java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 48819
    at dev.fileformat.drako.MeshAttributeCornerTable.vertex(MeshAttributeCornerTable.java:288)
    at dev.fileformat.drako.MeshEdgeBreakerDecoderImpl.assignPointsToCorners(MeshEdgeBreakerDecoderImpl.java:783)
    at dev.fileformat.drako.MeshEdgeBreakerDecoderImpl.decodeConnectivity(MeshEdgeBreakerDecoderImpl.java:692)
    ...

(Number of positions: 23960,
Number of normals: 23960,
Number of indices: 48819
…)

Encoding and decoding the same mesh with only positions and indices works correctly. Adding any additional attribute (e.g., normals or colors) consistently causes this failure.

Environment
Library: dev.fileformat:drako:1.4.1/1.4.2
JDK 17
Platform: Windows 10

Observed Behavior
If only positions + indices are encoded → decoding succeeds.
Adding any extra attribute (e.g., normals, colors) → decoding throws the exception.
Removing any 7 indices (reducing index count from 48,819 to 48,812) → decoding succeeds again.
The same behavior occurs across multiple library versions.

Debug Findings
The error occurs inside MeshEdgeBreakerDecoderImpl.decodeConnectivity(), specifically in assignPointsToCorners() around this loop:

for (int v = 0; v < this.cornerTable.getNumVertices(); ++v) {
    int c = this.cornerTable.leftMostCorner(v);
    ...
    for (int i = 0; i < this.attributeData.length; ++i) {
        if (this.attributeData[i].connectivityData.isCornerOnSeam(c)) {
            int vertId = this.attributeData[i].connectivityData.vertex(c);
            int actC = this.cornerTable.swingRight(c);

            for (boolean seamFound = false; actC != c; actC = this.cornerTable.swingRight(actC)) {
                if (this.attributeData[i].connectivityData.vertex(actC) != vertId) {
                    deduplicationFirstCorner = actC;
                    seamFound = true;
                    break;
                }
            }
            ...
        }
    }
}

In the failing case, actC becomes -1 when calling cornerTable.swingRight(actC).
This leads to accessing cornerToVertexMap[-1] → exception.
The fact that decoding succeeds when only positions are present suggests that the attribute connectivity (or corner-to-vertex mapping) becomes inconsistent across attributes.

Hypothesis
The bug appears to stem from a missing guard or incorrect assumption in assignPointsToCorners() — it assumes that swingRight() always returns a valid corner index (>= 0), but when geometry or attribute connectivity degenerates, it can return -1.

Expected Outcome
The decoder should be able to decode the DracoMesh object encoded by itself.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions