|
@@ -434,14 +434,16 @@
|
|
// updates the mesh positions according to the positionFunction returned values.
|
|
// updates the mesh positions according to the positionFunction returned values.
|
|
// The positionFunction argument must be a javascript function accepting the mesh "positions" array as parameter.
|
|
// The positionFunction argument must be a javascript function accepting the mesh "positions" array as parameter.
|
|
// This dedicated positionFunction computes new mesh positions according to the given mesh type.
|
|
// This dedicated positionFunction computes new mesh positions according to the given mesh type.
|
|
- public updateMeshPositions(positionFunction): void {
|
|
|
|
|
|
+ public updateMeshPositions(positionFunction, computeNormals: boolean = true): void {
|
|
var positions = this.getVerticesData(BABYLON.VertexBuffer.PositionKind);
|
|
var positions = this.getVerticesData(BABYLON.VertexBuffer.PositionKind);
|
|
positionFunction(positions);
|
|
positionFunction(positions);
|
|
- var indices = this.getIndices();
|
|
|
|
- var normals = this.getVerticesData(BABYLON.VertexBuffer.NormalKind);
|
|
|
|
this.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positions, false, false);
|
|
this.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positions, false, false);
|
|
- BABYLON.VertexData.ComputeNormals(positions, indices, normals);
|
|
|
|
- this.updateVerticesData(BABYLON.VertexBuffer.NormalKind, normals, false, false);
|
|
|
|
|
|
+ if (computeNormals) {
|
|
|
|
+ var indices = this.getIndices();
|
|
|
|
+ var normals = this.getVerticesData(BABYLON.VertexBuffer.NormalKind);
|
|
|
|
+ BABYLON.VertexData.ComputeNormals(positions, indices, normals);
|
|
|
|
+ this.updateVerticesData(BABYLON.VertexBuffer.NormalKind, normals, false, false);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1195,7 +1197,7 @@
|
|
};
|
|
};
|
|
var sideOrientation = ribbonInstance.sideOrientation;
|
|
var sideOrientation = ribbonInstance.sideOrientation;
|
|
var positionFunction = positionsOfRibbon(pathArray, sideOrientation);
|
|
var positionFunction = positionsOfRibbon(pathArray, sideOrientation);
|
|
- ribbonInstance.updateMeshPositions(positionFunction);
|
|
|
|
|
|
+ ribbonInstance.updateMeshPositions(positionFunction, true);
|
|
|
|
|
|
return ribbonInstance;
|
|
return ribbonInstance;
|
|
|
|
|
|
@@ -1270,58 +1272,105 @@
|
|
}
|
|
}
|
|
|
|
|
|
// Lines
|
|
// Lines
|
|
- public static CreateLines(name: string, points: Vector3[], scene: Scene, updatable?: boolean): LinesMesh {
|
|
|
|
- var lines = new LinesMesh(name, scene, updatable);
|
|
|
|
|
|
+ public static CreateLines(name: string, points: Vector3[], scene: Scene, updatable?: boolean, linesInstance: LinesMesh = null): LinesMesh {
|
|
|
|
+ if (linesInstance) { // lines update
|
|
|
|
+ var positionsOfLines = function(points) {
|
|
|
|
+ var positionFunction = function(positions) {
|
|
|
|
+ var i = 0;
|
|
|
|
+ for(var p = 0; p < points.length; p++) {
|
|
|
|
+ positions[i] = points[p].x;
|
|
|
|
+ positions[i + 1] = points[p].y;
|
|
|
|
+ positions[i + 2] = points[p].z;
|
|
|
|
+ i += 3;
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ return positionFunction;
|
|
|
|
+ };
|
|
|
|
+ var positionFunction = positionsOfLines(points);
|
|
|
|
+ linesInstance.updateMeshPositions(positionFunction, false);
|
|
|
|
+
|
|
|
|
+ return linesInstance;
|
|
|
|
|
|
- var vertexData = VertexData.CreateLines(points);
|
|
|
|
|
|
+ }
|
|
|
|
+ else { // lines creation
|
|
|
|
+
|
|
|
|
+ var lines = new LinesMesh(name, scene, updatable);
|
|
|
|
|
|
- vertexData.applyToMesh(lines, updatable);
|
|
|
|
|
|
+ var vertexData = VertexData.CreateLines(points);
|
|
|
|
|
|
- return lines;
|
|
|
|
|
|
+ vertexData.applyToMesh(lines, updatable);
|
|
|
|
+
|
|
|
|
+ return lines;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
// Extrusion
|
|
// Extrusion
|
|
- public static ExtrudeShape(name: string, shape: Vector3[], path: Vector3[], scale: number, rotation: number, scene: Scene, updatable?: boolean, sideOrientation: number = Mesh.DEFAULTSIDE): Mesh {
|
|
|
|
|
|
+ public static ExtrudeShape(name: string, shape: Vector3[], path: Vector3[], scale: number, rotation: number, scene: Scene, updatable?: boolean, sideOrientation: number = Mesh.DEFAULTSIDE, extrudedInstance: Mesh = null): Mesh {
|
|
scale = scale || 1;
|
|
scale = scale || 1;
|
|
rotation = rotation || 0;
|
|
rotation = rotation || 0;
|
|
- var extruded = Mesh._ExtrudeShapeGeneric(name, shape, path, scale, rotation, null, null, false, false, false, scene, updatable, sideOrientation);
|
|
|
|
|
|
+ var extruded = Mesh._ExtrudeShapeGeneric(name, shape, path, scale, rotation, null, null, false, false, false, scene, updatable, sideOrientation, extrudedInstance);
|
|
return extruded;
|
|
return extruded;
|
|
}
|
|
}
|
|
|
|
|
|
- public static ExtrudeShapeCustom(name: string, shape: Vector3[], path: Vector3[], scaleFunction, rotationFunction, ribbonCloseArray: boolean, ribbonClosePath: boolean, scene: Scene, updatable?: boolean, sideOrientation: number = Mesh.DEFAULTSIDE): Mesh {
|
|
|
|
- var extrudedCustom = Mesh._ExtrudeShapeGeneric(name, shape, path, null, null, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, true, scene, updatable, sideOrientation);
|
|
|
|
|
|
+ public static ExtrudeShapeCustom(name: string, shape: Vector3[], path: Vector3[], scaleFunction, rotationFunction, ribbonCloseArray: boolean, ribbonClosePath: boolean, scene: Scene, updatable?: boolean, sideOrientation: number = Mesh.DEFAULTSIDE, extrudedInstance: Mesh = null): Mesh {
|
|
|
|
+ var extrudedCustom = Mesh._ExtrudeShapeGeneric(name, shape, path, null, null, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, true, scene, updatable, sideOrientation, extrudedInstance);
|
|
return extrudedCustom;
|
|
return extrudedCustom;
|
|
}
|
|
}
|
|
|
|
|
|
- private static _ExtrudeShapeGeneric(name: string, shape: Vector3[], curve: Vector3[], scale: number, rotation: number, scaleFunction: { (i: number, distance: number): number; }, rotateFunction: { (i: number, distance: number): number; }, rbCA: boolean, rbCP: boolean, custom: boolean, scene: Scene, updtbl: boolean, side: number): Mesh {
|
|
|
|
- var path3D = new Path3D(curve);
|
|
|
|
- var tangents = path3D.getTangents();
|
|
|
|
- var normals = path3D.getNormals();
|
|
|
|
- var binormals = path3D.getBinormals();
|
|
|
|
- var distances = path3D.getDistances();
|
|
|
|
- var shapePaths = new Array<Array<Vector3>>();
|
|
|
|
- var angle = 0;
|
|
|
|
- var returnScale: { (i: number, distance: number): number; } = (i, distance) => { return scale; };
|
|
|
|
- var returnRotation: { (i: number, distance: number): number; } = (i, distance) => { return rotation; };
|
|
|
|
- var rotate: { (i: number, distance: number): number; } = custom ? rotateFunction : returnRotation;
|
|
|
|
- var scl: { (i: number, distance: number): number; } = custom ? scaleFunction : returnScale;
|
|
|
|
-
|
|
|
|
- for (var i = 0; i < curve.length; i++) {
|
|
|
|
- var shapePath = new Array<Vector3>();
|
|
|
|
- var angleStep = rotate(i, distances[i]);
|
|
|
|
- var scaleRatio = scl(i, distances[i]);
|
|
|
|
- for (var p = 0; p < shape.length; p++) {
|
|
|
|
- var rotationMatrix = Matrix.RotationAxis(tangents[i], angle);
|
|
|
|
- var planed = ((tangents[i].scale(shape[p].z)).add(normals[i].scale(shape[p].x)).add(binormals[i].scale(shape[p].y)));
|
|
|
|
- var rotated = Vector3.TransformCoordinates(planed, rotationMatrix).scaleInPlace(scaleRatio).add(curve[i]);
|
|
|
|
- shapePath.push(rotated);
|
|
|
|
|
|
+ private static _ExtrudeShapeGeneric(name: string, shape: Vector3[], curve: Vector3[], scale: number, rotation: number, scaleFunction: { (i: number, distance: number): number; }, rotateFunction: { (i: number, distance: number): number; }, rbCA: boolean, rbCP: boolean, custom: boolean, scene: Scene, updtbl: boolean, side: number, instance: Mesh): Mesh {
|
|
|
|
+
|
|
|
|
+ // extrusion geometry
|
|
|
|
+ var extrusionPathArray = function(shape, curve, path3D, shapePaths, scale, rotation, scaleFunction, rotateFunction, custom) {
|
|
|
|
+ var tangents = path3D.getTangents();
|
|
|
|
+ var normals = path3D.getNormals();
|
|
|
|
+ var binormals = path3D.getBinormals();
|
|
|
|
+ var distances = path3D.getDistances();
|
|
|
|
+
|
|
|
|
+ var angle = 0;
|
|
|
|
+ var returnScale: { (i: number, distance: number): number; } = (i, distance) => { return scale; };
|
|
|
|
+ var returnRotation: { (i: number, distance: number): number; } = (i, distance) => { return rotation; };
|
|
|
|
+ var rotate: { (i: number, distance: number): number; } = custom ? rotateFunction : returnRotation;
|
|
|
|
+ var scl: { (i: number, distance: number): number; } = custom ? scaleFunction : returnScale;
|
|
|
|
+ var index = 0;
|
|
|
|
+
|
|
|
|
+ for (var i = 0; i < curve.length; i++) {
|
|
|
|
+ var shapePath = new Array<Vector3>();
|
|
|
|
+ var angleStep = rotate(i, distances[i]);
|
|
|
|
+ var scaleRatio = scl(i, distances[i]);
|
|
|
|
+ for (var p = 0; p < shape.length; p++) {
|
|
|
|
+ var rotationMatrix = Matrix.RotationAxis(tangents[i], angle);
|
|
|
|
+ var planed = ((tangents[i].scale(shape[p].z)).add(normals[i].scale(shape[p].x)).add(binormals[i].scale(shape[p].y)));
|
|
|
|
+ var rotated = Vector3.TransformCoordinates(planed, rotationMatrix).scaleInPlace(scaleRatio).add(curve[i]);
|
|
|
|
+ shapePath.push(rotated);
|
|
|
|
+ }
|
|
|
|
+ shapePaths[index] = shapePath;
|
|
|
|
+ angle += angleStep;
|
|
|
|
+ index++;
|
|
}
|
|
}
|
|
- shapePaths.push(shapePath);
|
|
|
|
- angle += angleStep;
|
|
|
|
|
|
+ return shapePaths;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ if (instance) { // instance update
|
|
|
|
+
|
|
|
|
+ var path3D = ((<any>instance).path3D).update(curve);
|
|
|
|
+ var pathArray = extrusionPathArray(shape, curve, (<any>instance).path3D, (<any>instance).pathArray, scale, rotation, scaleFunction, rotateFunction, custom);
|
|
|
|
+ instance = Mesh.CreateRibbon(null, pathArray, null, null, null, null, null, null, instance);
|
|
|
|
+
|
|
|
|
+ return instance;
|
|
|
|
+ }
|
|
|
|
+ else { // extruded shape creation
|
|
|
|
+
|
|
|
|
+ var path3D = <any>new Path3D(curve);
|
|
|
|
+ var newShapePaths = new Array<Array<Vector3>>();
|
|
|
|
+ var pathArray = extrusionPathArray(shape, curve, path3D, newShapePaths, scale, rotation, scaleFunction, rotateFunction, custom);
|
|
|
|
+
|
|
|
|
+ var extrudedGeneric = Mesh.CreateRibbon(name, pathArray, rbCA, rbCP, 0, scene, updtbl, side);
|
|
|
|
+ (<any>extrudedGeneric).pathArray = pathArray;
|
|
|
|
+ (<any>extrudedGeneric).path3D = path3D;
|
|
|
|
+
|
|
|
|
+ return extrudedGeneric;
|
|
}
|
|
}
|
|
|
|
|
|
- var extrudedGeneric = Mesh.CreateRibbon(name, shapePaths, rbCA, rbCP, 0, scene, updtbl, side);
|
|
|
|
- return extrudedGeneric;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
// Plane & ground
|
|
// Plane & ground
|
|
@@ -1395,35 +1444,59 @@
|
|
return ground;
|
|
return ground;
|
|
}
|
|
}
|
|
|
|
|
|
- public static CreateTube(name: string, path: Vector3[], radius: number, tesselation: number, radiusFunction: { (i: number, distance: number): number; }, scene: Scene, updatable?: boolean, sideOrientation: number = Mesh.DEFAULTSIDE): Mesh {
|
|
|
|
- var path3D = new Path3D(path);
|
|
|
|
- var tangents = path3D.getTangents();
|
|
|
|
- var normals = path3D.getNormals();
|
|
|
|
- var distances = path3D.getDistances();
|
|
|
|
- var pi2 = Math.PI * 2;
|
|
|
|
- var step = pi2 / tesselation;
|
|
|
|
- var returnRadius: { (i: number, distance: number): number; } = (i, distance) => radius;
|
|
|
|
- var radiusFunctionFinal: { (i: number, distance: number): number; } = radiusFunction || returnRadius;
|
|
|
|
-
|
|
|
|
- var circlePaths = new Array<Array<Vector3>>();
|
|
|
|
- var circlePath: Vector3[];
|
|
|
|
- var rad: number;
|
|
|
|
- var normal: Vector3;
|
|
|
|
- var rotated: Vector3;
|
|
|
|
- var rotationMatrix: Matrix;
|
|
|
|
- for (var i = 0; i < path.length; i++) {
|
|
|
|
- rad = radiusFunctionFinal(i, distances[i]); // current radius
|
|
|
|
- circlePath = Array<Vector3>(); // current circle array
|
|
|
|
- normal = normals[i]; // current normal
|
|
|
|
- for (var ang = 0; ang < pi2; ang += step) {
|
|
|
|
- rotationMatrix = Matrix.RotationAxis(tangents[i], ang);
|
|
|
|
- rotated = Vector3.TransformCoordinates(normal, rotationMatrix).scaleInPlace(rad).add(path[i]);
|
|
|
|
- circlePath.push(rotated);
|
|
|
|
|
|
+ public static CreateTube(name: string, path: Vector3[], radius: number, tessellation: number, radiusFunction: { (i: number, distance: number): number; }, scene: Scene, updatable?: boolean, sideOrientation: number = Mesh.DEFAULTSIDE, tubeInstance: Mesh = null): Mesh {
|
|
|
|
+
|
|
|
|
+ // tube geometry
|
|
|
|
+ var tubePathArray = function(path, path3D, circlePaths, radius, tessellation, radiusFunction) {
|
|
|
|
+ var tangents = path3D.getTangents();
|
|
|
|
+ var normals = path3D.getNormals();
|
|
|
|
+ var distances = path3D.getDistances();
|
|
|
|
+ var pi2 = Math.PI * 2;
|
|
|
|
+ var step = pi2 / tessellation;
|
|
|
|
+ var returnRadius: { (i: number, distance: number): number; } = (i, distance) => radius;
|
|
|
|
+ var radiusFunctionFinal: { (i: number, distance: number): number; } = radiusFunction || returnRadius;
|
|
|
|
+
|
|
|
|
+ var circlePath: Vector3[];
|
|
|
|
+ var rad: number;
|
|
|
|
+ var normal: Vector3;
|
|
|
|
+ var rotated: Vector3;
|
|
|
|
+ var rotationMatrix: Matrix;
|
|
|
|
+ var index = 0;
|
|
|
|
+ for (var i = 0; i < path.length; i++) {
|
|
|
|
+ rad = radiusFunctionFinal(i, distances[i]); // current radius
|
|
|
|
+ circlePath = Array<Vector3>(); // current circle array
|
|
|
|
+ normal = normals[i]; // current normal
|
|
|
|
+ for (var ang = 0; ang < pi2; ang += step) {
|
|
|
|
+ rotationMatrix = Matrix.RotationAxis(tangents[i], ang);
|
|
|
|
+ rotated = Vector3.TransformCoordinates(normal, rotationMatrix).scaleInPlace(rad).add(path[i]);
|
|
|
|
+ circlePath.push(rotated);
|
|
|
|
+ }
|
|
|
|
+ circlePaths[index] = circlePath;
|
|
|
|
+ index++;
|
|
}
|
|
}
|
|
- circlePaths.push(circlePath);
|
|
|
|
|
|
+ return circlePaths;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ if (tubeInstance) { // tube update
|
|
|
|
+ var path3D = ((<any>tubeInstance).path3D).update(path);
|
|
|
|
+ var pathArray = tubePathArray(path, path3D, (<any>tubeInstance).pathArray, radius, (<any>tubeInstance).tessellation, radiusFunction);
|
|
|
|
+ tubeInstance = Mesh.CreateRibbon(null, pathArray, null, null, null, null, null, null, tubeInstance);
|
|
|
|
+
|
|
|
|
+ return tubeInstance;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ else { // tube creation
|
|
|
|
+
|
|
|
|
+ var path3D = <any>new Path3D(path);
|
|
|
|
+ var newPathArray = new Array<Array<Vector3>>();
|
|
|
|
+ var pathArray = tubePathArray(path, path3D, newPathArray, radius, tessellation, radiusFunction);
|
|
|
|
+ var tube = Mesh.CreateRibbon(name, pathArray, false, true, 0, scene, updatable, sideOrientation);
|
|
|
|
+ (<any>tube).pathArray = pathArray;
|
|
|
|
+ (<any>tube).path3D = path3D;
|
|
|
|
+ (<any>tube).tessellation = tessellation;
|
|
|
|
+
|
|
|
|
+ return tube;
|
|
}
|
|
}
|
|
- var tube = Mesh.CreateRibbon(name, circlePaths, false, true, 0, scene, updatable, sideOrientation);
|
|
|
|
- return tube;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
// Decals
|
|
// Decals
|