Răsfoiți Sursa

solve issue #1806 (global FrameInterpolator violates threading model) (#1943)

* solve issue #1806 (global FrameInterpolator violates threading model)

* FrameInterpolator:  deprecate the global instance
Stephen Gold 2 ani în urmă
părinte
comite
387aba89f0

+ 9 - 3
jme3-core/src/main/java/com/jme3/anim/MorphTrack.java

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2021 jMonkeyEngine
+ * Copyright (c) 2009-2023 jMonkeyEngine
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -52,7 +52,11 @@ public class MorphTrack implements AnimTrack<float[]> {
      * Weights and times for track.
      */
     private float[] weights;
-    private FrameInterpolator interpolator = FrameInterpolator.DEFAULT;
+    /**
+     * The interpolator to use, or null to always use the default interpolator
+     * of the current thread.
+     */
+    private FrameInterpolator interpolator = null;
     private float[] times;
     private int nbMorphTargets;
 
@@ -219,7 +223,9 @@ public class MorphTrack implements AnimTrack<float[]> {
                     / (times[endFrame] - times[startFrame]);
         }
 
-        interpolator.interpolateWeights(blend, startFrame, weights, nbMorphTargets, store);
+        FrameInterpolator fi = (interpolator == null)
+                ? FrameInterpolator.getThreadDefault() : interpolator;
+        fi.interpolateWeights(blend, startFrame, weights, nbMorphTargets, store);
     }
 
     /**

+ 10 - 3
jme3-core/src/main/java/com/jme3/anim/TransformTrack.java

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2021 jMonkeyEngine
+ * Copyright (c) 2009-2023 jMonkeyEngine
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -50,7 +50,11 @@ import java.io.IOException;
 public class TransformTrack implements AnimTrack<Transform> {
 
     private double length;
-    private FrameInterpolator interpolator = FrameInterpolator.DEFAULT;
+    /**
+     * The interpolator to use, or null to always use the default interpolator
+     * of the current thread.
+     */
+    private FrameInterpolator interpolator = null;
     private HasLocalTransform target;
 
     /**
@@ -281,7 +285,10 @@ public class TransformTrack implements AnimTrack<Transform> {
                     / (times[endFrame] - times[startFrame]);
         }
 
-        Transform interpolated = interpolator.interpolate(blend, startFrame, translations, rotations, scales, times);
+        FrameInterpolator fi = (interpolator == null)
+                ? FrameInterpolator.getThreadDefault() : interpolator;
+        Transform interpolated = fi.interpolate(
+                blend, startFrame, translations, rotations, scales, times);
 
         if (translations != null) {
             transform.setTranslation(interpolated.getTranslation());

+ 23 - 1
jme3-core/src/main/java/com/jme3/anim/interpolator/FrameInterpolator.java

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2021 jMonkeyEngine
+ * Copyright (c) 2009-2023 jMonkeyEngine
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,19 @@ import com.jme3.math.*;
  * Created by nehon on 15/04/17.
  */
 public class FrameInterpolator {
+    /**
+     * A global default instance of this class, for compatibility with JME v3.5.
+     * Due to issue #1806, use of this instance is discouraged.
+     *
+     * @deprecated use {@link #getThreadDefault()}
+     */
+    @Deprecated
     public static final FrameInterpolator DEFAULT = new FrameInterpolator();
+    /**
+     * The per-thread default instances of this class.
+     */
+    private static final ThreadLocal<FrameInterpolator> THREAD_DEFAULT
+            = ThreadLocal.withInitial(() -> new FrameInterpolator());
 
     private AnimInterpolator<Float> timeInterpolator;
     private AnimInterpolator<Vector3f> translationInterpolator = AnimInterpolators.LinearVec3f;
@@ -52,6 +64,16 @@ public class FrameInterpolator {
 
     final private Transform transforms = new Transform();
 
+    /**
+     * Obtain the default interpolator for the current thread.
+     *
+     * @return the pre-existing instance (not null)
+     */
+    public static FrameInterpolator getThreadDefault() {
+        FrameInterpolator result = THREAD_DEFAULT.get();
+        return result;
+    }
+
     public Transform interpolate(float t, int currentIndex, CompactVector3Array translations,
             CompactQuaternionArray rotations, CompactVector3Array scales, float[] times) {
         timesReader.setData(times);