aboutsummaryrefslogtreecommitdiff
path: root/engine/src/core/com/jme3/math/CurveAndSurfaceMath.java
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/core/com/jme3/math/CurveAndSurfaceMath.java')
-rw-r--r--engine/src/core/com/jme3/math/CurveAndSurfaceMath.java133
1 files changed, 133 insertions, 0 deletions
diff --git a/engine/src/core/com/jme3/math/CurveAndSurfaceMath.java b/engine/src/core/com/jme3/math/CurveAndSurfaceMath.java
new file mode 100644
index 0000000..079880f
--- /dev/null
+++ b/engine/src/core/com/jme3/math/CurveAndSurfaceMath.java
@@ -0,0 +1,133 @@
+package com.jme3.math;
+
+import com.jme3.math.Spline.SplineType;
+import java.util.List;
+
+/**
+ * This class offers methods to help with curves and surfaces calculations.
+ * @author Marcin Roguski (Kealthas)
+ */
+public class CurveAndSurfaceMath {
+ private static final float KNOTS_MINIMUM_DELTA = 0.0001f;
+
+ /**
+ * A private constructor is defined to avoid instatiation of this class.
+ */
+ private CurveAndSurfaceMath() {}
+
+ /**
+ * This method interpolates tha data for the nurbs curve.
+ * @param u
+ * the u value
+ * @param nurbSpline
+ * the nurbs spline definition
+ * @param store
+ * the resulting point in 3D space
+ */
+ public static void interpolateNurbs(float u, Spline nurbSpline, Vector3f store) {
+ if (nurbSpline.getType() != SplineType.Nurb) {
+ throw new IllegalArgumentException("Given spline is not of a NURB type!");
+ }
+ List<Vector3f> controlPoints = nurbSpline.getControlPoints();
+ float[] weights = nurbSpline.getWeights();
+ List<Float> knots = nurbSpline.getKnots();
+ int controlPointAmount = controlPoints.size();
+
+ store.set(Vector3f.ZERO);
+ float delimeter = 0;
+ for (int i = 0; i < controlPointAmount; ++i) {
+ float val = weights[i] * CurveAndSurfaceMath.computeBaseFunctionValue(i, nurbSpline.getBasisFunctionDegree(), u, knots);
+ store.addLocal(nurbSpline.getControlPoints().get(i)
+ .mult(val));
+ delimeter += val;
+ }
+ store.divideLocal(delimeter);
+ }
+
+ /**
+ * This method interpolates tha data for the nurbs surface.
+ *
+ * @param u
+ * the u value
+ * @param v
+ * the v value
+ * @param controlPoints
+ * the nurbs' control points
+ * @param knots
+ * the nurbs' knots
+ * @param basisUFunctionDegree
+ * the degree of basis U function
+ * @param basisVFunctionDegree
+ * the degree of basis V function
+ * @param store
+ * the resulting point in 3D space
+ */
+ public static void interpolate(float u, float v, List<List<Vector4f>> controlPoints, List<Float>[] knots,
+ int basisUFunctionDegree, int basisVFunctionDegree, Vector3f store) {
+ store.set(Vector3f.ZERO);
+ float delimeter = 0;
+ int vControlPointsAmount = controlPoints.size();
+ int uControlPointsAmount = controlPoints.get(0).size();
+ for (int i = 0; i < vControlPointsAmount; ++i) {
+ for (int j = 0; j < uControlPointsAmount; ++j) {
+ Vector4f controlPoint = controlPoints.get(i).get(j);
+ float val = controlPoint.w
+ * CurveAndSurfaceMath.computeBaseFunctionValue(i, basisVFunctionDegree, v, knots[1])
+ * CurveAndSurfaceMath.computeBaseFunctionValue(j, basisUFunctionDegree, u, knots[0]);
+ store.addLocal(controlPoint.x * val, controlPoint.y * val, controlPoint.z * val);
+ delimeter += val;
+ }
+ }
+ store.divideLocal(delimeter);
+ }
+
+ /**
+ * This method prepares the knots to be used. If the knots represent non-uniform B-splines (first and last knot values are being
+ * repeated) it leads to NaN results during calculations. This method adds a small number to each of such knots to avoid NaN's.
+ * @param knots
+ * the knots to be prepared to use
+ * @param basisFunctionDegree
+ * the degree of basis function
+ */
+ // TODO: improve this; constant delta may lead to errors if the difference between tha last repeated
+ // point and the following one is lower than it
+ public static void prepareNurbsKnots(List<Float> knots, int basisFunctionDegree) {
+ float delta = KNOTS_MINIMUM_DELTA;
+ float prevValue = knots.get(0).floatValue();
+ for(int i=1;i<knots.size();++i) {
+ float value = knots.get(i).floatValue();
+ if(value<=prevValue) {
+ value += delta;
+ knots.set(i, Float.valueOf(value));
+ delta += KNOTS_MINIMUM_DELTA;
+ } else {
+ delta = KNOTS_MINIMUM_DELTA;//reset the delta's value
+ }
+
+ prevValue = value;
+ }
+ }
+
+ /**
+ * This method computes the base function value for the NURB curve.
+ * @param i
+ * the knot index
+ * @param k
+ * the base function degree
+ * @param t
+ * the knot value
+ * @param knots
+ * the knots' values
+ * @return the base function value
+ */
+ private static float computeBaseFunctionValue(int i, int k, float t, List<Float> knots) {
+ if (k == 1) {
+ return knots.get(i) <= t && t < knots.get(i + 1) ? 1.0f : 0.0f;
+ } else {
+ return (t - knots.get(i)) / (knots.get(i + k - 1) - knots.get(i)) *
+ CurveAndSurfaceMath.computeBaseFunctionValue(i, k - 1, t, knots)
+ + (knots.get(i + k) - t) / (knots.get(i + k) - knots.get(i + 1)) *
+ CurveAndSurfaceMath.computeBaseFunctionValue(i + 1, k - 1, t, knots);
+ }
+ }
+}