159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * To change this template, choose Tools | Templates 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * and open the template in the editor. 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.math; 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.*; 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException; 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.ArrayList; 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.Iterator; 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.List; 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Nehon 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class Spline implements Savable { 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public enum SplineType { 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Linear, 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CatmullRom, 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Bezier, 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Nurb 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private List<Vector3f> controlPoints = new ArrayList<Vector3f>(); 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private List<Float> knots; //knots of NURBS spline 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private float[] weights; //weights of NURBS spline 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int basisFunctionDegree; //degree of NURBS spline basis function (computed automatically) 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private boolean cycle; 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private List<Float> segmentsLength; 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private float totalLength; 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private List<Vector3f> CRcontrolPoints; 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private float curveTension = 0.5f; 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private SplineType type = SplineType.CatmullRom; 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Spline() { 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Create a spline 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param splineType the type of the spline @see {SplineType} 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param controlPoints an array of vector to use as control points of the spline 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * If the type of the curve is Bezier curve the control points should be provided 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * in the appropriate way. Each point 'p' describing control position in the scene 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * should be surrounded by two handler points. This applies to every point except 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * for the border points of the curve, who should have only one handle point. 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * The pattern should be as follows: 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * P0 - H0 : H1 - P1 - H1 : ... : Hn - Pn 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * n is the amount of 'P' - points. 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param curveTension the tension of the spline 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param cycle true if the spline cycle. 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Spline(SplineType splineType, Vector3f[] controlPoints, float curveTension, boolean cycle) { 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if(splineType==SplineType.Nurb) { 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("To create NURBS spline use: 'public Spline(Vector3f[] controlPoints, float[] weights, float[] nurbKnots)' constructor!"); 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < controlPoints.length; i++) { 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f vector3f = controlPoints[i]; 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.controlPoints.add(vector3f); 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta type = splineType; 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.curveTension = curveTension; 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.cycle = cycle; 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.computeTotalLentgh(); 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Create a spline 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param splineType the type of the spline @see {SplineType} 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param controlPoints a list of vector to use as control points of the spline 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * If the type of the curve is Bezier curve the control points should be provided 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * in the appropriate way. Each point 'p' describing control position in the scene 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * should be surrounded by two handler points. This applies to every point except 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * for the border points of the curve, who should have only one handle point. 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * The pattern should be as follows: 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * P0 - H0 : H1 - P1 - H1 : ... : Hn - Pn 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * n is the amount of 'P' - points. 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param curveTension the tension of the spline 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param cycle true if the spline cycle. 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Spline(SplineType splineType, List<Vector3f> controlPoints, float curveTension, boolean cycle) { 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if(splineType==SplineType.Nurb) { 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("To create NURBS spline use: 'public Spline(Vector3f[] controlPoints, float[] weights, float[] nurbKnots)' constructor!"); 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta type = splineType; 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.controlPoints.addAll(controlPoints); 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.curveTension = curveTension; 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.cycle = cycle; 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.computeTotalLentgh(); 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Create a NURBS spline. A spline type is automatically set to SplineType.Nurb. 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * The cycle is set to <b>false</b> by default. 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param controlPoints a list of vector to use as control points of the spline 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param nurbKnots the nurb's spline knots 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Spline(List<Vector4f> controlPoints, List<Float> nurbKnots) { 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //input data control 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for(int i=0;i<nurbKnots.size()-1;++i) { 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if(nurbKnots.get(i)>nurbKnots.get(i+1)) { 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("The knots values cannot decrease!"); 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //storing the data 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta type = SplineType.Nurb; 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.weights = new float[controlPoints.size()]; 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.knots = nurbKnots; 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.basisFunctionDegree = nurbKnots.size() - weights.length; 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for(int i=0;i<controlPoints.size();++i) { 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector4f controlPoint = controlPoints.get(i); 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.controlPoints.add(new Vector3f(controlPoint.x, controlPoint.y, controlPoint.z)); 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.weights[i] = controlPoint.w; 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CurveAndSurfaceMath.prepareNurbsKnots(knots, basisFunctionDegree); 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.computeTotalLentgh(); 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void initCatmullRomWayPoints(List<Vector3f> list) { 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (CRcontrolPoints == null) { 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CRcontrolPoints = new ArrayList<Vector3f>(); 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CRcontrolPoints.clear(); 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int nb = list.size() - 1; 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (cycle) { 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CRcontrolPoints.add(list.get(list.size() - 2)); 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CRcontrolPoints.add(list.get(0).subtract(list.get(1).subtract(list.get(0)))); 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Iterator<Vector3f> it = list.iterator(); it.hasNext();) { 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f vector3f = it.next(); 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CRcontrolPoints.add(vector3f); 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (cycle) { 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CRcontrolPoints.add(list.get(1)); 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CRcontrolPoints.add(list.get(nb).add(list.get(nb).subtract(list.get(nb - 1)))); 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Adds a controlPoint to the spline 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param controlPoint a position in world space 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void addControlPoint(Vector3f controlPoint) { 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (controlPoints.size() > 2 && this.cycle) { 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta controlPoints.remove(controlPoints.size() - 1); 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta controlPoints.add(controlPoint); 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (controlPoints.size() >= 2 && this.cycle) { 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta controlPoints.add(controlPoints.get(0)); 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (controlPoints.size() > 1) { 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.computeTotalLentgh(); 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * remove the controlPoint from the spline 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param controlPoint the controlPoint to remove 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void removeControlPoint(Vector3f controlPoint) { 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta controlPoints.remove(controlPoint); 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (controlPoints.size() > 1) { 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.computeTotalLentgh(); 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void clearControlPoints(){ 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta controlPoints.clear(); 17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta totalLength = 0; 18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method computes the total length of the curve. 18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void computeTotalLentgh() { 18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta totalLength = 0; 18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float l = 0; 18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (segmentsLength == null) { 18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta segmentsLength = new ArrayList<Float>(); 19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta segmentsLength.clear(); 19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (type == SplineType.Linear) { 19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (controlPoints.size() > 1) { 19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < controlPoints.size() - 1; i++) { 19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta l = controlPoints.get(i + 1).subtract(controlPoints.get(i)).length(); 19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta segmentsLength.add(l); 19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta totalLength += l; 19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if(type == SplineType.Bezier) { 20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.computeBezierLength(); 20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if(type == SplineType.Nurb) { 20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.computeNurbLength(); 20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.initCatmullRomWayPoints(controlPoints); 20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.computeCatmulLength(); 20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method computes the Catmull Rom curve length. 21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void computeCatmulLength() { 21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float l = 0; 21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (controlPoints.size() > 1) { 21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < controlPoints.size() - 1; i++) { 21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta l = FastMath.getCatmullRomP1toP2Length(CRcontrolPoints.get(i), 21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CRcontrolPoints.get(i + 1), CRcontrolPoints.get(i + 2), CRcontrolPoints.get(i + 3), 0, 1, curveTension); 22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta segmentsLength.add(l); 22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta totalLength += l; 22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method calculates the Bezier curve length. 22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void computeBezierLength() { 23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float l = 0; 23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (controlPoints.size() > 1) { 23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < controlPoints.size() - 1; i+=3) { 23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta l = FastMath.getBezierP1toP2Length(controlPoints.get(i), 23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta controlPoints.get(i + 1), controlPoints.get(i + 2), controlPoints.get(i + 3)); 23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta segmentsLength.add(l); 23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta totalLength += l; 23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method calculates the NURB curve length. 24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void computeNurbLength() { 24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //TODO: implement 24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Iterpolate a position on the spline 25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param value a value from 0 to 1 that represent the postion between the curent control point and the next one 25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param currentControlPoint the current control point 25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param store a vector to store the result (use null to create a new one that will be returned by the method) 25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the position 25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Vector3f interpolate(float value, int currentControlPoint, Vector3f store) { 25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (store == null) { 25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta store = new Vector3f(); 25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (type) { 26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case CatmullRom: 26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta FastMath.interpolateCatmullRom(value, curveTension, CRcontrolPoints.get(currentControlPoint), CRcontrolPoints.get(currentControlPoint + 1), CRcontrolPoints.get(currentControlPoint + 2), CRcontrolPoints.get(currentControlPoint + 3), store); 26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Linear: 26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta FastMath.interpolateLinear(value, controlPoints.get(currentControlPoint), controlPoints.get(currentControlPoint + 1), store); 26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Bezier: 26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta FastMath.interpolateBezier(value, controlPoints.get(currentControlPoint), controlPoints.get(currentControlPoint + 1), controlPoints.get(currentControlPoint + 2), controlPoints.get(currentControlPoint + 3), store); 26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Nurb: 27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CurveAndSurfaceMath.interpolateNurbs(value, this, store); 27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return store; 27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * returns the curve tension 28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public float getCurveTension() { 28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return curveTension; 28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * sets the curve tension 28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param curveTension the tension 28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setCurveTension(float curveTension) { 29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.curveTension = curveTension; 29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if(type==SplineType.CatmullRom) { 29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.computeTotalLentgh(); 29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * returns true if the spline cycle 29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean isCycle() { 30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return cycle; 30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * set to true to make the spline cycle 30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param cycle 30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setCycle(boolean cycle) { 30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if(type!=SplineType.Nurb) { 31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (controlPoints.size() >= 2) { 31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (this.cycle && !cycle) { 31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta controlPoints.remove(controlPoints.size() - 1); 31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!this.cycle && cycle) { 31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta controlPoints.add(controlPoints.get(0)); 31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.cycle = cycle; 31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.computeTotalLentgh(); 31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.cycle = cycle; 32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * return the total lenght of the spline 32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public float getTotalLength() { 32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return totalLength; 33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * return the type of the spline 33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public SplineType getType() { 33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return type; 33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Sets the type of the spline 34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param type 34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setType(SplineType type) { 34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.type = type; 34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.computeTotalLentgh(); 34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * returns this spline control points 35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public List<Vector3f> getControlPoints() { 35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return controlPoints; 35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * returns a list of float representing the segments lenght 35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public List<Float> getSegmentsLength() { 35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return segmentsLength; 36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //////////// NURBS getters ///////////////////// 36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method returns the minimum nurb curve knot value. Check the nurb type before calling this method. It the curve is not of a Nurb 36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * type - NPE will be thrown. 36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the minimum nurb curve knot value 36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public float getMinNurbKnot() { 37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return knots.get(basisFunctionDegree - 1); 37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method returns the maximum nurb curve knot value. Check the nurb type before calling this method. It the curve is not of a Nurb 37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * type - NPE will be thrown. 37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the maximum nurb curve knot value 37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public float getMaxNurbKnot() { 37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return knots.get(weights.length); 38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method returns NURBS' spline knots. 38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return NURBS' spline knots 38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public List<Float> getKnots() { 38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return knots; 38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method returns NURBS' spline weights. 39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return NURBS' spline weights 39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public float[] getWeights() { 39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return weights; 39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method returns NURBS' spline basis function degree. 40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return NURBS' spline basis function degree 40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public int getBasisFunctionDegree() { 40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return basisFunctionDegree; 40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void write(JmeExporter ex) throws IOException { 40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta OutputCapsule oc = ex.getCapsule(this); 40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.writeSavableArrayList((ArrayList) controlPoints, "controlPoints", null); 41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(type, "type", SplineType.CatmullRom); 41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float list[] = new float[segmentsLength.size()]; 41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < segmentsLength.size(); i++) { 41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta list[i] = segmentsLength.get(i); 41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(list, "segmentsLength", null); 41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(totalLength, "totalLength", 0); 41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.writeSavableArrayList((ArrayList) CRcontrolPoints, "CRControlPoints", null); 41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(curveTension, "curveTension", 0.5f); 42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(cycle, "cycle", false); 42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.writeSavableArrayList((ArrayList<Float>)knots, "knots", null); 42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(weights, "weights", null); 42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(basisFunctionDegree, "basisFunctionDegree", 0); 42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void read(JmeImporter im) throws IOException { 42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta InputCapsule in = im.getCapsule(this); 42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta controlPoints = (ArrayList<Vector3f>) in.readSavableArrayList("wayPoints", null); 43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float list[] = in.readFloatArray("segmentsLength", null); 43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (list != null) { 43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta segmentsLength = new ArrayList<Float>(); 43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < list.length; i++) { 43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta segmentsLength.add(new Float(list[i])); 43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta type = in.readEnum("pathSplineType", SplineType.class, SplineType.CatmullRom); 43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta totalLength = in.readFloat("totalLength", 0); 44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CRcontrolPoints = (ArrayList<Vector3f>) in.readSavableArrayList("CRControlPoints", null); 44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta curveTension = in.readFloat("curveTension", 0.5f); 44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cycle = in.readBoolean("cycle", false); 44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta knots = in.readSavableArrayList("knots", null); 44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta weights = in.readFloatArray("weights", null); 44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta basisFunctionDegree = in.readInt("basisFunctionDegree", 0); 44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 448