Skip to content

Commit 69d1013

Browse files
committed
Spline: implement JmeCloneable and test
1 parent 75f0b73 commit 69d1013

File tree

2 files changed

+172
-42
lines changed

2 files changed

+172
-42
lines changed

jme3-core/src/main/java/com/jme3/math/Spline.java

+40-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
package com.jme3.math;
3333

3434
import com.jme3.export.*;
35+
import com.jme3.util.clone.Cloner;
36+
import com.jme3.util.clone.JmeCloneable;
3537
import java.io.IOException;
3638
import java.util.ArrayList;
3739
import java.util.Iterator;
@@ -41,7 +43,7 @@
4143
*
4244
* @author Nehon
4345
*/
44-
public class Spline implements Savable {
46+
public class Spline implements JmeCloneable, Savable {
4547

4648
public enum SplineType {
4749
Linear,
@@ -536,4 +538,41 @@ public void read(JmeImporter im) throws IOException {
536538
weights = in.readFloatArray("weights", null);
537539
basisFunctionDegree = in.readInt("basisFunctionDegree", 0);
538540
}
541+
542+
/**
543+
* Callback from {@link com.jme3.util.clone.Cloner} to convert this
544+
* shallow-cloned spline into a deep-cloned one, using the specified cloner
545+
* and original to resolve copied fields.
546+
*
547+
* @param cloner the cloner that's cloning this spline (not null)
548+
* @param original the object from which this spline was shallow-cloned
549+
* (not null, unaffected)
550+
*/
551+
@Override
552+
public void cloneFields(Cloner cloner, Object original) {
553+
this.controlPoints = cloner.clone(controlPoints);
554+
if (segmentsLength != null) {
555+
this.segmentsLength = new ArrayList<>(segmentsLength);
556+
}
557+
this.CRcontrolPoints = cloner.clone(CRcontrolPoints);
558+
if (knots != null) {
559+
this.knots = new ArrayList<>(knots);
560+
}
561+
this.weights = cloner.clone(weights);
562+
}
563+
564+
/**
565+
* Create a shallow clone for the JME cloner.
566+
*
567+
* @return a new object
568+
*/
569+
@Override
570+
public Spline jmeClone() {
571+
try {
572+
Spline clone = (Spline) clone();
573+
return clone;
574+
} catch (CloneNotSupportedException exception) {
575+
throw new RuntimeException(exception);
576+
}
577+
}
539578
}

jme3-core/src/test/java/com/jme3/math/SplineTest.java

+132-41
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.jme3.asset.AssetManager;
3535
import com.jme3.asset.DesktopAssetManager;
3636
import com.jme3.export.binary.BinaryExporter;
37+
import com.jme3.util.clone.Cloner;
3738
import java.util.ArrayList;
3839
import java.util.List;
3940
import org.junit.Assert;
@@ -52,70 +53,76 @@ public class SplineTest {
5253
// *************************************************************************
5354
// tests
5455

56+
/**
57+
* Verifies that spline cloning works correctly.
58+
*/
59+
@Test
60+
public void cloneSplines() {
61+
// Clone a Bézier spline:
62+
{
63+
Spline test1 = createBezier();
64+
Spline copy1 = Cloner.deepClone(test1);
65+
assertSplineEquals(test1, copy1);
66+
}
67+
68+
// Clone a NURB spline:
69+
{
70+
Spline test2 = createNurb();
71+
Spline copy2 = Cloner.deepClone(test2);
72+
assertSplineEquals(test2, copy2);
73+
}
74+
75+
// Clone a Catmull-Rom spline:
76+
{
77+
Spline test3 = createCatmullRom();
78+
Spline copy3 = Cloner.deepClone(test3);
79+
assertSplineEquals(test3, copy3);
80+
}
81+
82+
// Clone a linear spline:
83+
{
84+
Spline test4 = createLinear();
85+
Spline copy4 = Cloner.deepClone(test4);
86+
assertSplineEquals(test4, copy4);
87+
}
88+
89+
// Clone a default spline:
90+
{
91+
Spline test5 = new Spline();
92+
Spline copy5 = Cloner.deepClone(test5);
93+
assertSplineEquals(test5, copy5);
94+
}
95+
}
96+
5597
/**
5698
* Verifies that spline serialization/deserialization works correctly.
5799
*/
58100
@Test
59101
public void saveAndLoadSplines() {
60102
// Serialize and deserialize a Bezier spline:
61103
{
62-
Vector3f[] controlPoints1 = {
63-
new Vector3f(0f, 1f, 0f), new Vector3f(1f, 2f, 1f),
64-
new Vector3f(1.5f, 1.5f, 1.5f), new Vector3f(2f, 0f, 1f)
65-
};
66-
67-
Spline test1 = new Spline(
68-
Spline.SplineType.Bezier, controlPoints1, 0.1f, true);
104+
Spline test1 = createBezier();
69105
Spline copy1 = BinaryExporter.saveAndLoad(assetManager, test1);
70106
assertSplineEquals(test1, copy1);
71107
}
72108

73109
// Serialize and deserialize a NURB spline:
74110
{
75-
List<Vector4f> controlPoints2 = new ArrayList<>(5);
76-
controlPoints2.add(new Vector4f(0f, 1f, 2f, 3f));
77-
controlPoints2.add(new Vector4f(3f, 1f, 4f, 0f));
78-
controlPoints2.add(new Vector4f(2f, 5f, 3f, 0f));
79-
controlPoints2.add(new Vector4f(3f, 2f, 3f, 1f));
80-
controlPoints2.add(new Vector4f(0.5f, 1f, 0.6f, 5f));
81-
List<Float> nurbKnots = new ArrayList<>(6);
82-
nurbKnots.add(0.2f);
83-
nurbKnots.add(0.3f);
84-
nurbKnots.add(0.4f);
85-
nurbKnots.add(0.43f);
86-
nurbKnots.add(0.51f);
87-
nurbKnots.add(0.52f);
88-
89-
Spline test2 = new Spline(controlPoints2, nurbKnots);
111+
Spline test2 = createNurb();
90112
Spline copy2 = BinaryExporter.saveAndLoad(assetManager, test2);
91113
assertSplineEquals(test2, copy2);
92114
}
93115

94116
// Serialize and deserialize a Catmull-Rom spline:
95117
{
96-
List<Vector3f> controlPoints3 = new ArrayList<>(6);
97-
controlPoints3.add(new Vector3f(0f, 1f, 2f));
98-
controlPoints3.add(new Vector3f(3f, -1f, 4f));
99-
controlPoints3.add(new Vector3f(2f, 5f, 3f));
100-
controlPoints3.add(new Vector3f(3f, -2f, 3f));
101-
controlPoints3.add(new Vector3f(0.5f, 1f, 0.6f));
102-
controlPoints3.add(new Vector3f(-0.5f, 4f, 0.2f));
103-
104-
Spline test3 = new Spline(
105-
Spline.SplineType.CatmullRom, controlPoints3, 0.01f, false);
118+
Spline test3 = createCatmullRom();
106119
Spline copy3 = BinaryExporter.saveAndLoad(assetManager, test3);
107120
assertSplineEquals(test3, copy3);
108121
}
109122

110123
// Serialize and deserialize a linear spline:
111124
{
112-
List<Vector3f> controlPoints4 = new ArrayList<>(3);
113-
controlPoints4.add(new Vector3f(3f, -1f, 4f));
114-
controlPoints4.add(new Vector3f(2f, 0f, 3f));
115-
controlPoints4.add(new Vector3f(3f, -2f, 3f));
116-
117-
Spline test4 = new Spline(
118-
Spline.SplineType.Linear, controlPoints4, 0f, true);
125+
Spline test4 = createLinear();
119126
Spline copy4 = BinaryExporter.saveAndLoad(assetManager, test4);
120127
assertSplineEquals(test4, copy4);
121128
}
@@ -131,14 +138,22 @@ public void saveAndLoadSplines() {
131138
// private helper methods
132139

133140
/**
134-
* Verify that the specified lists are equivalent.
141+
* Verifies that the specified lists are equivalent but distinct.
135142
*
136143
* @param s1 the first list to compare (may be null, unaffected)
137144
* @param s2 the 2nd list to compare (may be null, unaffected)
138145
*/
139146
private static void assertListEquals(List<?> a1, List<?> a2) {
140-
if (a1 != a2) {
147+
if (a1 == null || a2 == null) {
148+
// If either list is null, verify that both are null:
149+
Assert.assertNull(a1);
150+
Assert.assertNull(a2);
151+
152+
} else {
153+
// Verify that the lists are distinct and and of equal length:
154+
Assert.assertTrue(a1 != a2);
141155
Assert.assertEquals(a1.size(), a2.size());
156+
142157
for (int i = 0; i < a1.size(); ++i) {
143158
Assert.assertEquals(a1.get(i), a2.get(i));
144159
}
@@ -172,4 +187,80 @@ private static void assertSplineEquals(Spline s1, Spline s2) {
172187
s1.getTotalLength(), s2.getTotalLength(), 0f);
173188
Assert.assertArrayEquals(s1.getWeights(), s2.getWeights(), 0f);
174189
}
190+
191+
/**
192+
* Generates a simple cyclic Bézier spline for testing.
193+
*
194+
* @return a new Spline
195+
*/
196+
private static Spline createBezier() {
197+
Vector3f[] controlPoints1 = {
198+
new Vector3f(0f, 1f, 0f), new Vector3f(1f, 2f, 1f),
199+
new Vector3f(1.5f, 1.5f, 1.5f), new Vector3f(2f, 0f, 1f)
200+
};
201+
202+
Spline result = new Spline(
203+
Spline.SplineType.Bezier, controlPoints1, 0.1f, true);
204+
return result;
205+
}
206+
207+
/**
208+
* Generates a simple acyclic Catmull-Rom spline for testing.
209+
*
210+
* @return a new Spline
211+
*/
212+
private static Spline createCatmullRom() {
213+
List<Vector3f> controlPoints3 = new ArrayList<>(6);
214+
controlPoints3.add(new Vector3f(0f, 1f, 2f));
215+
controlPoints3.add(new Vector3f(3f, -1f, 4f));
216+
controlPoints3.add(new Vector3f(2f, 5f, 3f));
217+
controlPoints3.add(new Vector3f(3f, -2f, 3f));
218+
controlPoints3.add(new Vector3f(0.5f, 1f, 0.6f));
219+
controlPoints3.add(new Vector3f(-0.5f, 4f, 0.2f));
220+
221+
Spline result = new Spline(
222+
Spline.SplineType.CatmullRom, controlPoints3, 0.01f, false);
223+
return result;
224+
}
225+
226+
/**
227+
* Generates a simple cyclic linear spline for testing.
228+
*
229+
* @return a new Spline
230+
*/
231+
private static Spline createLinear() {
232+
List<Vector3f> controlPoints4 = new ArrayList<>(3);
233+
controlPoints4.add(new Vector3f(3f, -1f, 4f));
234+
controlPoints4.add(new Vector3f(2f, 0f, 3f));
235+
controlPoints4.add(new Vector3f(3f, -2f, 3f));
236+
237+
Spline result = new Spline(
238+
Spline.SplineType.Linear, controlPoints4, 0f, true);
239+
return result;
240+
}
241+
242+
/**
243+
* Generates a simple NURB spline for testing.
244+
*
245+
* @return a new Spline
246+
*/
247+
private static Spline createNurb() {
248+
List<Vector4f> controlPoints2 = new ArrayList<>(5);
249+
controlPoints2.add(new Vector4f(0f, 1f, 2f, 3f));
250+
controlPoints2.add(new Vector4f(3f, 1f, 4f, 0f));
251+
controlPoints2.add(new Vector4f(2f, 5f, 3f, 0f));
252+
controlPoints2.add(new Vector4f(3f, 2f, 3f, 1f));
253+
controlPoints2.add(new Vector4f(0.5f, 1f, 0.6f, 5f));
254+
255+
List<Float> nurbKnots = new ArrayList<>(6);
256+
nurbKnots.add(0.2f);
257+
nurbKnots.add(0.3f);
258+
nurbKnots.add(0.4f);
259+
nurbKnots.add(0.43f);
260+
nurbKnots.add(0.51f);
261+
nurbKnots.add(0.52f);
262+
263+
Spline result = new Spline(controlPoints2, nurbKnots);
264+
return result;
265+
}
175266
}

0 commit comments

Comments
 (0)