|
@@ -32,12 +32,12 @@
|
|
package com.jme3.scene.plugins.blender.curves;
|
|
package com.jme3.scene.plugins.blender.curves;
|
|
|
|
|
|
import java.nio.FloatBuffer;
|
|
import java.nio.FloatBuffer;
|
|
-import java.nio.IntBuffer;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
import java.util.Map.Entry;
|
|
import java.util.Map.Entry;
|
|
|
|
+import java.util.TreeMap;
|
|
import java.util.logging.Logger;
|
|
import java.util.logging.Logger;
|
|
|
|
|
|
import com.jme3.material.Material;
|
|
import com.jme3.material.Material;
|
|
@@ -69,11 +69,12 @@ import com.jme3.util.BufferUtils;
|
|
|
|
|
|
/**
|
|
/**
|
|
* A class that is used in mesh calculations.
|
|
* A class that is used in mesh calculations.
|
|
- * @author Marcin Roguski
|
|
|
|
|
|
+ *
|
|
|
|
+ * @author Marcin Roguski (Kaelthas)
|
|
*/
|
|
*/
|
|
public class CurvesHelper extends AbstractBlenderHelper {
|
|
public class CurvesHelper extends AbstractBlenderHelper {
|
|
-
|
|
|
|
private static final Logger LOGGER = Logger.getLogger(CurvesHelper.class.getName());
|
|
private static final Logger LOGGER = Logger.getLogger(CurvesHelper.class.getName());
|
|
|
|
+
|
|
/** Minimum basis U function degree for NURBS curves and surfaces. */
|
|
/** Minimum basis U function degree for NURBS curves and surfaces. */
|
|
protected int minimumBasisUFunctionDegree = 4;
|
|
protected int minimumBasisUFunctionDegree = 4;
|
|
/** Minimum basis V function degree for NURBS curves and surfaces. */
|
|
/** Minimum basis V function degree for NURBS curves and surfaces. */
|
|
@@ -113,7 +114,7 @@ public class CurvesHelper extends AbstractBlenderHelper {
|
|
if (isBack) {
|
|
if (isBack) {
|
|
LOGGER.warning("No back face in curve implemented yet!");//TODO: implement back face
|
|
LOGGER.warning("No back face in curve implemented yet!");//TODO: implement back face
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
//reading nurbs (and sorting them by material)
|
|
//reading nurbs (and sorting them by material)
|
|
List<Structure> nurbStructures = ((Structure) curveStructure.getFieldValue("nurb")).evaluateListBase(blenderContext);
|
|
List<Structure> nurbStructures = ((Structure) curveStructure.getFieldValue("nurb")).evaluateListBase(blenderContext);
|
|
Map<Number, List<Structure>> nurbs = new HashMap<Number, List<Structure>>();
|
|
Map<Number, List<Structure>> nurbs = new HashMap<Number, List<Structure>>();
|
|
@@ -155,44 +156,43 @@ public class CurvesHelper extends AbstractBlenderHelper {
|
|
float handlerLength = bevelDepth / 2.0f;
|
|
float handlerLength = bevelDepth / 2.0f;
|
|
|
|
|
|
List<Vector3f> conrtolPoints = new ArrayList<Vector3f>(extrude > 0.0f ? 19 : 13);
|
|
List<Vector3f> conrtolPoints = new ArrayList<Vector3f>(extrude > 0.0f ? 19 : 13);
|
|
- conrtolPoints.add(new Vector3f(-bevelDepth, extrude, 0));
|
|
|
|
- conrtolPoints.add(new Vector3f(-bevelDepth, handlerLength + extrude, 0));
|
|
|
|
-
|
|
|
|
- conrtolPoints.add(new Vector3f(-handlerLength, bevelDepth + extrude, 0));
|
|
|
|
- conrtolPoints.add(new Vector3f(0, bevelDepth + extrude, 0));
|
|
|
|
- conrtolPoints.add(new Vector3f(handlerLength, bevelDepth + extrude, 0));
|
|
|
|
-
|
|
|
|
- conrtolPoints.add(new Vector3f(bevelDepth, extrude + handlerLength, 0));
|
|
|
|
- conrtolPoints.add(new Vector3f(bevelDepth, extrude, 0));
|
|
|
|
- conrtolPoints.add(new Vector3f(bevelDepth, extrude - handlerLength, 0));
|
|
|
|
-
|
|
|
|
if (extrude > 0.0f) {
|
|
if (extrude > 0.0f) {
|
|
- conrtolPoints.add(new Vector3f(bevelDepth, -extrude + handlerLength, 0));
|
|
|
|
- conrtolPoints.add(new Vector3f(bevelDepth, -extrude, 0));
|
|
|
|
- conrtolPoints.add(new Vector3f(bevelDepth, -extrude - handlerLength, 0));
|
|
|
|
|
|
+ conrtolPoints.add(new Vector3f(-bevelDepth, 0, extrude));
|
|
|
|
+ conrtolPoints.add(new Vector3f(-bevelDepth, 0, -handlerLength + extrude));
|
|
|
|
+ conrtolPoints.add(new Vector3f(-bevelDepth, 0, handlerLength - extrude));
|
|
}
|
|
}
|
|
-
|
|
|
|
- conrtolPoints.add(new Vector3f(handlerLength, -bevelDepth - extrude, 0));
|
|
|
|
- conrtolPoints.add(new Vector3f(0, -bevelDepth - extrude, 0));
|
|
|
|
- conrtolPoints.add(new Vector3f(-handlerLength, -bevelDepth - extrude, 0));
|
|
|
|
-
|
|
|
|
- conrtolPoints.add(new Vector3f(-bevelDepth, -handlerLength - extrude, 0));
|
|
|
|
- conrtolPoints.add(new Vector3f(-bevelDepth, -extrude, 0));
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ conrtolPoints.add(new Vector3f(-bevelDepth, 0, -extrude));
|
|
|
|
+ conrtolPoints.add(new Vector3f(-bevelDepth, 0, -handlerLength - extrude));
|
|
|
|
+
|
|
|
|
+ conrtolPoints.add(new Vector3f(-handlerLength, 0, -bevelDepth - extrude));
|
|
|
|
+ conrtolPoints.add(new Vector3f(0, 0, -bevelDepth - extrude));
|
|
|
|
+ conrtolPoints.add(new Vector3f(handlerLength, 0, -bevelDepth - extrude));
|
|
|
|
+
|
|
if (extrude > 0.0f) {
|
|
if (extrude > 0.0f) {
|
|
- conrtolPoints.add(new Vector3f(-bevelDepth, handlerLength - extrude, 0));
|
|
|
|
-
|
|
|
|
- conrtolPoints.add(new Vector3f(-bevelDepth, -handlerLength + extrude, 0));
|
|
|
|
- conrtolPoints.add(new Vector3f(-bevelDepth, extrude, 0));
|
|
|
|
|
|
+ conrtolPoints.add(new Vector3f(bevelDepth, 0, -extrude - handlerLength));
|
|
|
|
+ conrtolPoints.add(new Vector3f(bevelDepth, 0, -extrude));
|
|
|
|
+ conrtolPoints.add(new Vector3f(bevelDepth, 0, -extrude + handlerLength));
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ conrtolPoints.add(new Vector3f(bevelDepth, 0, extrude - handlerLength));
|
|
|
|
+ conrtolPoints.add(new Vector3f(bevelDepth, 0, extrude));
|
|
|
|
+ conrtolPoints.add(new Vector3f(bevelDepth, 0, extrude + handlerLength));
|
|
|
|
+
|
|
|
|
+ conrtolPoints.add(new Vector3f(handlerLength, 0, bevelDepth + extrude));
|
|
|
|
+ conrtolPoints.add(new Vector3f(0, 0, bevelDepth + extrude));
|
|
|
|
+ conrtolPoints.add(new Vector3f(-handlerLength, 0, bevelDepth + extrude));
|
|
|
|
+
|
|
|
|
+ conrtolPoints.add(new Vector3f(-bevelDepth, 0, handlerLength + extrude));
|
|
|
|
+ conrtolPoints.add(new Vector3f(-bevelDepth, 0, extrude));
|
|
|
|
+
|
|
Spline bevelSpline = new Spline(SplineType.Bezier, conrtolPoints, 0, false);
|
|
Spline bevelSpline = new Spline(SplineType.Bezier, conrtolPoints, 0, false);
|
|
Curve bevelCurve = new Curve(bevelSpline, bevResol);
|
|
Curve bevelCurve = new Curve(bevelSpline, bevResol);
|
|
bevelObject = new ArrayList<Geometry>(1);
|
|
bevelObject = new ArrayList<Geometry>(1);
|
|
bevelObject.add(new Geometry("", bevelCurve));
|
|
bevelObject.add(new Geometry("", bevelCurve));
|
|
} else if (extrude > 0.0f) {
|
|
} else if (extrude > 0.0f) {
|
|
Spline bevelSpline = new Spline(SplineType.Linear, new Vector3f[]{
|
|
Spline bevelSpline = new Spline(SplineType.Linear, new Vector3f[]{
|
|
- new Vector3f(0, extrude, 0), new Vector3f(0, -extrude, 0)
|
|
|
|
|
|
+ new Vector3f(0, 0, -extrude), new Vector3f(0, 0, extrude)
|
|
}, 1, false);
|
|
}, 1, false);
|
|
Curve bevelCurve = new Curve(bevelSpline, bevResol);
|
|
Curve bevelCurve = new Curve(bevelSpline, bevResol);
|
|
bevelObject = new ArrayList<Geometry>(1);
|
|
bevelObject = new ArrayList<Geometry>(1);
|
|
@@ -201,7 +201,7 @@ public class CurvesHelper extends AbstractBlenderHelper {
|
|
}
|
|
}
|
|
|
|
|
|
//getting taper object
|
|
//getting taper object
|
|
- Curve taperObject = null;
|
|
|
|
|
|
+ Spline taperObject = null;
|
|
Pointer pTaperObject = (Pointer) curveStructure.getFieldValue("taperobj");
|
|
Pointer pTaperObject = (Pointer) curveStructure.getFieldValue("taperobj");
|
|
if (bevelObject != null && pTaperObject.isNotNull()) {
|
|
if (bevelObject != null && pTaperObject.isNotNull()) {
|
|
Pointer pTaperStructure = (Pointer) pTaperObject.fetchData(blenderContext.getInputStream()).get(0).getFieldValue("data");
|
|
Pointer pTaperStructure = (Pointer) pTaperObject.fetchData(blenderContext.getInputStream()).get(0).getFieldValue("data");
|
|
@@ -262,7 +262,7 @@ public class CurvesHelper extends AbstractBlenderHelper {
|
|
* @throws BlenderFileException
|
|
* @throws BlenderFileException
|
|
* an exception is thrown when there are problems with the blender file
|
|
* an exception is thrown when there are problems with the blender file
|
|
*/
|
|
*/
|
|
- protected List<Geometry> loadBezierCurve(Vector3f loc, Structure nurb, List<Geometry> bevelObject, Curve taperObject,
|
|
|
|
|
|
+ protected List<Geometry> loadBezierCurve(Vector3f loc, Structure nurb, List<Geometry> bevelObject, Spline taperObject,
|
|
BlenderContext blenderContext) throws BlenderFileException {
|
|
BlenderContext blenderContext) throws BlenderFileException {
|
|
Pointer pBezierTriple = (Pointer) nurb.getFieldValue("bezt");
|
|
Pointer pBezierTriple = (Pointer) nurb.getFieldValue("bezt");
|
|
List<Geometry> result = new ArrayList<Geometry>();
|
|
List<Geometry> result = new ArrayList<Geometry>();
|
|
@@ -274,6 +274,23 @@ public class CurvesHelper extends AbstractBlenderHelper {
|
|
//creating the curve object
|
|
//creating the curve object
|
|
BezierCurve bezierCurve = new BezierCurve(0, pBezierTriple.fetchData(blenderContext.getInputStream()), 3);
|
|
BezierCurve bezierCurve = new BezierCurve(0, pBezierTriple.fetchData(blenderContext.getInputStream()), 3);
|
|
List<Vector3f> controlPoints = bezierCurve.getControlPoints();
|
|
List<Vector3f> controlPoints = bezierCurve.getControlPoints();
|
|
|
|
+ if(fixUpAxis) {
|
|
|
|
+ for(Vector3f v : controlPoints) {
|
|
|
|
+ float y = v.y;
|
|
|
|
+ v.y = v.z;
|
|
|
|
+ v.z = -y;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (bevelObject != null && taperObject == null) {// create taper object using the scales of the bezier triple
|
|
|
|
+ int triplesCount = controlPoints.size() / 3;
|
|
|
|
+ List<Vector3f> taperControlPoints = new ArrayList<Vector3f>(triplesCount);
|
|
|
|
+ for (int i = 0; i < triplesCount; ++i) {
|
|
|
|
+ taperControlPoints.add(new Vector3f(controlPoints.get(i * 3 + 1).x, bezierCurve.getRadius(i), 0));
|
|
|
|
+ }
|
|
|
|
+ taperObject = new Spline(SplineType.Linear, taperControlPoints, 0, false);
|
|
|
|
+ }
|
|
|
|
+
|
|
if (cyclic) {
|
|
if (cyclic) {
|
|
//copy the first three points at the end
|
|
//copy the first three points at the end
|
|
for (int i = 0; i < 3; ++i) {
|
|
for (int i = 0; i < 3; ++i) {
|
|
@@ -292,7 +309,7 @@ public class CurvesHelper extends AbstractBlenderHelper {
|
|
result.add(curveGeometry);
|
|
result.add(curveGeometry);
|
|
//TODO: use front and back flags; surface excluding algorithm for bezier circles should be added
|
|
//TODO: use front and back flags; surface excluding algorithm for bezier circles should be added
|
|
} else {//creating curve with bevel and taper shape
|
|
} else {//creating curve with bevel and taper shape
|
|
- result = this.applyBevelAndTaper(curve, bevelObject, taperObject, smooth, blenderContext);
|
|
|
|
|
|
+ result = this.applyBevelAndTaper(curve, bevelObject, taperObject, smooth, blenderContext);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
return result;
|
|
@@ -315,7 +332,7 @@ public class CurvesHelper extends AbstractBlenderHelper {
|
|
* an exception is throw when problems with blender loaded data occurs
|
|
* an exception is throw when problems with blender loaded data occurs
|
|
*/
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
@SuppressWarnings("unchecked")
|
|
- protected List<Geometry> loadNurb(Vector3f loc, Structure nurb, List<Geometry> bevelObject, Curve taperObject,
|
|
|
|
|
|
+ protected List<Geometry> loadNurb(Vector3f loc, Structure nurb, List<Geometry> bevelObject, Spline taperObject,
|
|
BlenderContext blenderContext) throws BlenderFileException {
|
|
BlenderContext blenderContext) throws BlenderFileException {
|
|
//loading the knots
|
|
//loading the knots
|
|
List<Float>[] knots = new List[2];
|
|
List<Float>[] knots = new List[2];
|
|
@@ -388,34 +405,41 @@ public class CurvesHelper extends AbstractBlenderHelper {
|
|
}
|
|
}
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
-
|
|
|
|
- /**
|
|
|
|
- * This method returns the taper scale that should be applied to the object.
|
|
|
|
- * @param taperPoints
|
|
|
|
- * the taper points
|
|
|
|
- * @param taperLength
|
|
|
|
- * the taper curve length
|
|
|
|
- * @param percent
|
|
|
|
- * the percent of way along the whole taper curve
|
|
|
|
- */
|
|
|
|
- protected float getTaperScale(float[] taperPoints, float taperLength, float percent) {
|
|
|
|
- float length = taperLength * percent;
|
|
|
|
- float currentLength = 0;
|
|
|
|
- Vector3f p = new Vector3f();
|
|
|
|
- int i;
|
|
|
|
- for (i = 0; i < taperPoints.length - 6 && currentLength < length; i += 3) {
|
|
|
|
- p.set(taperPoints[i], taperPoints[i + 1], taperPoints[i + 2]);
|
|
|
|
- p.subtractLocal(taperPoints[i + 3], taperPoints[i + 4], taperPoints[i + 5]);
|
|
|
|
- currentLength += p.length();
|
|
|
|
- }
|
|
|
|
- currentLength -= p.length();
|
|
|
|
- float leftLength = length - currentLength;
|
|
|
|
- float percentOnSegment = p.length() == 0 ? 0 : leftLength / p.length();
|
|
|
|
- Vector3f store = FastMath.interpolateLinear(percentOnSegment,
|
|
|
|
- new Vector3f(taperPoints[i], taperPoints[i + 1], taperPoints[i + 2]),
|
|
|
|
- new Vector3f(taperPoints[i + 3], taperPoints[i + 4], taperPoints[i + 5]));
|
|
|
|
- return store.y;
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The method computes the taper scale on the given point on the curve.
|
|
|
|
+ *
|
|
|
|
+ * @param taper
|
|
|
|
+ * the taper object that defines the scale
|
|
|
|
+ * @param percent
|
|
|
|
+ * the percent of the 'road' along the curve
|
|
|
|
+ * @return scale on the pointed place along the curve
|
|
|
|
+ */
|
|
|
|
+ protected float getTaperScale(Spline taper, float percent) {
|
|
|
|
+ percent = FastMath.clamp(percent, 0, 1);
|
|
|
|
+ List<Float> segmentLengths = taper.getSegmentsLength();
|
|
|
|
+ float percentLength = taper.getTotalLength() * percent;
|
|
|
|
+ float partLength = 0;
|
|
|
|
+ int i;
|
|
|
|
+ for (i = 0; i < segmentLengths.size(); ++i) {
|
|
|
|
+ partLength += segmentLengths.get(i);
|
|
|
|
+ if (partLength > percentLength) {
|
|
|
|
+ partLength -= segmentLengths.get(i);
|
|
|
|
+ percentLength -= partLength;
|
|
|
|
+ percent = percentLength / segmentLengths.get(i);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // do not cross the line :)
|
|
|
|
+ if (percent >= 1) {
|
|
|
|
+ percent = 1;
|
|
|
|
+ --i;
|
|
|
|
+ }
|
|
|
|
+ if (taper.getType() == SplineType.Bezier) {
|
|
|
|
+ i *= 3;
|
|
|
|
+ }
|
|
|
|
+ return taper.interpolate(percent, i, null).y;
|
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
/**
|
|
* This method applies bevel and taper objects to the curve.
|
|
* This method applies bevel and taper objects to the curve.
|
|
@@ -431,186 +455,325 @@ public class CurvesHelper extends AbstractBlenderHelper {
|
|
* the blender context
|
|
* the blender context
|
|
* @return a list of geometries representing the beveled and/or tapered curve
|
|
* @return a list of geometries representing the beveled and/or tapered curve
|
|
*/
|
|
*/
|
|
- protected List<Geometry> applyBevelAndTaper(Curve curve, List<Geometry> bevelObject, Curve taperObject,
|
|
|
|
|
|
+ protected List<Geometry> applyBevelAndTaper(Curve curve, List<Geometry> bevelObject, Spline taperObject,
|
|
boolean smooth, BlenderContext blenderContext) {
|
|
boolean smooth, BlenderContext blenderContext) {
|
|
- float[] curvePoints = BufferUtils.getFloatArray(curve.getFloatBuffer(Type.Position));
|
|
|
|
|
|
+ Vector3f[] curvePoints = BufferUtils.getVector3Array(curve.getFloatBuffer(Type.Position));
|
|
float curveLength = curve.getLength();
|
|
float curveLength = curve.getLength();
|
|
- //TODO: use the smooth var
|
|
|
|
-
|
|
|
|
- //taper data
|
|
|
|
- float[] taperPoints = null;
|
|
|
|
- float taperLength = 0;
|
|
|
|
- if (taperObject != null) {
|
|
|
|
- taperPoints = BufferUtils.getFloatArray(taperObject.getFloatBuffer(Type.Position));
|
|
|
|
- taperLength = taperObject.getLength();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //several objects can be allocated only once
|
|
|
|
- Vector3f p = new Vector3f();
|
|
|
|
- Vector3f z = new Vector3f(0, 0, 1);
|
|
|
|
- Vector3f negativeY = new Vector3f(0, -1, 0);
|
|
|
|
- Matrix4f m = new Matrix4f();
|
|
|
|
- float lengthAlongCurve = 0, taperScale = 1.0f;
|
|
|
|
- Quaternion planeRotation = new Quaternion();
|
|
|
|
- Quaternion zRotation = new Quaternion();
|
|
|
|
- float[] temp = new float[]{0, 0, 0, 1};
|
|
|
|
- Map<Vector3f, Vector3f> normalMap = new HashMap<Vector3f, Vector3f>();//normalMap merges normals of faces that will be rendered smooth
|
|
|
|
-
|
|
|
|
|
|
+
|
|
FloatBuffer[] vertexBuffers = new FloatBuffer[bevelObject.size()];
|
|
FloatBuffer[] vertexBuffers = new FloatBuffer[bevelObject.size()];
|
|
FloatBuffer[] normalBuffers = new FloatBuffer[bevelObject.size()];
|
|
FloatBuffer[] normalBuffers = new FloatBuffer[bevelObject.size()];
|
|
- IntBuffer[] indexBuffers = new IntBuffer[bevelObject.size()];
|
|
|
|
- for (int geomIndex = 0; geomIndex < bevelObject.size(); ++geomIndex) {
|
|
|
|
- Mesh mesh = bevelObject.get(geomIndex).getMesh();
|
|
|
|
- FloatBuffer positions = mesh.getFloatBuffer(Type.Position);
|
|
|
|
- float[] vertices = BufferUtils.getFloatArray(positions);
|
|
|
|
-
|
|
|
|
- for (int i = 0; i < curvePoints.length; i += 3) {
|
|
|
|
- p.set(curvePoints[i], curvePoints[i + 1], curvePoints[i + 2]);
|
|
|
|
- Vector3f v;
|
|
|
|
- if (i == 0) {
|
|
|
|
- v = new Vector3f(curvePoints[3] - p.x, curvePoints[4] - p.y, curvePoints[5] - p.z);
|
|
|
|
- } else if (i + 3 >= curvePoints.length) {
|
|
|
|
- v = new Vector3f(p.x - curvePoints[i - 3], p.y - curvePoints[i - 2], p.z - curvePoints[i - 1]);
|
|
|
|
- lengthAlongCurve += v.length();
|
|
|
|
- } else {
|
|
|
|
- v = new Vector3f(curvePoints[i + 3] - curvePoints[i - 3],
|
|
|
|
- curvePoints[i + 4] - curvePoints[i - 2],
|
|
|
|
- curvePoints[i + 5] - curvePoints[i - 1]);
|
|
|
|
- lengthAlongCurve += new Vector3f(curvePoints[i + 3] - p.x, curvePoints[i + 4] - p.y, curvePoints[i + 5] - p.z).length();
|
|
|
|
- }
|
|
|
|
- v.normalizeLocal();
|
|
|
|
-
|
|
|
|
- float angle = FastMath.acos(v.dot(z));
|
|
|
|
- v.crossLocal(z).normalizeLocal();//v is the rotation axis now
|
|
|
|
- planeRotation.fromAngleAxis(angle, v);
|
|
|
|
-
|
|
|
|
- Vector3f zAxisRotationVector = negativeY.cross(v).normalizeLocal();
|
|
|
|
- float zAxisRotationAngle = FastMath.acos(negativeY.dot(v));
|
|
|
|
- zRotation.fromAngleAxis(zAxisRotationAngle, zAxisRotationVector);
|
|
|
|
-
|
|
|
|
- //point transformation matrix
|
|
|
|
- if (taperPoints != null) {
|
|
|
|
- taperScale = this.getTaperScale(taperPoints, taperLength, lengthAlongCurve / curveLength);
|
|
|
|
- }
|
|
|
|
- m.set(Matrix4f.IDENTITY);
|
|
|
|
- m.setRotationQuaternion(planeRotation.multLocal(zRotation));
|
|
|
|
- m.setTranslation(p);
|
|
|
|
-
|
|
|
|
- //these vertices need to be thrown on XY plane
|
|
|
|
- //and moved to the origin of [p1.x, p1.y] on the plane
|
|
|
|
- Vector3f[] verts = new Vector3f[vertices.length / 3];
|
|
|
|
- for (int j = 0; j < verts.length; ++j) {
|
|
|
|
- temp[0] = vertices[j * 3] * taperScale;
|
|
|
|
- temp[1] = vertices[j * 3 + 1] * taperScale;
|
|
|
|
- temp[2] = 0;
|
|
|
|
- m.mult(temp);//the result is stored in the array
|
|
|
|
- if (fixUpAxis) {//TODO: not the other way ???
|
|
|
|
- verts[j] = new Vector3f(temp[0], temp[1], temp[2]);
|
|
|
|
- } else {
|
|
|
|
- verts[j] = new Vector3f(temp[0], temp[2], -temp[1]);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (vertexBuffers[geomIndex] == null) {
|
|
|
|
- vertexBuffers[geomIndex] = BufferUtils.createFloatBuffer(verts.length * curvePoints.length);
|
|
|
|
- }
|
|
|
|
- FloatBuffer buffer = BufferUtils.createFloatBuffer(verts);
|
|
|
|
- vertexBuffers[geomIndex].put(buffer);
|
|
|
|
-
|
|
|
|
- //adding indexes
|
|
|
|
- IntBuffer indexBuffer = indexBuffers[geomIndex];
|
|
|
|
- if (indexBuffer == null) {
|
|
|
|
- //the amount of faces in the final mesh is the amount of edges in the bevel curve
|
|
|
|
- //(which is less by 1 than its number of vertices)
|
|
|
|
- //multiplied by 2 (because each edge has two faces assigned on both sides)
|
|
|
|
- //and multiplied by the amount of bevel curve repeats which is equal to the amount of vertices on the target curve
|
|
|
|
- //finally we need to subtract the bevel edges amount 2 times because the border edges have only one face attached
|
|
|
|
- //and at last multiply everything by 3 because each face needs 3 indexes to be described
|
|
|
|
- int bevelCurveEdgesAmount = verts.length - 1;
|
|
|
|
- indexBuffer = BufferUtils.createIntBuffer(((bevelCurveEdgesAmount << 1) * curvePoints.length - bevelCurveEdgesAmount << 1) * 3);
|
|
|
|
- indexBuffers[geomIndex] = indexBuffer;
|
|
|
|
- }
|
|
|
|
- int pointOffset = i / 3 * verts.length;
|
|
|
|
- if (i + 3 < curvePoints.length) {
|
|
|
|
- for (int index = 0; index < verts.length - 1; ++index) {
|
|
|
|
- indexBuffer.put(index + pointOffset);
|
|
|
|
- indexBuffer.put(index + pointOffset + 1);
|
|
|
|
- indexBuffer.put(verts.length + index + pointOffset);
|
|
|
|
- indexBuffer.put(verts.length + index + pointOffset);
|
|
|
|
- indexBuffer.put(index + pointOffset + 1);
|
|
|
|
- indexBuffer.put(verts.length + index + pointOffset + 1);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //calculating the normals
|
|
|
|
|
|
+ IndexBuffer[] indexBuffers = new IndexBuffer[bevelObject.size()];
|
|
for (int geomIndex = 0; geomIndex < bevelObject.size(); ++geomIndex) {
|
|
for (int geomIndex = 0; geomIndex < bevelObject.size(); ++geomIndex) {
|
|
- Vector3f[] allVerts = BufferUtils.getVector3Array(vertexBuffers[geomIndex]);
|
|
|
|
- int[] allIndices = BufferUtils.getIntArray(indexBuffers[geomIndex]);
|
|
|
|
- for (int i = 0; i < allIndices.length - 3; i += 3) {
|
|
|
|
- Vector3f n = FastMath.computeNormal(allVerts[allIndices[i]], allVerts[allIndices[i + 1]], allVerts[allIndices[i + 2]]);
|
|
|
|
- this.addNormal(n, normalMap, smooth, allVerts[allIndices[i]], allVerts[allIndices[i + 1]], allVerts[allIndices[i + 2]]);
|
|
|
|
- }
|
|
|
|
- if (normalBuffers[geomIndex] == null) {
|
|
|
|
- normalBuffers[geomIndex] = BufferUtils.createFloatBuffer(allVerts.length * 3);
|
|
|
|
- }
|
|
|
|
- for (Vector3f v : allVerts) {
|
|
|
|
- Vector3f n = normalMap.get(v);
|
|
|
|
- normalBuffers[geomIndex].put(n.x);
|
|
|
|
- normalBuffers[geomIndex].put(n.y);
|
|
|
|
- normalBuffers[geomIndex].put(n.z);
|
|
|
|
|
|
+ Mesh mesh = bevelObject.get(geomIndex).getMesh();
|
|
|
|
+ Vector3f[] positions = BufferUtils.getVector3Array(mesh.getFloatBuffer(Type.Position));
|
|
|
|
+ Vector3f[] bevelPoints = this.transformToFirstLineOfBevelPoints(positions, curvePoints[0], curvePoints[1]);
|
|
|
|
+
|
|
|
|
+ List<Vector3f[]> bevels = new ArrayList<Vector3f[]>(curvePoints.length);
|
|
|
|
+ bevels.add(bevelPoints);
|
|
|
|
+
|
|
|
|
+ vertexBuffers[geomIndex] = BufferUtils.createFloatBuffer(bevelPoints.length * 3 * curvePoints.length * (smooth ? 1 : 6));
|
|
|
|
+ for (int i = 1; i < curvePoints.length - 1; ++i) {
|
|
|
|
+ bevelPoints = this.transformBevel(bevelPoints, curvePoints[i - 1], curvePoints[i], curvePoints[i + 1]);
|
|
|
|
+ bevels.add(bevelPoints);
|
|
}
|
|
}
|
|
|
|
+ bevelPoints = this.transformBevel(bevelPoints, curvePoints[curvePoints.length - 2], curvePoints[curvePoints.length - 1], null);
|
|
|
|
+ bevels.add(bevelPoints);
|
|
|
|
+
|
|
|
|
+ //apply scales to the bevels
|
|
|
|
+ float lengthAlongCurve = 0;
|
|
|
|
+ for(int i=0;i<curvePoints.length; ++i) {
|
|
|
|
+ if(i > 0) {
|
|
|
|
+ lengthAlongCurve += curvePoints[i].subtract(curvePoints[i - 1]).length();
|
|
|
|
+ }
|
|
|
|
+ float taperScale = this.getTaperScale(taperObject, i == 0 ? 0 : lengthAlongCurve / curveLength);
|
|
|
|
+ this.applyScale(bevels.get(i), curvePoints[i], taperScale);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(smooth) {//add everything to the buffer
|
|
|
|
+ for(Vector3f[] bevel : bevels) {
|
|
|
|
+ for(Vector3f d : bevel) {
|
|
|
|
+ vertexBuffers[geomIndex].put(d.x);
|
|
|
|
+ vertexBuffers[geomIndex].put(d.y);
|
|
|
|
+ vertexBuffers[geomIndex].put(d.z);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {//add vertices to the buffer duplicating them so that every vertex belongs only to a single triangle
|
|
|
|
+ for (int i = 0; i < curvePoints.length - 1; ++i) {
|
|
|
|
+ for (int j = 0; j < bevelPoints.length - 1; ++j) {
|
|
|
|
+ //first triangle
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i)[j].x);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i)[j].y);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i)[j].z);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i)[j + 1].x);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i)[j + 1].y);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i)[j + 1].z);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i + 1)[j].x);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i + 1)[j].y);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i + 1)[j].z);
|
|
|
|
+
|
|
|
|
+ //second triangle
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i)[j + 1].x);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i)[j + 1].y);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i)[j + 1].z);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i + 1)[j + 1].x);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i + 1)[j + 1].y);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i + 1)[j + 1].z);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i + 1)[j].x);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i + 1)[j].y);
|
|
|
|
+ vertexBuffers[geomIndex].put(bevels.get(i + 1)[j].z);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ indexBuffers[geomIndex] = this.generateIndexes(bevelPoints.length, curvePoints.length, smooth);
|
|
|
|
+ normalBuffers[geomIndex] = this.generateNormals(indexBuffers[geomIndex], vertexBuffers[geomIndex], smooth);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ //creating and returning the result
|
|
List<Geometry> result = new ArrayList<Geometry>(vertexBuffers.length);
|
|
List<Geometry> result = new ArrayList<Geometry>(vertexBuffers.length);
|
|
Float oneReferenceToCurveLength = new Float(curveLength);//its important for array modifier to use one reference here
|
|
Float oneReferenceToCurveLength = new Float(curveLength);//its important for array modifier to use one reference here
|
|
for (int i = 0; i < vertexBuffers.length; ++i) {
|
|
for (int i = 0; i < vertexBuffers.length; ++i) {
|
|
Mesh mesh = new Mesh();
|
|
Mesh mesh = new Mesh();
|
|
mesh.setBuffer(Type.Position, 3, vertexBuffers[i]);
|
|
mesh.setBuffer(Type.Position, 3, vertexBuffers[i]);
|
|
- mesh.setBuffer(Type.Index, 3, indexBuffers[i]);
|
|
|
|
|
|
+ if(indexBuffers[i].getIntBuffer() != null) {
|
|
|
|
+ mesh.setBuffer(Type.Index, 3, indexBuffers[i].getIntBuffer());
|
|
|
|
+ } else {
|
|
|
|
+ mesh.setBuffer(Type.Index, 3, indexBuffers[i].getShortBuffer());
|
|
|
|
+ }
|
|
mesh.setBuffer(Type.Normal, 3, normalBuffers[i]);
|
|
mesh.setBuffer(Type.Normal, 3, normalBuffers[i]);
|
|
Geometry g = new Geometry("g" + i, mesh);
|
|
Geometry g = new Geometry("g" + i, mesh);
|
|
g.setUserData("curveLength", oneReferenceToCurveLength);
|
|
g.setUserData("curveLength", oneReferenceToCurveLength);
|
|
g.updateModelBound();
|
|
g.updateModelBound();
|
|
result.add(g);
|
|
result.add(g);
|
|
}
|
|
}
|
|
-
|
|
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * the method applies scale for the given bevel points. The points table is
|
|
|
|
+ * being modified so expect ypur result there.
|
|
|
|
+ *
|
|
|
|
+ * @param points
|
|
|
|
+ * the bevel points
|
|
|
|
+ * @param centerPoint
|
|
|
|
+ * the center point of the bevel
|
|
|
|
+ * @param scale
|
|
|
|
+ * the scale to be applied
|
|
|
|
+ */
|
|
|
|
+ private void applyScale(Vector3f[] points, Vector3f centerPoint, float scale) {
|
|
|
|
+ Vector3f taperScaleVector = new Vector3f();
|
|
|
|
+ for (Vector3f p : points) {
|
|
|
|
+ taperScaleVector.set(centerPoint).subtractLocal(p).multLocal(1 - scale);
|
|
|
|
+ p.addLocal(taperScaleVector);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The method generates normal buffer for the created mesh of the curve.
|
|
|
|
+ *
|
|
|
|
+ * @param indexes
|
|
|
|
+ * the indexes of the mesh points
|
|
|
|
+ * @param points
|
|
|
|
+ * the mesh's points
|
|
|
|
+ * @param smooth
|
|
|
|
+ * the flag indicating if the result is to be smooth or solid
|
|
|
|
+ * @return normals buffer for the mesh
|
|
|
|
+ */
|
|
|
|
+ private FloatBuffer generateNormals(IndexBuffer indexes, FloatBuffer points, boolean smooth) {
|
|
|
|
+ Map<Integer, Vector3f> normalMap = new TreeMap<Integer, Vector3f>();
|
|
|
|
+ Vector3f[] allVerts = BufferUtils.getVector3Array(points);
|
|
|
|
+
|
|
|
|
+ for (int i = 0; i < indexes.limit(); i += 3) {
|
|
|
|
+ int index1 = indexes.get(i);
|
|
|
|
+ int index2 = indexes.get(i + 1);
|
|
|
|
+ int index3 = indexes.get(i + 2);
|
|
|
|
+
|
|
|
|
+ Vector3f n = FastMath.computeNormal(allVerts[index1], allVerts[index2], allVerts[index3]);
|
|
|
|
+ this.addNormal(n, normalMap, smooth, index1, index2, index3);
|
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
|
- * This method adds a normal to a normals' map. This map is used to merge normals of a vertor that should be rendered smooth.
|
|
|
|
- *
|
|
|
|
- * @param normalToAdd
|
|
|
|
- * a normal to be added
|
|
|
|
- * @param normalMap
|
|
|
|
- * merges normals of faces that will be rendered smooth; the key is the vertex and the value - its normal vector
|
|
|
|
- * @param smooth
|
|
|
|
- * the variable that indicates wheather to merge normals (creating the smooth mesh) or not
|
|
|
|
- * @param vertices
|
|
|
|
- * a list of vertices read from the blender file
|
|
|
|
- */
|
|
|
|
- private void addNormal(Vector3f normalToAdd, Map<Vector3f, Vector3f> normalMap, boolean smooth, Vector3f... vertices) {
|
|
|
|
- for (Vector3f v : vertices) {
|
|
|
|
- Vector3f n = normalMap.get(v);
|
|
|
|
|
|
+ FloatBuffer normals = BufferUtils.createFloatBuffer(normalMap.size() * 3);
|
|
|
|
+ for (Entry<Integer, Vector3f> entry : normalMap.entrySet()) {
|
|
|
|
+ normals.put(entry.getValue().x);
|
|
|
|
+ normals.put(entry.getValue().y);
|
|
|
|
+ normals.put(entry.getValue().z);
|
|
|
|
+ }
|
|
|
|
+ return normals;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The amount of faces in the final mesh is the amount of edges in the bevel
|
|
|
|
+ * curve (which is less by 1 than its number of vertices) multiplied by 2
|
|
|
|
+ * (because each edge has two faces assigned on both sides) and multiplied
|
|
|
|
+ * by the amount of bevel curve repeats which is equal to the amount of
|
|
|
|
+ * vertices on the target curve finally we need to subtract the bevel edges
|
|
|
|
+ * amount 2 times because the border edges have only one face attached and
|
|
|
|
+ * at last multiply everything by 3 because each face needs 3 indexes to be
|
|
|
|
+ * described
|
|
|
|
+ *
|
|
|
|
+ * @param bevelShapeVertexCount
|
|
|
|
+ * amount of points in bevel shape
|
|
|
|
+ * @param bevelRepeats
|
|
|
|
+ * amount of bevel shapes along the curve
|
|
|
|
+ * @param smooth
|
|
|
|
+ * the smooth flag
|
|
|
|
+ * @return index buffer for the mesh
|
|
|
|
+ */
|
|
|
|
+ private IndexBuffer generateIndexes(int bevelShapeVertexCount, int bevelRepeats, boolean smooth) {
|
|
|
|
+ if(smooth) {
|
|
|
|
+ int indexBufferSize = (bevelRepeats - 1) * (bevelShapeVertexCount - 1) * 6;
|
|
|
|
+ IndexBuffer result = new IndexBuffer(indexBufferSize);
|
|
|
|
+
|
|
|
|
+ for (int i = 0; i < bevelRepeats - 1; ++i) {
|
|
|
|
+ for (int j = 0; j < bevelShapeVertexCount - 1; ++j) {
|
|
|
|
+ result.put(i * bevelShapeVertexCount + j);
|
|
|
|
+ result.put(i * bevelShapeVertexCount + j + 1);
|
|
|
|
+ result.put((i + 1) * bevelShapeVertexCount + j);
|
|
|
|
+
|
|
|
|
+ result.put(i * bevelShapeVertexCount + j + 1);
|
|
|
|
+ result.put((i + 1) * bevelShapeVertexCount + j + 1);
|
|
|
|
+ result.put((i + 1) * bevelShapeVertexCount + j);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return result;
|
|
|
|
+ } else {
|
|
|
|
+ //every pair of bevel vertices belongs to two triangles
|
|
|
|
+ //we have the same amount of pairs as the amount of vertices in bevel
|
|
|
|
+ //so the amount of triangles is: bevelShapeVertexCount * 2 * (bevelRepeats - 1)
|
|
|
|
+ //and this gives the amount of vertices in non smooth shape as below ...
|
|
|
|
+ int indexBufferSize = bevelShapeVertexCount * bevelRepeats * 6;//6 = 2 * 3 where 2 is stated above and 3 is the count of vertices for each triangle
|
|
|
|
+ IndexBuffer result = new IndexBuffer(indexBufferSize);
|
|
|
|
+ for (int i = 0; i < indexBufferSize; ++i) {
|
|
|
|
+ result.put(i);
|
|
|
|
+ }
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The method transforms the bevel along the curve.
|
|
|
|
+ *
|
|
|
|
+ * @param bevel
|
|
|
|
+ * the bevel to be transformed
|
|
|
|
+ * @param prevPos
|
|
|
|
+ * previous curve point
|
|
|
|
+ * @param currPos
|
|
|
|
+ * current curve point (here the center of the new bevel will be
|
|
|
|
+ * set)
|
|
|
|
+ * @param nextPos
|
|
|
|
+ * next curve point
|
|
|
|
+ * @return points of transformed bevel
|
|
|
|
+ */
|
|
|
|
+ private Vector3f[] transformBevel(Vector3f[] bevel, Vector3f prevPos, Vector3f currPos, Vector3f nextPos) {
|
|
|
|
+ bevel = bevel.clone();
|
|
|
|
+
|
|
|
|
+ //currPos and directionVector define the line in 3D space
|
|
|
|
+ Vector3f directionVector = prevPos != null ? currPos.subtract(prevPos) : nextPos.subtract(currPos);
|
|
|
|
+ directionVector.normalizeLocal();
|
|
|
|
+
|
|
|
|
+ //plane is described by equation: Ax + By + Cz + D = 0 where planeNormal = [A, B, C] and D = -(Ax + By + Cz)
|
|
|
|
+ Vector3f planeNormal = null;
|
|
|
|
+ if(prevPos != null) {
|
|
|
|
+ planeNormal = currPos.subtract(prevPos).normalizeLocal();
|
|
|
|
+ if(nextPos != null) {
|
|
|
|
+ planeNormal.addLocal(nextPos.subtract(currPos).normalizeLocal()).normalizeLocal();
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ planeNormal = nextPos.subtract(currPos).normalizeLocal();
|
|
|
|
+ }
|
|
|
|
+ float D = -planeNormal.dot(currPos);//D = -(Ax + By + Cz)
|
|
|
|
+
|
|
|
|
+ //now we need to compute paralell cast of each bevel point on the plane, the leading line is already known
|
|
|
|
+ //parametric equation of a line: x = px + vx * t; y = py + vy * t; z = pz + vz * t
|
|
|
|
+ //where p = currPos and v = directionVector
|
|
|
|
+ //using x, y and z in plane equation we get value of 't' that will allow us to compute the point where plane and line cross
|
|
|
|
+ float temp = planeNormal.dot(directionVector);
|
|
|
|
+ for(int i=0;i<bevel.length;++i) {
|
|
|
|
+ float t = -(planeNormal.dot(bevel[i]) + D) / temp;
|
|
|
|
+ if (fixUpAxis) {
|
|
|
|
+ bevel[i] = new Vector3f(bevel[i].x + directionVector.x * t, bevel[i].y + directionVector.y * t, bevel[i].z + directionVector.z * t);
|
|
|
|
+ } else {
|
|
|
|
+ bevel[i] = new Vector3f(bevel[i].x + directionVector.x * t, -bevel[i].z + directionVector.z * t, bevel[i].y + directionVector.y * t);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return bevel;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * This method transforms the first line of the bevel points positioning it
|
|
|
|
+ * on the first point of the curve.
|
|
|
|
+ *
|
|
|
|
+ * @param startingLinePoints
|
|
|
|
+ * the vbevel shape points
|
|
|
|
+ * @param firstCurvePoint
|
|
|
|
+ * the first curve's point
|
|
|
|
+ * @param secondCurvePoint
|
|
|
|
+ * the second curve's point
|
|
|
|
+ * @return points of transformed bevel
|
|
|
|
+ */
|
|
|
|
+ private Vector3f[] transformToFirstLineOfBevelPoints(Vector3f[] startingLinePoints, Vector3f firstCurvePoint, Vector3f secondCurvePoint) {
|
|
|
|
+ Vector3f planeNormal = secondCurvePoint.subtract(firstCurvePoint).normalizeLocal();
|
|
|
|
+
|
|
|
|
+ float angle = FastMath.acos(planeNormal.dot(Vector3f.UNIT_Y));
|
|
|
|
+ planeNormal.crossLocal(Vector3f.UNIT_Y).normalizeLocal();//planeNormal is the rotation axis now
|
|
|
|
+ Quaternion pointRotation = new Quaternion();
|
|
|
|
+ pointRotation.fromAngleAxis(angle, planeNormal);
|
|
|
|
+
|
|
|
|
+ Matrix4f m = new Matrix4f();
|
|
|
|
+ m.setRotationQuaternion(pointRotation);
|
|
|
|
+ m.setTranslation(firstCurvePoint);
|
|
|
|
+
|
|
|
|
+ float[] temp = new float[] { 0, 0, 0, 1 };
|
|
|
|
+ Vector3f[] verts = new Vector3f[startingLinePoints.length];
|
|
|
|
+ for (int j = 0; j < verts.length; ++j) {
|
|
|
|
+ temp[0] = startingLinePoints[j].x;
|
|
|
|
+ temp[1] = startingLinePoints[j].y;
|
|
|
|
+ temp[2] = startingLinePoints[j].z;
|
|
|
|
+ temp = m.mult(temp);//the result is stored in the array
|
|
|
|
+ if (fixUpAxis) {
|
|
|
|
+ verts[j] = new Vector3f(temp[0], -temp[2], temp[1]);
|
|
|
|
+ } else {
|
|
|
|
+ verts[j] = new Vector3f(temp[0], temp[1], temp[2]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return verts;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The method adds a normal to the given map. Depending in the smooth factor
|
|
|
|
+ * it is either merged with the revious normal or not.
|
|
|
|
+ *
|
|
|
|
+ * @param normalToAdd
|
|
|
|
+ * the normal vector to be added
|
|
|
|
+ * @param normalMap
|
|
|
|
+ * the normal map where we add vectors
|
|
|
|
+ * @param smooth
|
|
|
|
+ * the smooth flag
|
|
|
|
+ * @param indexes
|
|
|
|
+ * the indexes of the normals
|
|
|
|
+ */
|
|
|
|
+ private void addNormal(Vector3f normalToAdd, Map<Integer, Vector3f> normalMap, boolean smooth, int... indexes) {
|
|
|
|
+ for (int index : indexes) {
|
|
|
|
+ Vector3f n = normalMap.get(index);
|
|
if (!smooth || n == null) {
|
|
if (!smooth || n == null) {
|
|
- normalMap.put(v, normalToAdd.clone());
|
|
|
|
|
|
+ normalMap.put(index, normalToAdd.clone());
|
|
} else {
|
|
} else {
|
|
n.addLocal(normalToAdd).normalizeLocal();
|
|
n.addLocal(normalToAdd).normalizeLocal();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /**
|
|
|
|
- * This method loads the taper object.
|
|
|
|
- * @param taperStructure
|
|
|
|
- * the taper structure
|
|
|
|
- * @param blenderContext
|
|
|
|
- * the blender context
|
|
|
|
- * @return the taper object
|
|
|
|
- * @throws BlenderFileException
|
|
|
|
- */
|
|
|
|
- protected Curve loadTaperObject(Structure taperStructure, BlenderContext blenderContext) throws BlenderFileException {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * This method loads the taper object.
|
|
|
|
+ *
|
|
|
|
+ * @param taperStructure
|
|
|
|
+ * the taper structure
|
|
|
|
+ * @param blenderContext
|
|
|
|
+ * the blender context
|
|
|
|
+ * @return the taper object
|
|
|
|
+ * @throws BlenderFileException
|
|
|
|
+ */
|
|
|
|
+ protected Spline loadTaperObject(Structure taperStructure, BlenderContext blenderContext) throws BlenderFileException {
|
|
//reading nurbs
|
|
//reading nurbs
|
|
List<Structure> nurbStructures = ((Structure) taperStructure.getFieldValue("nurb")).evaluateListBase(blenderContext);
|
|
List<Structure> nurbStructures = ((Structure) taperStructure.getFieldValue("nurb")).evaluateListBase(blenderContext);
|
|
for (Structure nurb : nurbStructures) {
|
|
for (Structure nurb : nurbStructures) {
|
|
@@ -625,21 +788,21 @@ public class CurvesHelper extends AbstractBlenderHelper {
|
|
|
|
|
|
//return the first taper curve that has more than 3 control points
|
|
//return the first taper curve that has more than 3 control points
|
|
if (controlPoints.size() > 3) {
|
|
if (controlPoints.size() > 3) {
|
|
- Spline spline = new Spline(SplineType.Bezier, controlPoints, 0, false);
|
|
|
|
- int resolution = ((Number) taperStructure.getFieldValue("resolu")).intValue();
|
|
|
|
- return new Curve(spline, resolution);
|
|
|
|
|
|
+ return new Spline(SplineType.Bezier, controlPoints, 0, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
- /**
|
|
|
|
- * This method returns the translation of the curve. The UP axis is taken into account here.
|
|
|
|
- * @param curveStructure
|
|
|
|
- * the curve structure
|
|
|
|
- * @return curve translation
|
|
|
|
- */
|
|
|
|
|
|
+ /**
|
|
|
|
+ * This method returns the translation of the curve. The UP axis is taken
|
|
|
|
+ * into account here.
|
|
|
|
+ *
|
|
|
|
+ * @param curveStructure
|
|
|
|
+ * the curve structure
|
|
|
|
+ * @return curve translation
|
|
|
|
+ */
|
|
@SuppressWarnings("unchecked")
|
|
@SuppressWarnings("unchecked")
|
|
protected Vector3f getLoc(Structure curveStructure) {
|
|
protected Vector3f getLoc(Structure curveStructure) {
|
|
DynamicArray<Number> locArray = (DynamicArray<Number>) curveStructure.getFieldValue("loc");
|
|
DynamicArray<Number> locArray = (DynamicArray<Number>) curveStructure.getFieldValue("loc");
|