Fix glTF CUBICSPLINE animation sampling#2818
Conversation
There was a problem hiding this comment.
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.
| 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; | ||
| } |
There was a problem hiding this comment.
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;
}| 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; | ||
| } |
There was a problem hiding this comment.
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;
}|
Could a maintainer please approve/run the gated GitHub Actions workflow for this fork PR? The current failure is from |
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 tangentjME 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 samplingThis 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:
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 samplingAfter this fix:
ext ./gradlew :jme3-plugins:test --tests com.jme3.scene.plugins.gltf.GltfLoaderTest.testLoadCubicSplineScaleAnimation --no-daemonpasses.
Also ran the full plugin test suite:
ext ./gradlew :jme3-plugins:test --no-daemonResult:
ext BUILD SUCCESSFULFixes #2384