Skip to content

Fix glTF CUBICSPLINE animation sampling#2818

Open
ittaigolde wants to merge 2 commits into
jMonkeyEngine:masterfrom
ittaigolde:fix-gltf-cubic-spline-animation-sampling
Open

Fix glTF CUBICSPLINE animation sampling#2818
ittaigolde wants to merge 2 commits into
jMonkeyEngine:masterfrom
ittaigolde:fix-gltf-cubic-spline-animation-sampling

Conversation

@ittaigolde
Copy link
Copy Markdown
Contributor

Summary

Fixes glTF animation loading for CUBICSPLINE samplers by normalizing sampler output data before it is passed to TrackData.

glTF stores cubic spline animation output as triplets per keyframe:

ext in tangent, value, out tangent

jME currently warns that only linear animation interpolation is supported, but then continues to read the full cubic spline output array as if it contained one value per timestamp. For a sampler with 5 input times, this produces 15 output values, which later fails in TrackData.checkTimesConsistency() with:

ext AssetLoadException: Inconsistent animation sampling

This affects assets such as Khronos' InterpolationTest.gltf.

Fix

When a sampler uses CUBICSPLINE, this change keeps the actual keyframe value from each triplet and discards the in/out tangents before assigning animation data to TrackData.

This does not add full cubic spline interpolation support. It preserves the existing behavior of warning that only linear interpolation is supported, while allowing the asset to load using the actual keyframe values instead of crashing.

Covered paths:

  • translation
  • scale
  • rotation
  • morph weights

Test

Added a small regression glTF asset with a cubic spline scale animation.

Before this fix, the new test failed with:

ext AssetLoadException: Inconsistent animation sampling

After this fix:

ext ./gradlew :jme3-plugins:test --tests com.jme3.scene.plugins.gltf.GltfLoaderTest.testLoadCubicSplineScaleAnimation --no-daemon

passes.

Also ran the full plugin test suite:

ext ./gradlew :jme3-plugins:test --no-daemon

Result:

ext BUILD SUCCESSFUL

Fixes #2384

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for loading GLTF models with cubic spline interpolation in animations by extracting the keyframe values from the cubic spline data. It also includes a unit test with a sample GLTF file to verify the implementation. The reviewer suggested adding defensive null and bounds checks in the newly introduced helper methods getCubicSplineValues to prevent potential NullPointerException and division-by-zero errors.

Comment on lines +1512 to +1518
private <T> T[] getCubicSplineValues(T[] data) {
T[] values = Arrays.copyOf(data, data.length / 3);
for (int i = 0; i < values.length; i++) {
values[i] = data[i * 3 + 1];
}
return values;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To prevent potential NullPointerExceptions, we should add a defensive null check for the data array before accessing its length or copying it.

    private <T> T[] getCubicSplineValues(T[] data) {
        if (data == null) {
            return null;
        }
        T[] values = Arrays.copyOf(data, data.length / 3);
        for (int i = 0; i < values.length; i++) {
            values[i] = data[i * 3 + 1];
        }
        return values;
    }

Comment on lines +1520 to +1527
private float[] getCubicSplineValues(float[] data, int timesLength) {
int valuesPerTime = data.length / timesLength / 3;
float[] values = new float[timesLength * valuesPerTime];
for (int i = 0; i < timesLength; i++) {
System.arraycopy(data, (i * 3 + 1) * valuesPerTime, values, i * valuesPerTime, valuesPerTime);
}
return values;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To prevent potential NullPointerExceptions and ArithmeticException (division by zero if timesLength is 0), we should add defensive checks for data and timesLength.

    private float[] getCubicSplineValues(float[] data, int timesLength) {
        if (data == null) {
            return null;
        }
        if (timesLength <= 0) {
            return new float[0];
        }
        int valuesPerTime = data.length / timesLength / 3;
        float[] values = new float[timesLength * valuesPerTime];
        for (int i = 0; i < timesLength; i++) {
            System.arraycopy(data, (i * 3 + 1) * valuesPerTime, values, i * valuesPerTime, valuesPerTime);
        }
        return values;
    }

@ittaigolde
Copy link
Copy Markdown
Contributor Author

Could a maintainer please approve/run the gated GitHub Actions workflow for this fork PR? The current failure is from Screenshot Test PR Comment waiting for the Run Screenshot Tests check, but the paired Build jMonkeyEngine run is action_required and has zero jobs, so the screenshot check was never created.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

InterpolationTest.gltf fails to load, crashes with "Inconsistent animation sampling"

1 participant