com.jme3.scene.plugins.blender.curves.BezierCurve Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jme3-blender Show documentation
Show all versions of jme3-blender Show documentation
jMonkeyEngine is a 3D game engine for adventurous Java developers
The newest version!
package com.jme3.scene.plugins.blender.curves;
import java.util.ArrayList;
import java.util.List;
import com.jme3.math.Vector3f;
import com.jme3.scene.plugins.blender.file.DynamicArray;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* A class that helps to calculate the bezier curves calues. It uses doubles for performing calculations to minimize
* floating point operations errors.
* @author Marcin Roguski (Kaelthas)
*/
public class BezierCurve {
private static final int IPO_CONSTANT = 0;
private static final int IPO_LINEAR = 1;
private static final int IPO_BEZIER = 2;
public static final int X_VALUE = 0;
public static final int Y_VALUE = 1;
public static final int Z_VALUE = 2;
/**
* The type of the curve. Describes the data it modifies.
* Used in ipos calculations.
*/
private int type;
/** The dimension of the curve. */
private int dimension;
/** A table of the bezier points. */
private double[][][] bezierPoints;
/** Array that stores a radius for each bezier triple. */
private double[] radiuses;
/** Interpolation types of the bezier triples. */
private int[] interpolations;
public BezierCurve(final int type, final List bezTriples, final int dimension) {
this(type, bezTriples, dimension, false);
}
@SuppressWarnings("unchecked")
public BezierCurve(final int type, final List bezTriples, final int dimension, boolean fixUpAxis) {
if (dimension != 2 && dimension != 3) {
throw new IllegalArgumentException("The dimension of the curve should be 2 or 3!");
}
this.type = type;
this.dimension = dimension;
// first index of the bezierPoints table has the length of triples amount
// the second index points to a table od three points of a bezier triple (handle, point, handle)
// the third index specifies the coordinates of the specific point in a bezier triple
bezierPoints = new double[bezTriples.size()][3][dimension];
radiuses = new double[bezTriples.size()];
interpolations = new int[bezTriples.size()];
int i = 0, j, k;
for (Structure bezTriple : bezTriples) {
DynamicArray vec = (DynamicArray) bezTriple.getFieldValue("vec");
for (j = 0; j < 3; ++j) {
for (k = 0; k < dimension; ++k) {
bezierPoints[i][j][k] = vec.get(j, k).doubleValue();
}
if (fixUpAxis && dimension == 3) {
double temp = bezierPoints[i][j][2];
bezierPoints[i][j][2] = -bezierPoints[i][j][1];
bezierPoints[i][j][1] = temp;
}
}
radiuses[i] = ((Number) bezTriple.getFieldValue("radius")).floatValue();
interpolations[i++] = ((Number) bezTriple.getFieldValue("ipo", IPO_BEZIER)).intValue();
}
}
/**
* This method evaluates the data for the specified frame. The Y value is returned.
* @param frame
* the frame for which the value is being calculated
* @param valuePart
* this param specifies wheather we should return the X, Y or Z part of the result value; it should have
* one of the following values: X_VALUE - the X factor of the result Y_VALUE - the Y factor of the result
* Z_VALUE - the Z factor of the result
* @return the value of the curve
*/
public double evaluate(int frame, int valuePart) {
for (int i = 0; i < bezierPoints.length - 1; ++i) {
if (frame >= bezierPoints[i][1][0] && frame <= bezierPoints[i + 1][1][0]) {
double t = (frame - bezierPoints[i][1][0]) / (bezierPoints[i + 1][1][0] - bezierPoints[i][1][0]);
switch (interpolations[i]) {
case IPO_BEZIER:
double oneMinusT = 1.0f - t;
double oneMinusT2 = oneMinusT * oneMinusT;
double t2 = t * t;
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;
case IPO_LINEAR:
return (1f - t) * bezierPoints[i][1][valuePart] + t * bezierPoints[i + 1][1][valuePart];
case IPO_CONSTANT:
return bezierPoints[i][1][valuePart];
default:
throw new IllegalStateException("Unknown interpolation type for curve: " + interpolations[i]);
}
}
}
if (frame < bezierPoints[0][1][0]) {
return bezierPoints[0][1][1];
} else { // frame>bezierPoints[bezierPoints.length-1][1][0]
return bezierPoints[bezierPoints.length - 1][1][1];
}
}
/**
* This method returns the frame where last bezier triple center point of the bezier curve is located.
* @return the frame number of the last defined bezier triple point for the curve
*/
public int getLastFrame() {
return (int) bezierPoints[bezierPoints.length - 1][1][0];
}
/**
* This method returns the type of the bezier curve. The type describes the parameter that this curve modifies
* (ie. LocationX or rotationW of the feature).
* @return the type of the bezier curve
*/
public int getType() {
return type;
}
/**
* The method returns the radius for the required bezier triple.
*
* @param bezierTripleIndex
* index of the bezier triple
* @return radius of the required bezier triple
*/
public double getRadius(int bezierTripleIndex) {
return radiuses[bezierTripleIndex];
}
/**
* This method returns a list of control points for this curve.
* @return a list of control points for this curve.
*/
public List getControlPoints() {
List controlPoints = new ArrayList(bezierPoints.length * 3);
for (int i = 0; i < bezierPoints.length; ++i) {
controlPoints.add(new Vector3f((float) bezierPoints[i][0][0], (float) bezierPoints[i][0][1], (float) bezierPoints[i][0][2]));
controlPoints.add(new Vector3f((float) bezierPoints[i][1][0], (float) bezierPoints[i][1][1], (float) bezierPoints[i][1][2]));
controlPoints.add(new Vector3f((float) bezierPoints[i][2][0], (float) bezierPoints[i][2][1], (float) bezierPoints[i][2][2]));
}
return controlPoints;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("Bezier curve: ").append(type).append('\n');
for (int i = 0; i < bezierPoints.length; ++i) {
sb.append(this.toStringBezTriple(i)).append('\n');
}
return sb.toString();
}
/**
* This method converts the bezier triple of a specified index into text.
* @param tripleIndex
* index of the triple
* @return text representation of the triple
*/
private String toStringBezTriple(int tripleIndex) {
if (dimension == 2) {
return "[(" + bezierPoints[tripleIndex][0][0] + ", " + bezierPoints[tripleIndex][0][1] + ") (" + bezierPoints[tripleIndex][1][0] + ", " + bezierPoints[tripleIndex][1][1] + ") (" + bezierPoints[tripleIndex][2][0] + ", " + bezierPoints[tripleIndex][2][1] + ")]";
} else {
return "[(" + bezierPoints[tripleIndex][0][0] + ", " + bezierPoints[tripleIndex][0][1] + ", " + bezierPoints[tripleIndex][0][2] + ") (" + bezierPoints[tripleIndex][1][0] + ", " + bezierPoints[tripleIndex][1][1] + ", " + bezierPoints[tripleIndex][1][2] + ") (" + bezierPoints[tripleIndex][2][0] + ", " + bezierPoints[tripleIndex][2][1] + ", " + bezierPoints[tripleIndex][2][2] + ")]";
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy