• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.jme3.scene.plugins.blender.curves;
2 
3 import com.jme3.math.Vector3f;
4 import com.jme3.scene.plugins.blender.file.DynamicArray;
5 import com.jme3.scene.plugins.blender.file.Structure;
6 import java.util.ArrayList;
7 import java.util.List;
8 
9 /**
10  * A class that helps to calculate the bezier curves calues. It uses doubles for performing calculations to minimize
11  * floating point operations errors.
12  * @author Marcin Roguski
13  */
14 public class BezierCurve {
15 
16     public static final int X_VALUE = 0;
17     public static final int Y_VALUE = 1;
18     public static final int Z_VALUE = 2;
19     /**
20      * The type of the curve. Describes the data it modifies.
21      * Used in ipos calculations.
22      */
23     private int type;
24     /** The dimension of the curve. */
25     private int dimension;
26     /** A table of the bezier points. */
27     private float[][][] bezierPoints;
28 
29     @SuppressWarnings("unchecked")
BezierCurve(final int type, final List<Structure> bezTriples, final int dimension)30     public BezierCurve(final int type, final List<Structure> bezTriples, final int dimension) {
31         if (dimension != 2 && dimension != 3) {
32             throw new IllegalArgumentException("The dimension of the curve should be 2 or 3!");
33         }
34         this.type = type;
35         this.dimension = dimension;
36         //first index of the bezierPoints table has the length of triples amount
37         //the second index points to a table od three points of a bezier triple (handle, point, handle)
38         //the third index specifies the coordinates of the specific point in a bezier triple
39         bezierPoints = new float[bezTriples.size()][3][dimension];
40         int i = 0, j, k;
41         for (Structure bezTriple : bezTriples) {
42             DynamicArray<Number> vec = (DynamicArray<Number>) bezTriple.getFieldValue("vec");
43             for (j = 0; j < 3; ++j) {
44                 for (k = 0; k < dimension; ++k) {
45                     bezierPoints[i][j][k] = vec.get(j, k).floatValue();
46                 }
47             }
48             ++i;
49         }
50     }
51 
52     /**
53      * This method evaluates the data for the specified frame. The Y value is returned.
54      * @param frame
55      *        the frame for which the value is being calculated
56      * @param valuePart
57      *        this param specifies wheather we should return the X, Y or Z part of the result value; it should have
58      *        one of the following values: X_VALUE - the X factor of the result Y_VALUE - the Y factor of the result
59      *        Z_VALUE - the Z factor of the result
60      * @return the value of the curve
61      */
evaluate(int frame, int valuePart)62     public float evaluate(int frame, int valuePart) {
63         for (int i = 0; i < bezierPoints.length - 1; ++i) {
64             if (frame >= bezierPoints[i][1][0] && frame <= bezierPoints[i + 1][1][0]) {
65                 float t = (frame - bezierPoints[i][1][0]) / (bezierPoints[i + 1][1][0] - bezierPoints[i][1][0]);
66                 float oneMinusT = 1.0f - t;
67                 float oneMinusT2 = oneMinusT * oneMinusT;
68                 float t2 = t * t;
69                 return bezierPoints[i][1][valuePart] * oneMinusT2 * oneMinusT + 3.0f * bezierPoints[i][2][valuePart] * t * oneMinusT2 + 3.0f * bezierPoints[i + 1][0][valuePart] * t2 * oneMinusT + bezierPoints[i + 1][1][valuePart] * t2 * t;
70             }
71         }
72         if (frame < bezierPoints[0][1][0]) {
73             return bezierPoints[0][1][1];
74         } else { //frame>bezierPoints[bezierPoints.length-1][1][0]
75             return bezierPoints[bezierPoints.length - 1][1][1];
76         }
77     }
78 
79     /**
80      * This method returns the frame where last bezier triple center point of the bezier curve is located.
81      * @return the frame number of the last defined bezier triple point for the curve
82      */
getLastFrame()83     public int getLastFrame() {
84         return (int) bezierPoints[bezierPoints.length - 1][1][0];
85     }
86 
87     /**
88      * This method returns the type of the bezier curve. The type describes the parameter that this curve modifies
89      * (ie. LocationX or rotationW of the feature).
90      * @return the type of the bezier curve
91      */
getType()92     public int getType() {
93         return type;
94     }
95 
96     /**
97      * This method returns a list of control points for this curve.
98      * @return a list of control points for this curve.
99      */
getControlPoints()100     public List<Vector3f> getControlPoints() {
101         List<Vector3f> controlPoints = new ArrayList<Vector3f>(bezierPoints.length * 3);
102         for (int i = 0; i < bezierPoints.length; ++i) {
103             controlPoints.add(new Vector3f(bezierPoints[i][0][0], bezierPoints[i][0][1], bezierPoints[i][0][2]));
104             controlPoints.add(new Vector3f(bezierPoints[i][1][0], bezierPoints[i][1][1], bezierPoints[i][1][2]));
105             controlPoints.add(new Vector3f(bezierPoints[i][2][0], bezierPoints[i][2][1], bezierPoints[i][2][2]));
106         }
107         return controlPoints;
108     }
109 
110     @Override
toString()111     public String toString() {
112         StringBuilder sb = new StringBuilder("Bezier curve: ").append(type).append('\n');
113         for (int i = 0; i < bezierPoints.length; ++i) {
114             sb.append(this.toStringBezTriple(i)).append('\n');
115         }
116         return sb.toString();
117     }
118 
119     /**
120      * This method converts the bezier triple of a specified index into text.
121      * @param tripleIndex
122      *        index of the triple
123      * @return text representation of the triple
124      */
toStringBezTriple(int tripleIndex)125     private String toStringBezTriple(int tripleIndex) {
126         if (this.dimension == 2) {
127             return "[(" + bezierPoints[tripleIndex][0][0] + ", " + bezierPoints[tripleIndex][0][1] + ") ("
128                     + bezierPoints[tripleIndex][1][0] + ", " + bezierPoints[tripleIndex][1][1] + ") ("
129                     + bezierPoints[tripleIndex][2][0] + ", " + bezierPoints[tripleIndex][2][1] + ")]";
130         } else {
131             return "[(" + bezierPoints[tripleIndex][0][0] + ", " + bezierPoints[tripleIndex][0][1] + ", " + bezierPoints[tripleIndex][0][2] + ") ("
132                     + bezierPoints[tripleIndex][1][0] + ", " + bezierPoints[tripleIndex][1][1] + ", " + bezierPoints[tripleIndex][1][2] + ") ("
133                     + bezierPoints[tripleIndex][2][0] + ", " + bezierPoints[tripleIndex][2][1] + ", " + bezierPoints[tripleIndex][2][2] + ")]";
134         }
135     }
136 }