|
@@ -1,4 +1,6 @@
|
|
|
module BABYLON {
|
|
|
+ const depthSortFunction = (p1: DepthSortedParticle, p2: DepthSortedParticle) => p2.sqDistance - p1.sqDistance;
|
|
|
+
|
|
|
/**
|
|
|
* The SPS is a single updatable mesh. The solid particles are simply separate parts or faces fo this big mesh.
|
|
|
*As it is just a mesh, the SPS has all the same properties than any other BJS mesh : not more, not less. It can be scaled, rotated, translated, enlighted, textured, moved, etc.
|
|
@@ -89,8 +91,6 @@ module BABYLON {
|
|
|
private _depthSort: boolean = false;
|
|
|
private _shapeCounter: number = 0;
|
|
|
private _copy: SolidParticle = new SolidParticle(0, 0, 0, null, 0, 0, this);
|
|
|
- private _shape: Vector3[];
|
|
|
- private _shapeUV: number[];
|
|
|
private _color: Color4 = new Color4(0, 0, 0, 0);
|
|
|
private _computeParticleColor: boolean = true;
|
|
|
private _computeParticleTexture: boolean = true;
|
|
@@ -98,47 +98,10 @@ module BABYLON {
|
|
|
private _computeParticleVertex: boolean = false;
|
|
|
private _computeBoundingBox: boolean = false;
|
|
|
private _depthSortParticles: boolean = true;
|
|
|
- private _cam_axisZ: Vector3 = Vector3.Zero();
|
|
|
- private _cam_axisY: Vector3 = Vector3.Zero();
|
|
|
- private _cam_axisX: Vector3 = Vector3.Zero();
|
|
|
- private _axisZ: Vector3 = Axis.Z;
|
|
|
private _camera: TargetCamera;
|
|
|
- private _particle: SolidParticle;
|
|
|
- private _camDir: Vector3 = Vector3.Zero();
|
|
|
- private _camInvertedPosition: Vector3 = Vector3.Zero();
|
|
|
- private _rotMatrix: Matrix = new Matrix();
|
|
|
- private _invertMatrix: Matrix = new Matrix();
|
|
|
- private _rotated: Vector3 = Vector3.Zero();
|
|
|
- private _quaternion: Quaternion = new Quaternion();
|
|
|
- private _vertex: Vector3 = Vector3.Zero();
|
|
|
- private _normal: Vector3 = Vector3.Zero();
|
|
|
- private _yaw: number = 0.0;
|
|
|
- private _pitch: number = 0.0;
|
|
|
- private _roll: number = 0.0;
|
|
|
- private _halfroll: number = 0.0;
|
|
|
- private _halfpitch: number = 0.0;
|
|
|
- private _halfyaw: number = 0.0;
|
|
|
- private _sinRoll: number = 0.0;
|
|
|
- private _cosRoll: number = 0.0;
|
|
|
- private _sinPitch: number = 0.0;
|
|
|
- private _cosPitch: number = 0.0;
|
|
|
- private _sinYaw: number = 0.0;
|
|
|
- private _cosYaw: number = 0.0;
|
|
|
private _mustUnrotateFixedNormals = false;
|
|
|
- private _minimum: Vector3 = Vector3.Zero();
|
|
|
- private _maximum: Vector3 = Vector3.Zero();
|
|
|
- private _minBbox: Vector3 = Vector3.Zero();
|
|
|
- private _maxBbox: Vector3 = Vector3.Zero();
|
|
|
private _particlesIntersect: boolean = false;
|
|
|
- private _depthSortFunction: (p1: DepthSortedParticle, p2: DepthSortedParticle) => number =
|
|
|
- function(p1, p2) {
|
|
|
- return (p2.sqDistance - p1.sqDistance);
|
|
|
- };
|
|
|
private _needs32Bits: boolean = false;
|
|
|
- private _pivotBackTranslation: Vector3 = Vector3.Zero();
|
|
|
- private _scaledPivot: Vector3 = Vector3.Zero();
|
|
|
- private _particleHasParent: boolean = false;
|
|
|
- private _parent: SolidParticle;
|
|
|
|
|
|
/**
|
|
|
* Creates a SPS (Solid Particle System) object.
|
|
@@ -337,27 +300,19 @@ module BABYLON {
|
|
|
private _unrotateFixedNormals() {
|
|
|
var index = 0;
|
|
|
var idx = 0;
|
|
|
+ const tmpNormal = Tmp.Vector3[0];
|
|
|
+ const rotMatrix = Tmp.Matrix[0];
|
|
|
+ const invertedRotMatrix = Tmp.Matrix[1];
|
|
|
for (var p = 0; p < this.particles.length; p++) {
|
|
|
- this._particle = this.particles[p];
|
|
|
- this._shape = this._particle._model._shape;
|
|
|
- if (this._particle.rotationQuaternion) {
|
|
|
- this._quaternion.copyFrom(this._particle.rotationQuaternion);
|
|
|
- }
|
|
|
- else {
|
|
|
- this._yaw = this._particle.rotation.y;
|
|
|
- this._pitch = this._particle.rotation.x;
|
|
|
- this._roll = this._particle.rotation.z;
|
|
|
- this._quaternionRotationYPR();
|
|
|
- }
|
|
|
- this._quaternionToRotationMatrix();
|
|
|
- this._rotMatrix.invertToRef(this._invertMatrix);
|
|
|
+ const particle = this.particles[p];
|
|
|
+ const shape = particle._model._shape;
|
|
|
+ particle.getRotationMatrix(rotMatrix);
|
|
|
+ rotMatrix.invertToRef(invertedRotMatrix);
|
|
|
|
|
|
- for (var pt = 0; pt < this._shape.length; pt++) {
|
|
|
+ for (var pt = 0; pt < shape.length; pt++) {
|
|
|
idx = index + pt * 3;
|
|
|
- Vector3.TransformNormalFromFloatsToRef(this._normals32[idx], this._normals32[idx + 1], this._normals32[idx + 2], this._invertMatrix, this._normal);
|
|
|
- this._fixedNormal32[idx] = this._normal.x;
|
|
|
- this._fixedNormal32[idx + 1] = this._normal.y;
|
|
|
- this._fixedNormal32[idx + 2] = this._normal.z;
|
|
|
+ Vector3.TransformNormalFromFloatsToRef(this._normals32[idx], this._normals32[idx + 1], this._normals32[idx + 2], invertedRotMatrix, tmpNormal);
|
|
|
+ tmpNormal.toArray(this._fixedNormal32, idx);
|
|
|
}
|
|
|
index = idx + 3;
|
|
|
}
|
|
@@ -365,22 +320,14 @@ module BABYLON {
|
|
|
|
|
|
//reset copy
|
|
|
private _resetCopy() {
|
|
|
- this._copy.position.x = 0;
|
|
|
- this._copy.position.y = 0;
|
|
|
- this._copy.position.z = 0;
|
|
|
- this._copy.rotation.x = 0;
|
|
|
- this._copy.rotation.y = 0;
|
|
|
- this._copy.rotation.z = 0;
|
|
|
- this._copy.rotationQuaternion = null;
|
|
|
- this._copy.scaling.x = 1.0;
|
|
|
- this._copy.scaling.y = 1.0;
|
|
|
- this._copy.scaling.z = 1.0;
|
|
|
- this._copy.uvs.x = 0;
|
|
|
- this._copy.uvs.y = 0;
|
|
|
- this._copy.uvs.z = 1.0;
|
|
|
- this._copy.uvs.w = 1.0;
|
|
|
- this._copy.color = null;
|
|
|
- this._copy.translateFromPivot = false;
|
|
|
+ const copy = this._copy;
|
|
|
+ copy.position.setAll(0);
|
|
|
+ copy.rotation.setAll(0);
|
|
|
+ copy.rotationQuaternion = null;
|
|
|
+ copy.scaling.setAll(1);
|
|
|
+ copy.uvs.copyFromFloats(0.0, 0.0, 1.0, 1.0);
|
|
|
+ copy.color = null;
|
|
|
+ copy.translateFromPivot = false;
|
|
|
}
|
|
|
|
|
|
// _meshBuilder : inserts the shape model in the global SPS mesh
|
|
@@ -391,80 +338,69 @@ module BABYLON {
|
|
|
var n = 0;
|
|
|
|
|
|
this._resetCopy();
|
|
|
+ const copy = this._copy;
|
|
|
if (options && options.positionFunction) { // call to custom positionFunction
|
|
|
- options.positionFunction(this._copy, idx, idxInShape);
|
|
|
+ options.positionFunction(copy, idx, idxInShape);
|
|
|
this._mustUnrotateFixedNormals = true;
|
|
|
}
|
|
|
|
|
|
- if (this._copy.rotationQuaternion) {
|
|
|
- this._quaternion.copyFrom(this._copy.rotationQuaternion);
|
|
|
- } else {
|
|
|
- this._yaw = this._copy.rotation.y;
|
|
|
- this._pitch = this._copy.rotation.x;
|
|
|
- this._roll = this._copy.rotation.z;
|
|
|
- this._quaternionRotationYPR();
|
|
|
- }
|
|
|
- this._quaternionToRotationMatrix();
|
|
|
+ const rotMatrix = Tmp.Matrix[0];
|
|
|
+ const tmpVertex = Tmp.Vector3[0];
|
|
|
+ const tmpRotated = Tmp.Vector3[1];
|
|
|
+ const pivotBackTranslation = Tmp.Vector3[2];
|
|
|
+ const scaledPivot = Tmp.Vector3[3];
|
|
|
+ copy.getRotationMatrix(rotMatrix);
|
|
|
|
|
|
- this._scaledPivot.x = this._copy.pivot.x * this._copy.scaling.x;
|
|
|
- this._scaledPivot.y = this._copy.pivot.y * this._copy.scaling.y;
|
|
|
- this._scaledPivot.z = this._copy.pivot.z * this._copy.scaling.z;
|
|
|
+ copy.pivot.multiplyToRef(copy.scaling, scaledPivot);
|
|
|
|
|
|
- if (this._copy.translateFromPivot) {
|
|
|
- this._pivotBackTranslation.copyFromFloats(0.0, 0.0, 0.0);
|
|
|
+ if (copy.translateFromPivot) {
|
|
|
+ pivotBackTranslation.setAll(0.0);
|
|
|
}
|
|
|
else {
|
|
|
- this._pivotBackTranslation.copyFrom(this._scaledPivot);
|
|
|
+ pivotBackTranslation.copyFrom(scaledPivot);
|
|
|
}
|
|
|
|
|
|
for (i = 0; i < shape.length; i++) {
|
|
|
- this._vertex.x = shape[i].x;
|
|
|
- this._vertex.y = shape[i].y;
|
|
|
- this._vertex.z = shape[i].z;
|
|
|
-
|
|
|
+ tmpVertex.copyFrom(shape[i]);
|
|
|
if (options && options.vertexFunction) {
|
|
|
- options.vertexFunction(this._copy, this._vertex, i);
|
|
|
+ options.vertexFunction(copy, tmpVertex, i);
|
|
|
}
|
|
|
|
|
|
- this._vertex.x *= this._copy.scaling.x;
|
|
|
- this._vertex.y *= this._copy.scaling.y;
|
|
|
- this._vertex.z *= this._copy.scaling.z;
|
|
|
-
|
|
|
- this._vertex.x -= this._scaledPivot.x;
|
|
|
- this._vertex.y -= this._scaledPivot.y;
|
|
|
- this._vertex.z -= this._scaledPivot.z;
|
|
|
-
|
|
|
- Vector3.TransformCoordinatesToRef(this._vertex, this._rotMatrix, this._rotated);
|
|
|
-
|
|
|
- this._rotated.addInPlace(this._pivotBackTranslation);
|
|
|
- positions.push(this._copy.position.x + this._rotated.x, this._copy.position.y + this._rotated.y, this._copy.position.z + this._rotated.z);
|
|
|
+ tmpVertex.multiplyInPlace(copy.scaling).subtractInPlace(scaledPivot);
|
|
|
+ Vector3.TransformCoordinatesToRef(tmpVertex, rotMatrix, tmpRotated);
|
|
|
+ tmpRotated.addInPlace(pivotBackTranslation).addInPlace(copy.position);
|
|
|
+ positions.push(tmpRotated.x, tmpRotated.y, tmpRotated.z);
|
|
|
if (meshUV) {
|
|
|
- uvs.push((this._copy.uvs.z - this._copy.uvs.x) * meshUV[u] + this._copy.uvs.x, (this._copy.uvs.w - this._copy.uvs.y) * meshUV[u + 1] + this._copy.uvs.y);
|
|
|
+ const copyUvs = copy.uvs;
|
|
|
+ uvs.push((copyUvs.z - copyUvs.x) * meshUV[u] + copyUvs.x, (copyUvs.w - copyUvs.y) * meshUV[u + 1] + copyUvs.y);
|
|
|
u += 2;
|
|
|
}
|
|
|
|
|
|
- if (this._copy.color) {
|
|
|
- this._color = this._copy.color;
|
|
|
- } else if (meshCol && meshCol[c] !== undefined) {
|
|
|
- this._color.r = meshCol[c];
|
|
|
- this._color.g = meshCol[c + 1];
|
|
|
- this._color.b = meshCol[c + 2];
|
|
|
- this._color.a = meshCol[c + 3];
|
|
|
+ if (copy.color) {
|
|
|
+ this._color = copy.color;
|
|
|
} else {
|
|
|
- this._color.r = 1.0;
|
|
|
- this._color.g = 1.0;
|
|
|
- this._color.b = 1.0;
|
|
|
- this._color.a = 1.0;
|
|
|
+ const color = this._color;
|
|
|
+ if (meshCol && meshCol[c] !== undefined) {
|
|
|
+ color.r = meshCol[c];
|
|
|
+ color.g = meshCol[c + 1];
|
|
|
+ color.b = meshCol[c + 2];
|
|
|
+ color.a = meshCol[c + 3];
|
|
|
+ } else {
|
|
|
+ color.r = 1.0;
|
|
|
+ color.g = 1.0;
|
|
|
+ color.b = 1.0;
|
|
|
+ color.a = 1.0;
|
|
|
+ }
|
|
|
}
|
|
|
colors.push(this._color.r, this._color.g, this._color.b, this._color.a);
|
|
|
c += 4;
|
|
|
|
|
|
if (!this.recomputeNormals && meshNor) {
|
|
|
- this._normal.x = meshNor[n];
|
|
|
- this._normal.y = meshNor[n + 1];
|
|
|
- this._normal.z = meshNor[n + 2];
|
|
|
- Vector3.TransformNormalToRef(this._normal, this._rotMatrix, this._normal);
|
|
|
- normals.push(this._normal.x, this._normal.y, this._normal.z);
|
|
|
+ tmpVertex.x = meshNor[n];
|
|
|
+ tmpVertex.y = meshNor[n + 1];
|
|
|
+ tmpVertex.z = meshNor[n + 2];
|
|
|
+ Vector3.TransformNormalToRef(tmpVertex, rotMatrix, tmpVertex);
|
|
|
+ normals.push(tmpVertex.x, tmpVertex.y, tmpVertex.z);
|
|
|
n += 3;
|
|
|
}
|
|
|
|
|
@@ -489,14 +425,14 @@ module BABYLON {
|
|
|
this.depthSortedParticles.push(new DepthSortedParticle());
|
|
|
}
|
|
|
|
|
|
- return this._copy;
|
|
|
+ return copy;
|
|
|
}
|
|
|
|
|
|
// returns a shape array from positions array
|
|
|
private _posToShape(positions: number[] | Float32Array): Vector3[] {
|
|
|
var shape = [];
|
|
|
for (var i = 0; i < positions.length; i += 3) {
|
|
|
- shape.push(new Vector3(positions[i], positions[i + 1], positions[i + 2]));
|
|
|
+ shape.push(Vector3.FromArray(positions, i));
|
|
|
}
|
|
|
return shape;
|
|
|
}
|
|
@@ -506,7 +442,7 @@ module BABYLON {
|
|
|
var shapeUV = [];
|
|
|
if (uvs) {
|
|
|
for (var i = 0; i < uvs.length; i++) {
|
|
|
- shapeUV.push(uvs[i]);
|
|
|
+ shapeUV.push(uvs[i]);
|
|
|
}
|
|
|
}
|
|
|
return shapeUV;
|
|
@@ -579,73 +515,46 @@ module BABYLON {
|
|
|
// rebuilds a particle back to its just built status : if needed, recomputes the custom positions and vertices
|
|
|
private _rebuildParticle(particle: SolidParticle): void {
|
|
|
this._resetCopy();
|
|
|
+ const copy = this._copy;
|
|
|
if (particle._model._positionFunction) { // recall to stored custom positionFunction
|
|
|
- particle._model._positionFunction(this._copy, particle.idx, particle.idxInShape);
|
|
|
+ particle._model._positionFunction(copy, particle.idx, particle.idxInShape);
|
|
|
}
|
|
|
|
|
|
- if (this._copy.rotationQuaternion) {
|
|
|
- this._quaternion.copyFrom(this._copy.rotationQuaternion);
|
|
|
- } else {
|
|
|
- this._yaw = this._copy.rotation.y;
|
|
|
- this._pitch = this._copy.rotation.x;
|
|
|
- this._roll = this._copy.rotation.z;
|
|
|
- this._quaternionRotationYPR();
|
|
|
- }
|
|
|
- this._quaternionToRotationMatrix();
|
|
|
+ const rotMatrix = Tmp.Matrix[0];
|
|
|
+ const tmpVertex = Tmp.Vector3[0];
|
|
|
+ const tmpRotated = Tmp.Vector3[1];
|
|
|
+ const pivotBackTranslation = Tmp.Vector3[2];
|
|
|
+ const scaledPivot = Tmp.Vector3[3];
|
|
|
+
|
|
|
+ copy.getRotationMatrix(rotMatrix);
|
|
|
|
|
|
- this._scaledPivot.x = this._particle.pivot.x * this._particle.scaling.x;
|
|
|
- this._scaledPivot.y = this._particle.pivot.y * this._particle.scaling.y;
|
|
|
- this._scaledPivot.z = this._particle.pivot.z * this._particle.scaling.z;
|
|
|
+ particle.pivot.multiplyToRef(particle.scaling, scaledPivot);
|
|
|
|
|
|
- if (this._copy.translateFromPivot) {
|
|
|
- this._pivotBackTranslation.copyFromFloats(0.0, 0.0, 0.0);
|
|
|
+ if (copy.translateFromPivot) {
|
|
|
+ pivotBackTranslation.copyFromFloats(0.0, 0.0, 0.0);
|
|
|
}
|
|
|
else {
|
|
|
- this._pivotBackTranslation.copyFrom(this._scaledPivot);
|
|
|
+ pivotBackTranslation.copyFrom(scaledPivot);
|
|
|
}
|
|
|
|
|
|
- this._shape = particle._model._shape;
|
|
|
- for (var pt = 0; pt < this._shape.length; pt++) {
|
|
|
- this._vertex.x = this._shape[pt].x;
|
|
|
- this._vertex.y = this._shape[pt].y;
|
|
|
- this._vertex.z = this._shape[pt].z;
|
|
|
+ const shape = particle._model._shape;
|
|
|
|
|
|
+ for (var pt = 0; pt < shape.length; pt++) {
|
|
|
+ tmpVertex.copyFrom(shape[pt]);
|
|
|
if (particle._model._vertexFunction) {
|
|
|
- particle._model._vertexFunction(this._copy, this._vertex, pt); // recall to stored vertexFunction
|
|
|
+ particle._model._vertexFunction(copy, tmpVertex, pt); // recall to stored vertexFunction
|
|
|
}
|
|
|
|
|
|
- this._vertex.x *= this._copy.scaling.x;
|
|
|
- this._vertex.y *= this._copy.scaling.y;
|
|
|
- this._vertex.z *= this._copy.scaling.z;
|
|
|
-
|
|
|
- this._vertex.x -= this._scaledPivot.x;
|
|
|
- this._vertex.y -= this._scaledPivot.y;
|
|
|
- this._vertex.z -= this._scaledPivot.z;
|
|
|
-
|
|
|
- Vector3.TransformCoordinatesToRef(this._vertex, this._rotMatrix, this._rotated);
|
|
|
- this._rotated.addInPlace(this._pivotBackTranslation);
|
|
|
-
|
|
|
- this._positions32[particle._pos + pt * 3] = this._copy.position.x + this._rotated.x;
|
|
|
- this._positions32[particle._pos + pt * 3 + 1] = this._copy.position.y + this._rotated.y;
|
|
|
- this._positions32[particle._pos + pt * 3 + 2] = this._copy.position.z + this._rotated.z;
|
|
|
+ tmpVertex.multiplyInPlace(copy.scaling).subtractInPlace(scaledPivot);
|
|
|
+ Vector3.TransformCoordinatesToRef(tmpVertex, rotMatrix, tmpRotated);
|
|
|
+ tmpRotated.addInPlace(pivotBackTranslation).addInPlace(copy.position).toArray(this._positions32, particle._pos + pt * 3);
|
|
|
}
|
|
|
- particle.position.x = 0.0;
|
|
|
- particle.position.y = 0.0;
|
|
|
- particle.position.z = 0.0;
|
|
|
- particle.rotation.x = 0.0;
|
|
|
- particle.rotation.y = 0.0;
|
|
|
- particle.rotation.z = 0.0;
|
|
|
+ particle.position.setAll(0.0);
|
|
|
+ particle.rotation.setAll(0.0);
|
|
|
particle.rotationQuaternion = null;
|
|
|
- particle.scaling.x = 1.0;
|
|
|
- particle.scaling.y = 1.0;
|
|
|
- particle.scaling.z = 1.0;
|
|
|
- particle.uvs.x = 0.0;
|
|
|
- particle.uvs.y = 0.0;
|
|
|
- particle.uvs.z = 1.0;
|
|
|
- particle.uvs.w = 1.0;
|
|
|
- particle.pivot.x = 0.0;
|
|
|
- particle.pivot.y = 0.0;
|
|
|
- particle.pivot.z = 0.0;
|
|
|
+ particle.scaling.setAll(1.0);
|
|
|
+ particle.uvs.setAll(0.0);
|
|
|
+ particle.pivot.setAll(0.0);
|
|
|
particle.translateFromPivot = false;
|
|
|
particle.parentId = null;
|
|
|
}
|
|
@@ -679,43 +588,51 @@ module BABYLON {
|
|
|
// custom beforeUpdate
|
|
|
this.beforeUpdateParticles(start, end, update);
|
|
|
|
|
|
- this._cam_axisX.x = 1.0;
|
|
|
- this._cam_axisX.y = 0.0;
|
|
|
- this._cam_axisX.z = 0.0;
|
|
|
-
|
|
|
- this._cam_axisY.x = 0.0;
|
|
|
- this._cam_axisY.y = 1.0;
|
|
|
- this._cam_axisY.z = 0.0;
|
|
|
-
|
|
|
- this._cam_axisZ.x = 0.0;
|
|
|
- this._cam_axisZ.y = 0.0;
|
|
|
- this._cam_axisZ.z = 1.0;
|
|
|
+ const rotMatrix = Tmp.Matrix[0];
|
|
|
+ const invertedMatrix = Tmp.Matrix[1];
|
|
|
+ const mesh = this.mesh;
|
|
|
+ const colors32 = this._colors32;
|
|
|
+ const positions32 = this._positions32;
|
|
|
+ const normals32 = this._normals32;
|
|
|
+ const uvs32 = this._uvs32;
|
|
|
+ const indices32 = this._indices32;
|
|
|
+ const indices = this._indices;
|
|
|
+ const fixedNormal32 = this._fixedNormal32;
|
|
|
+
|
|
|
+ const tempVectors = Tmp.Vector3;
|
|
|
+ const camAxisX = tempVectors[5].copyFromFloats(1.0, 0.0, 0.0);
|
|
|
+ const camAxisY = tempVectors[6].copyFromFloats(0.0, 1.0, 0.0);
|
|
|
+ const camAxisZ = tempVectors[7].copyFromFloats(0.0, 0.0, 1.0);
|
|
|
+ const minimum = tempVectors[8].setAll(Number.MAX_VALUE);
|
|
|
+ const maximum = tempVectors[9].setAll(-Number.MAX_VALUE);
|
|
|
+ const camInvertedPosition = tempVectors[10].setAll(0);
|
|
|
|
|
|
// cases when the World Matrix is to be computed first
|
|
|
if (this.billboard || this._depthSort) {
|
|
|
this.mesh.computeWorldMatrix(true);
|
|
|
- this.mesh._worldMatrix.invertToRef(this._invertMatrix);
|
|
|
+ this.mesh._worldMatrix.invertToRef(invertedMatrix);
|
|
|
}
|
|
|
// if the particles will always face the camera
|
|
|
if (this.billboard) {
|
|
|
// compute the camera position and un-rotate it by the current mesh rotation
|
|
|
- this._camera.getDirectionToRef(this._axisZ, this._camDir);
|
|
|
- Vector3.TransformNormalToRef(this._camDir, this._invertMatrix, this._cam_axisZ);
|
|
|
- this._cam_axisZ.normalize();
|
|
|
+ const tmpVertex = tempVectors[0];
|
|
|
+ this._camera.getDirectionToRef(Axis.Z, tmpVertex);
|
|
|
+ Vector3.TransformNormalToRef(tmpVertex, invertedMatrix, camAxisZ);
|
|
|
+ camAxisZ.normalize();
|
|
|
// same for camera up vector extracted from the cam view matrix
|
|
|
var view = this._camera.getViewMatrix(true);
|
|
|
- Vector3.TransformNormalFromFloatsToRef(view.m[1], view.m[5], view.m[9], this._invertMatrix, this._cam_axisY);
|
|
|
- Vector3.CrossToRef(this._cam_axisY, this._cam_axisZ, this._cam_axisX);
|
|
|
- this._cam_axisY.normalize();
|
|
|
- this._cam_axisX.normalize();
|
|
|
+ Vector3.TransformNormalFromFloatsToRef(view.m[1], view.m[5], view.m[9], invertedMatrix, camAxisY);
|
|
|
+ Vector3.CrossToRef(camAxisY, camAxisZ, camAxisX);
|
|
|
+ camAxisY.normalize();
|
|
|
+ camAxisX.normalize();
|
|
|
}
|
|
|
|
|
|
// if depthSort, compute the camera global position in the mesh local system
|
|
|
if (this._depthSort) {
|
|
|
- Vector3.TransformCoordinatesToRef(this._camera.globalPosition, this._invertMatrix, this._camInvertedPosition); // then un-rotate the camera
|
|
|
+ Vector3.TransformCoordinatesToRef(this._camera.globalPosition, invertedMatrix, camInvertedPosition); // then un-rotate the camera
|
|
|
}
|
|
|
|
|
|
- Matrix.IdentityToRef(this._rotMatrix);
|
|
|
+ Matrix.IdentityToRef(rotMatrix);
|
|
|
var idx = 0; // current position index in the global array positions32
|
|
|
var index = 0; // position start index in the global array positions32 of the current particle
|
|
|
var colidx = 0; // current color index in the global array colors32
|
|
@@ -730,267 +647,252 @@ module BABYLON {
|
|
|
|
|
|
end = (end >= this.nbParticles) ? this.nbParticles - 1 : end;
|
|
|
if (this._computeBoundingBox) {
|
|
|
- if (start == 0 && end == this.nbParticles - 1) { // all the particles are updated, then recompute the BBox from scratch
|
|
|
- Vector3.FromFloatsToRef(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, this._minimum);
|
|
|
- Vector3.FromFloatsToRef(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE, this._maximum);
|
|
|
- }
|
|
|
- else { // only some particles are updated, then use the current existing BBox basis. Note : it can only increase.
|
|
|
- if (this.mesh._boundingInfo) {
|
|
|
- this._minimum.copyFrom(this.mesh._boundingInfo.boundingBox.minimum);
|
|
|
- this._maximum.copyFrom(this.mesh._boundingInfo.boundingBox.maximum);
|
|
|
+ if (start != 0 || end != this.nbParticles - 1) { // only some particles are updated, then use the current existing BBox basis. Note : it can only increase.
|
|
|
+ const boundingInfo = this.mesh._boundingInfo;
|
|
|
+ if (boundingInfo) {
|
|
|
+ minimum.copyFrom(boundingInfo.minimum);
|
|
|
+ maximum.copyFrom(boundingInfo.maximum);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// particle loop
|
|
|
index = this.particles[start]._pos;
|
|
|
- var vpos = (index / 3) | 0;
|
|
|
+ const vpos = (index / 3) | 0;
|
|
|
colorIndex = vpos * 4;
|
|
|
uvIndex = vpos * 2;
|
|
|
+
|
|
|
for (var p = start; p <= end; p++) {
|
|
|
- this._particle = this.particles[p];
|
|
|
- this._shape = this._particle._model._shape;
|
|
|
- this._shapeUV = this._particle._model._shapeUV;
|
|
|
+ const particle = this.particles[p];
|
|
|
|
|
|
// call to custom user function to update the particle properties
|
|
|
- this.updateParticle(this._particle);
|
|
|
+ this.updateParticle(particle);
|
|
|
+
|
|
|
+ const shape = particle._model._shape;
|
|
|
+ const shapeUV = particle._model._shapeUV;
|
|
|
+ const particleRotationMatrix = particle._rotationMatrix;
|
|
|
+ const particlePosition = particle.position;
|
|
|
+ const particleRotation = particle.rotation;
|
|
|
+ const particleScaling = particle.scaling;
|
|
|
+ const particleGlobalPosition = particle._globalPosition;
|
|
|
|
|
|
// camera-particle distance for depth sorting
|
|
|
if (this._depthSort && this._depthSortParticles) {
|
|
|
var dsp = this.depthSortedParticles[p];
|
|
|
- dsp.ind = this._particle._ind;
|
|
|
- dsp.indicesLength = this._particle._model._indicesLength;
|
|
|
- dsp.sqDistance = Vector3.DistanceSquared(this._particle.position, this._camInvertedPosition);
|
|
|
+ dsp.ind = particle._ind;
|
|
|
+ dsp.indicesLength = particle._model._indicesLength;
|
|
|
+ dsp.sqDistance = Vector3.DistanceSquared(particle.position, camInvertedPosition);
|
|
|
}
|
|
|
|
|
|
// skip the computations for inactive or already invisible particles
|
|
|
- if (!this._particle.alive || (this._particle._stillInvisible && !this._particle.isVisible)) {
|
|
|
+ if (!particle.alive || (particle._stillInvisible && !particle.isVisible)) {
|
|
|
// increment indexes for the next particle
|
|
|
- pt = this._shape.length;
|
|
|
+ pt = shape.length;
|
|
|
index += pt * 3;
|
|
|
colorIndex += pt * 4;
|
|
|
uvIndex += pt * 2;
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- if (this._particle.isVisible) {
|
|
|
- this._particle._stillInvisible = false; // un-mark permanent invisibility
|
|
|
- this._particleHasParent = (this._particle.parentId !== null);
|
|
|
+ if (particle.isVisible) {
|
|
|
+ particle._stillInvisible = false; // un-mark permanent invisibility
|
|
|
|
|
|
- this._scaledPivot.x = this._particle.pivot.x * this._particle.scaling.x;
|
|
|
- this._scaledPivot.y = this._particle.pivot.y * this._particle.scaling.y;
|
|
|
- this._scaledPivot.z = this._particle.pivot.z * this._particle.scaling.z;
|
|
|
+ const scaledPivot = tempVectors[12];
|
|
|
+ particle.pivot.multiplyToRef(particleScaling, scaledPivot);
|
|
|
|
|
|
// particle rotation matrix
|
|
|
if (this.billboard) {
|
|
|
- this._particle.rotation.x = 0.0;
|
|
|
- this._particle.rotation.y = 0.0;
|
|
|
+ particleRotation.x = 0.0;
|
|
|
+ particleRotation.y = 0.0;
|
|
|
}
|
|
|
if (this._computeParticleRotation || this.billboard) {
|
|
|
- if (this._particle.rotationQuaternion) {
|
|
|
- this._quaternion.copyFrom(this._particle.rotationQuaternion);
|
|
|
- } else {
|
|
|
- this._yaw = this._particle.rotation.y;
|
|
|
- this._pitch = this._particle.rotation.x;
|
|
|
- this._roll = this._particle.rotation.z;
|
|
|
- this._quaternionRotationYPR();
|
|
|
- }
|
|
|
- this._quaternionToRotationMatrix();
|
|
|
+ particle.getRotationMatrix(rotMatrix);
|
|
|
}
|
|
|
|
|
|
- if (this._particleHasParent) {
|
|
|
- this._parent = this.particles[this._particle.parentId!];
|
|
|
- this._rotated.x = this._particle.position.x * this._parent._rotationMatrix[0] + this._particle.position.y * this._parent._rotationMatrix[3] + this._particle.position.z * this._parent._rotationMatrix[6];
|
|
|
- this._rotated.y = this._particle.position.x * this._parent._rotationMatrix[1] + this._particle.position.y * this._parent._rotationMatrix[4] + this._particle.position.z * this._parent._rotationMatrix[7];
|
|
|
- this._rotated.z = this._particle.position.x * this._parent._rotationMatrix[2] + this._particle.position.y * this._parent._rotationMatrix[5] + this._particle.position.z * this._parent._rotationMatrix[8];
|
|
|
+ const particleHasParent = (particle.parentId !== null);
|
|
|
+ if (particleHasParent) {
|
|
|
+ const parent = this.particles[particle.parentId!];
|
|
|
+ const parentRotationMatrix = parent._rotationMatrix;
|
|
|
+ const parentGlobalPosition = parent._globalPosition;
|
|
|
|
|
|
- this._particle._globalPosition.x = this._parent._globalPosition.x + this._rotated.x;
|
|
|
- this._particle._globalPosition.y = this._parent._globalPosition.y + this._rotated.y;
|
|
|
- this._particle._globalPosition.z = this._parent._globalPosition.z + this._rotated.z;
|
|
|
+ const rotatedY = particlePosition.x * parentRotationMatrix[1] + particlePosition.y * parentRotationMatrix[4] + particlePosition.z * parentRotationMatrix[7];
|
|
|
+ const rotatedX = particlePosition.x * parentRotationMatrix[0] + particlePosition.y * parentRotationMatrix[3] + particlePosition.z * parentRotationMatrix[6];
|
|
|
+ const rotatedZ = particlePosition.x * parentRotationMatrix[2] + particlePosition.y * parentRotationMatrix[5] + particlePosition.z * parentRotationMatrix[8];
|
|
|
+
|
|
|
+ particleGlobalPosition.x = parentGlobalPosition.x + rotatedX;
|
|
|
+ particleGlobalPosition.y = parentGlobalPosition.y + rotatedY;
|
|
|
+ particleGlobalPosition.z = parentGlobalPosition.z + rotatedZ;
|
|
|
|
|
|
if (this._computeParticleRotation || this.billboard) {
|
|
|
- this._particle._rotationMatrix[0] = this._rotMatrix.m[0] * this._parent._rotationMatrix[0] + this._rotMatrix.m[1] * this._parent._rotationMatrix[3] + this._rotMatrix.m[2] * this._parent._rotationMatrix[6];
|
|
|
- this._particle._rotationMatrix[1] = this._rotMatrix.m[0] * this._parent._rotationMatrix[1] + this._rotMatrix.m[1] * this._parent._rotationMatrix[4] + this._rotMatrix.m[2] * this._parent._rotationMatrix[7];
|
|
|
- this._particle._rotationMatrix[2] = this._rotMatrix.m[0] * this._parent._rotationMatrix[2] + this._rotMatrix.m[1] * this._parent._rotationMatrix[5] + this._rotMatrix.m[2] * this._parent._rotationMatrix[8];
|
|
|
- this._particle._rotationMatrix[3] = this._rotMatrix.m[4] * this._parent._rotationMatrix[0] + this._rotMatrix.m[5] * this._parent._rotationMatrix[3] + this._rotMatrix.m[6] * this._parent._rotationMatrix[6];
|
|
|
- this._particle._rotationMatrix[4] = this._rotMatrix.m[4] * this._parent._rotationMatrix[1] + this._rotMatrix.m[5] * this._parent._rotationMatrix[4] + this._rotMatrix.m[6] * this._parent._rotationMatrix[7];
|
|
|
- this._particle._rotationMatrix[5] = this._rotMatrix.m[4] * this._parent._rotationMatrix[2] + this._rotMatrix.m[5] * this._parent._rotationMatrix[5] + this._rotMatrix.m[6] * this._parent._rotationMatrix[8];
|
|
|
- this._particle._rotationMatrix[6] = this._rotMatrix.m[8] * this._parent._rotationMatrix[0] + this._rotMatrix.m[9] * this._parent._rotationMatrix[3] + this._rotMatrix.m[10] * this._parent._rotationMatrix[6];
|
|
|
- this._particle._rotationMatrix[7] = this._rotMatrix.m[8] * this._parent._rotationMatrix[1] + this._rotMatrix.m[9] * this._parent._rotationMatrix[4] + this._rotMatrix.m[10] * this._parent._rotationMatrix[7];
|
|
|
- this._particle._rotationMatrix[8] = this._rotMatrix.m[8] * this._parent._rotationMatrix[2] + this._rotMatrix.m[9] * this._parent._rotationMatrix[5] + this._rotMatrix.m[10] * this._parent._rotationMatrix[8];
|
|
|
+ const rotMatrixValues = rotMatrix.m;
|
|
|
+ particleRotationMatrix[0] = rotMatrixValues[0] * parentRotationMatrix[0] + rotMatrixValues[1] * parentRotationMatrix[3] + rotMatrixValues[2] * parentRotationMatrix[6];
|
|
|
+ particleRotationMatrix[1] = rotMatrixValues[0] * parentRotationMatrix[1] + rotMatrixValues[1] * parentRotationMatrix[4] + rotMatrixValues[2] * parentRotationMatrix[7];
|
|
|
+ particleRotationMatrix[2] = rotMatrixValues[0] * parentRotationMatrix[2] + rotMatrixValues[1] * parentRotationMatrix[5] + rotMatrixValues[2] * parentRotationMatrix[8];
|
|
|
+ particleRotationMatrix[3] = rotMatrixValues[4] * parentRotationMatrix[0] + rotMatrixValues[5] * parentRotationMatrix[3] + rotMatrixValues[6] * parentRotationMatrix[6];
|
|
|
+ particleRotationMatrix[4] = rotMatrixValues[4] * parentRotationMatrix[1] + rotMatrixValues[5] * parentRotationMatrix[4] + rotMatrixValues[6] * parentRotationMatrix[7];
|
|
|
+ particleRotationMatrix[5] = rotMatrixValues[4] * parentRotationMatrix[2] + rotMatrixValues[5] * parentRotationMatrix[5] + rotMatrixValues[6] * parentRotationMatrix[8];
|
|
|
+ particleRotationMatrix[6] = rotMatrixValues[8] * parentRotationMatrix[0] + rotMatrixValues[9] * parentRotationMatrix[3] + rotMatrixValues[10] * parentRotationMatrix[6];
|
|
|
+ particleRotationMatrix[7] = rotMatrixValues[8] * parentRotationMatrix[1] + rotMatrixValues[9] * parentRotationMatrix[4] + rotMatrixValues[10] * parentRotationMatrix[7];
|
|
|
+ particleRotationMatrix[8] = rotMatrixValues[8] * parentRotationMatrix[2] + rotMatrixValues[9] * parentRotationMatrix[5] + rotMatrixValues[10] * parentRotationMatrix[8];
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
- this._particle._globalPosition.x = this._particle.position.x;
|
|
|
- this._particle._globalPosition.y = this._particle.position.y;
|
|
|
- this._particle._globalPosition.z = this._particle.position.z;
|
|
|
+ particleGlobalPosition.x = particlePosition.x;
|
|
|
+ particleGlobalPosition.y = particlePosition.y;
|
|
|
+ particleGlobalPosition.z = particlePosition.z;
|
|
|
|
|
|
if (this._computeParticleRotation || this.billboard) {
|
|
|
- this._particle._rotationMatrix[0] = this._rotMatrix.m[0];
|
|
|
- this._particle._rotationMatrix[1] = this._rotMatrix.m[1];
|
|
|
- this._particle._rotationMatrix[2] = this._rotMatrix.m[2];
|
|
|
- this._particle._rotationMatrix[3] = this._rotMatrix.m[4];
|
|
|
- this._particle._rotationMatrix[4] = this._rotMatrix.m[5];
|
|
|
- this._particle._rotationMatrix[5] = this._rotMatrix.m[6];
|
|
|
- this._particle._rotationMatrix[6] = this._rotMatrix.m[8];
|
|
|
- this._particle._rotationMatrix[7] = this._rotMatrix.m[9];
|
|
|
- this._particle._rotationMatrix[8] = this._rotMatrix.m[10];
|
|
|
+ const rotMatrixValues = rotMatrix.m;
|
|
|
+ particleRotationMatrix[0] = rotMatrixValues[0];
|
|
|
+ particleRotationMatrix[1] = rotMatrixValues[1];
|
|
|
+ particleRotationMatrix[2] = rotMatrixValues[2];
|
|
|
+ particleRotationMatrix[3] = rotMatrixValues[4];
|
|
|
+ particleRotationMatrix[4] = rotMatrixValues[5];
|
|
|
+ particleRotationMatrix[5] = rotMatrixValues[6];
|
|
|
+ particleRotationMatrix[6] = rotMatrixValues[8];
|
|
|
+ particleRotationMatrix[7] = rotMatrixValues[9];
|
|
|
+ particleRotationMatrix[8] = rotMatrixValues[10];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (this._particle.translateFromPivot) {
|
|
|
- this._pivotBackTranslation.x = 0.0;
|
|
|
- this._pivotBackTranslation.y = 0.0;
|
|
|
- this._pivotBackTranslation.z = 0.0;
|
|
|
+ const pivotBackTranslation = tempVectors[11];
|
|
|
+ if (particle.translateFromPivot) {
|
|
|
+ pivotBackTranslation.setAll(0.0);
|
|
|
}
|
|
|
else {
|
|
|
- this._pivotBackTranslation.x = this._scaledPivot.x;
|
|
|
- this._pivotBackTranslation.y = this._scaledPivot.y;
|
|
|
- this._pivotBackTranslation.z = this._scaledPivot.z;
|
|
|
+ pivotBackTranslation.copyFrom(scaledPivot);
|
|
|
}
|
|
|
+
|
|
|
// particle vertex loop
|
|
|
- for (pt = 0; pt < this._shape.length; pt++) {
|
|
|
+ for (pt = 0; pt < shape.length; pt++) {
|
|
|
idx = index + pt * 3;
|
|
|
colidx = colorIndex + pt * 4;
|
|
|
uvidx = uvIndex + pt * 2;
|
|
|
|
|
|
- this._vertex.x = this._shape[pt].x;
|
|
|
- this._vertex.y = this._shape[pt].y;
|
|
|
- this._vertex.z = this._shape[pt].z;
|
|
|
-
|
|
|
+ const tmpVertex = tempVectors[0];
|
|
|
+ tmpVertex.copyFrom(shape[pt]);
|
|
|
if (this._computeParticleVertex) {
|
|
|
- this.updateParticleVertex(this._particle, this._vertex, pt);
|
|
|
+ this.updateParticleVertex(particle, tmpVertex, pt);
|
|
|
}
|
|
|
|
|
|
// positions
|
|
|
- this._vertex.x *= this._particle.scaling.x;
|
|
|
- this._vertex.y *= this._particle.scaling.y;
|
|
|
- this._vertex.z *= this._particle.scaling.z;
|
|
|
-
|
|
|
- this._vertex.x -= this._scaledPivot.x;
|
|
|
- this._vertex.y -= this._scaledPivot.y;
|
|
|
- this._vertex.z -= this._scaledPivot.z;
|
|
|
+ const vertexX = tmpVertex.x * particleScaling.x - scaledPivot.x;
|
|
|
+ const vertexY = tmpVertex.y * particleScaling.y - scaledPivot.y;
|
|
|
+ const vertexZ = tmpVertex.z * particleScaling.z - scaledPivot.z;
|
|
|
|
|
|
- this._rotated.x = this._vertex.x * this._particle._rotationMatrix[0] + this._vertex.y * this._particle._rotationMatrix[3] + this._vertex.z * this._particle._rotationMatrix[6];
|
|
|
- this._rotated.y = this._vertex.x * this._particle._rotationMatrix[1] + this._vertex.y * this._particle._rotationMatrix[4] + this._vertex.z * this._particle._rotationMatrix[7];
|
|
|
- this._rotated.z = this._vertex.x * this._particle._rotationMatrix[2] + this._vertex.y * this._particle._rotationMatrix[5] + this._vertex.z * this._particle._rotationMatrix[8];
|
|
|
+ let rotatedX = vertexX * particleRotationMatrix[0] + vertexY * particleRotationMatrix[3] + vertexZ * particleRotationMatrix[6];
|
|
|
+ let rotatedY = vertexX * particleRotationMatrix[1] + vertexY * particleRotationMatrix[4] + vertexZ * particleRotationMatrix[7];
|
|
|
+ let rotatedZ = vertexX * particleRotationMatrix[2] + vertexY * particleRotationMatrix[5] + vertexZ * particleRotationMatrix[8];
|
|
|
|
|
|
- this._rotated.x += this._pivotBackTranslation.x;
|
|
|
- this._rotated.y += this._pivotBackTranslation.y;
|
|
|
- this._rotated.z += this._pivotBackTranslation.z;
|
|
|
+ rotatedX += pivotBackTranslation.x;
|
|
|
+ rotatedY += pivotBackTranslation.y;
|
|
|
+ rotatedZ += pivotBackTranslation.z;
|
|
|
|
|
|
- this._positions32[idx] = this._particle._globalPosition.x + this._cam_axisX.x * this._rotated.x + this._cam_axisY.x * this._rotated.y + this._cam_axisZ.x * this._rotated.z;
|
|
|
- this._positions32[idx + 1] = this._particle._globalPosition.y + this._cam_axisX.y * this._rotated.x + this._cam_axisY.y * this._rotated.y + this._cam_axisZ.y * this._rotated.z;
|
|
|
- this._positions32[idx + 2] = this._particle._globalPosition.z + this._cam_axisX.z * this._rotated.x + this._cam_axisY.z * this._rotated.y + this._cam_axisZ.z * this._rotated.z;
|
|
|
+ const px = positions32[idx] = particleGlobalPosition.x + camAxisX.x * rotatedX + camAxisY.x * rotatedY + camAxisZ.x * rotatedZ;
|
|
|
+ const py = positions32[idx + 1] = particleGlobalPosition.y + camAxisX.y * rotatedX + camAxisY.y * rotatedY + camAxisZ.y * rotatedZ;
|
|
|
+ const pz = positions32[idx + 2] = particleGlobalPosition.z + camAxisX.z * rotatedX + camAxisY.z * rotatedY + camAxisZ.z * rotatedZ;
|
|
|
|
|
|
if (this._computeBoundingBox) {
|
|
|
- if (this._positions32[idx] < this._minimum.x) {
|
|
|
- this._minimum.x = this._positions32[idx];
|
|
|
- }
|
|
|
- if (this._positions32[idx] > this._maximum.x) {
|
|
|
- this._maximum.x = this._positions32[idx];
|
|
|
- }
|
|
|
- if (this._positions32[idx + 1] < this._minimum.y) {
|
|
|
- this._minimum.y = this._positions32[idx + 1];
|
|
|
- }
|
|
|
- if (this._positions32[idx + 1] > this._maximum.y) {
|
|
|
- this._maximum.y = this._positions32[idx + 1];
|
|
|
- }
|
|
|
- if (this._positions32[idx + 2] < this._minimum.z) {
|
|
|
- this._minimum.z = this._positions32[idx + 2];
|
|
|
- }
|
|
|
- if (this._positions32[idx + 2] > this._maximum.z) {
|
|
|
- this._maximum.z = this._positions32[idx + 2];
|
|
|
- }
|
|
|
+ minimum.minimizeInPlaceFromFloats(px, py, pz);
|
|
|
+ maximum.maximizeInPlaceFromFloats(px, py, pz);
|
|
|
}
|
|
|
|
|
|
// normals : if the particles can't be morphed then just rotate the normals, what is much more faster than ComputeNormals()
|
|
|
if (!this._computeParticleVertex) {
|
|
|
- this._normal.x = this._fixedNormal32[idx];
|
|
|
- this._normal.y = this._fixedNormal32[idx + 1];
|
|
|
- this._normal.z = this._fixedNormal32[idx + 2];
|
|
|
+ const normalx = fixedNormal32[idx];
|
|
|
+ const normaly = fixedNormal32[idx + 1];
|
|
|
+ const normalz = fixedNormal32[idx + 2];
|
|
|
|
|
|
- this._rotated.x = this._normal.x * this._particle._rotationMatrix[0] + this._normal.y * this._particle._rotationMatrix[3] + this._normal.z * this._particle._rotationMatrix[6];
|
|
|
- this._rotated.y = this._normal.x * this._particle._rotationMatrix[1] + this._normal.y * this._particle._rotationMatrix[4] + this._normal.z * this._particle._rotationMatrix[7];
|
|
|
- this._rotated.z = this._normal.x * this._particle._rotationMatrix[2] + this._normal.y * this._particle._rotationMatrix[5] + this._normal.z * this._particle._rotationMatrix[8];
|
|
|
+ const rotatedx = normalx * particleRotationMatrix[0] + normaly * particleRotationMatrix[3] + normalz * particleRotationMatrix[6];
|
|
|
+ const rotatedy = normalx * particleRotationMatrix[1] + normaly * particleRotationMatrix[4] + normalz * particleRotationMatrix[7];
|
|
|
+ const rotatedz = normalx * particleRotationMatrix[2] + normaly * particleRotationMatrix[5] + normalz * particleRotationMatrix[8];
|
|
|
|
|
|
- this._normals32[idx] = this._cam_axisX.x * this._rotated.x + this._cam_axisY.x * this._rotated.y + this._cam_axisZ.x * this._rotated.z;
|
|
|
- this._normals32[idx + 1] = this._cam_axisX.y * this._rotated.x + this._cam_axisY.y * this._rotated.y + this._cam_axisZ.y * this._rotated.z;
|
|
|
- this._normals32[idx + 2] = this._cam_axisX.z * this._rotated.x + this._cam_axisY.z * this._rotated.y + this._cam_axisZ.z * this._rotated.z;
|
|
|
+ normals32[idx] = camAxisX.x * rotatedx + camAxisY.x * rotatedy + camAxisZ.x * rotatedz;
|
|
|
+ normals32[idx + 1] = camAxisX.y * rotatedx + camAxisY.y * rotatedy + camAxisZ.y * rotatedz;
|
|
|
+ normals32[idx + 2] = camAxisX.z * rotatedx + camAxisY.z * rotatedy + camAxisZ.z * rotatedz;
|
|
|
}
|
|
|
|
|
|
- if (this._computeParticleColor && this._particle.color) {
|
|
|
- this._colors32[colidx] = this._particle.color.r;
|
|
|
- this._colors32[colidx + 1] = this._particle.color.g;
|
|
|
- this._colors32[colidx + 2] = this._particle.color.b;
|
|
|
- this._colors32[colidx + 3] = this._particle.color.a;
|
|
|
+ if (this._computeParticleColor && particle.color) {
|
|
|
+ const color = particle.color;
|
|
|
+ const colors32 = this._colors32;
|
|
|
+ colors32[colidx] = color.r;
|
|
|
+ colors32[colidx + 1] = color.g;
|
|
|
+ colors32[colidx + 2] = color.b;
|
|
|
+ colors32[colidx + 3] = color.a;
|
|
|
}
|
|
|
|
|
|
if (this._computeParticleTexture) {
|
|
|
- this._uvs32[uvidx] = this._shapeUV[pt * 2] * (this._particle.uvs.z - this._particle.uvs.x) + this._particle.uvs.x;
|
|
|
- this._uvs32[uvidx + 1] = this._shapeUV[pt * 2 + 1] * (this._particle.uvs.w - this._particle.uvs.y) + this._particle.uvs.y;
|
|
|
+ const uvs = particle.uvs;
|
|
|
+ uvs32[uvidx] = shapeUV[pt * 2] * (uvs.z - uvs.x) + uvs.x;
|
|
|
+ uvs32[uvidx + 1] = shapeUV[pt * 2 + 1] * (uvs.w - uvs.y) + uvs.y;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
// particle just set invisible : scaled to zero and positioned at the origin
|
|
|
else {
|
|
|
- this._particle._stillInvisible = true; // mark the particle as invisible
|
|
|
- for (pt = 0; pt < this._shape.length; pt++) {
|
|
|
+ particle._stillInvisible = true; // mark the particle as invisible
|
|
|
+ for (pt = 0; pt < shape.length; pt++) {
|
|
|
idx = index + pt * 3;
|
|
|
colidx = colorIndex + pt * 4;
|
|
|
uvidx = uvIndex + pt * 2;
|
|
|
|
|
|
- this._positions32[idx] = 0.0;
|
|
|
- this._positions32[idx + 1] = 0.0;
|
|
|
- this._positions32[idx + 2] = 0.0;
|
|
|
- this._normals32[idx] = 0.0;
|
|
|
- this._normals32[idx + 1] = 0.0;
|
|
|
- this._normals32[idx + 2] = 0.0;
|
|
|
- if (this._computeParticleColor && this._particle.color) {
|
|
|
- this._colors32[colidx] = this._particle.color.r;
|
|
|
- this._colors32[colidx + 1] = this._particle.color.g;
|
|
|
- this._colors32[colidx + 2] = this._particle.color.b;
|
|
|
- this._colors32[colidx + 3] = this._particle.color.a;
|
|
|
+ positions32[idx] = positions32[idx + 1] = positions32[idx + 2] = 0;
|
|
|
+ normals32[idx] = normals32[idx + 1] = normals32[idx + 2] = 0;
|
|
|
+ if (this._computeParticleColor && particle.color) {
|
|
|
+ const color = particle.color;
|
|
|
+ colors32[colidx] = color.r;
|
|
|
+ colors32[colidx + 1] = color.g;
|
|
|
+ colors32[colidx + 2] = color.b;
|
|
|
+ colors32[colidx + 3] = color.a;
|
|
|
}
|
|
|
if (this._computeParticleTexture) {
|
|
|
- this._uvs32[uvidx] = this._shapeUV[pt * 2] * (this._particle.uvs.z - this._particle.uvs.x) + this._particle.uvs.x;
|
|
|
- this._uvs32[uvidx + 1] = this._shapeUV[pt * 2 + 1] * (this._particle.uvs.w - this._particle.uvs.y) + this._particle.uvs.y;
|
|
|
+ const uvs = particle.uvs;
|
|
|
+ uvs32[uvidx] = shapeUV[pt * 2] * (uvs.z - uvs.x) + uvs.x;
|
|
|
+ uvs32[uvidx + 1] = shapeUV[pt * 2 + 1] * (uvs.w - uvs.y) + uvs.y;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// if the particle intersections must be computed : update the bbInfo
|
|
|
if (this._particlesIntersect) {
|
|
|
- var bInfo = this._particle._boundingInfo;
|
|
|
- var bBox = bInfo.boundingBox;
|
|
|
- var bSphere = bInfo.boundingSphere;
|
|
|
+ const bInfo = particle._boundingInfo;
|
|
|
+ const bBox = bInfo.boundingBox;
|
|
|
+ const bSphere = bInfo.boundingSphere;
|
|
|
+ const modelBoundingInfo = particle._modelBoundingInfo;
|
|
|
if (!this._bSphereOnly) {
|
|
|
// place, scale and rotate the particle bbox within the SPS local system, then update it
|
|
|
- for (var b = 0; b < bBox.vectors.length; b++) {
|
|
|
- this._vertex.x = this._particle._modelBoundingInfo.boundingBox.vectors[b].x * this._particle.scaling.x;
|
|
|
- this._vertex.y = this._particle._modelBoundingInfo.boundingBox.vectors[b].y * this._particle.scaling.y;
|
|
|
- this._vertex.z = this._particle._modelBoundingInfo.boundingBox.vectors[b].z * this._particle.scaling.z;
|
|
|
- this._rotated.x = this._vertex.x * this._particle._rotationMatrix[0] + this._vertex.y * this._particle._rotationMatrix[3] + this._vertex.z * this._particle._rotationMatrix[6];
|
|
|
- this._rotated.y = this._vertex.x * this._particle._rotationMatrix[1] + this._vertex.y * this._particle._rotationMatrix[4] + this._vertex.z * this._particle._rotationMatrix[7];
|
|
|
- this._rotated.z = this._vertex.x * this._particle._rotationMatrix[2] + this._vertex.y * this._particle._rotationMatrix[5] + this._vertex.z * this._particle._rotationMatrix[8];
|
|
|
- bBox.vectors[b].x = this._particle.position.x + this._cam_axisX.x * this._rotated.x + this._cam_axisY.x * this._rotated.y + this._cam_axisZ.x * this._rotated.z;
|
|
|
- bBox.vectors[b].y = this._particle.position.y + this._cam_axisX.y * this._rotated.x + this._cam_axisY.y * this._rotated.y + this._cam_axisZ.y * this._rotated.z;
|
|
|
- bBox.vectors[b].z = this._particle.position.z + this._cam_axisX.z * this._rotated.x + this._cam_axisY.z * this._rotated.y + this._cam_axisZ.z * this._rotated.z;
|
|
|
+ const modelBoundingInfoVectors = modelBoundingInfo.boundingBox.vectors;
|
|
|
+
|
|
|
+ const tempMin = tempVectors[1];
|
|
|
+ const tempMax = tempVectors[2];
|
|
|
+ tempMin.setAll(Number.MAX_VALUE);
|
|
|
+ tempMax.setAll(-Number.MAX_VALUE);
|
|
|
+ for (var b = 0; b < 8; b++) {
|
|
|
+ const scaledX = modelBoundingInfoVectors[b].x * particleScaling.x;
|
|
|
+ const scaledY = modelBoundingInfoVectors[b].y * particleScaling.y;
|
|
|
+ const scaledZ = modelBoundingInfoVectors[b].z * particleScaling.z;
|
|
|
+ const rotatedX = scaledX * particleRotationMatrix[0] + scaledY * particleRotationMatrix[3] + scaledZ * particleRotationMatrix[6];
|
|
|
+ const rotatedY = scaledX * particleRotationMatrix[1] + scaledY * particleRotationMatrix[4] + scaledZ * particleRotationMatrix[7];
|
|
|
+ const rotatedZ = scaledX * particleRotationMatrix[2] + scaledY * particleRotationMatrix[5] + scaledZ * particleRotationMatrix[8];
|
|
|
+ const x = particlePosition.x + camAxisX.x * rotatedX + camAxisY.x * rotatedY + camAxisZ.x * rotatedZ;
|
|
|
+ const y = particlePosition.y + camAxisX.y * rotatedX + camAxisY.y * rotatedY + camAxisZ.y * rotatedZ;
|
|
|
+ const z = particlePosition.z + camAxisX.z * rotatedX + camAxisY.z * rotatedY + camAxisZ.z * rotatedZ;
|
|
|
+ tempMin.minimizeInPlaceFromFloats(x, y, z);
|
|
|
+ tempMax.maximizeInPlaceFromFloats(x, y, z);
|
|
|
}
|
|
|
- bBox._update(this.mesh._worldMatrix);
|
|
|
+
|
|
|
+ bBox.reConstruct(tempMin, tempMax, mesh._worldMatrix);
|
|
|
}
|
|
|
+
|
|
|
// place and scale the particle bouding sphere in the SPS local system, then update it
|
|
|
- this._minBbox.x = this._particle._modelBoundingInfo.minimum.x * this._particle.scaling.x;
|
|
|
- this._minBbox.y = this._particle._modelBoundingInfo.minimum.y * this._particle.scaling.y;
|
|
|
- this._minBbox.z = this._particle._modelBoundingInfo.minimum.z * this._particle.scaling.z;
|
|
|
- this._maxBbox.x = this._particle._modelBoundingInfo.maximum.x * this._particle.scaling.x;
|
|
|
- this._maxBbox.y = this._particle._modelBoundingInfo.maximum.y * this._particle.scaling.y;
|
|
|
- this._maxBbox.z = this._particle._modelBoundingInfo.maximum.z * this._particle.scaling.z;
|
|
|
- bSphere.center.x = this._particle._globalPosition.x + (this._minBbox.x + this._maxBbox.x) * 0.5;
|
|
|
- bSphere.center.y = this._particle._globalPosition.y + (this._minBbox.y + this._maxBbox.y) * 0.5;
|
|
|
- bSphere.center.z = this._particle._globalPosition.z + (this._minBbox.z + this._maxBbox.z) * 0.5;
|
|
|
- bSphere.radius = this._bSphereRadiusFactor * 0.5 * Math.sqrt((this._maxBbox.x - this._minBbox.x) * (this._maxBbox.x - this._minBbox.x) + (this._maxBbox.y - this._minBbox.y) * (this._maxBbox.y - this._minBbox.y) + (this._maxBbox.z - this._minBbox.z) * (this._maxBbox.z - this._minBbox.z));
|
|
|
- bSphere._update(this.mesh._worldMatrix);
|
|
|
+ const minBbox = modelBoundingInfo.minimum.multiplyToRef(particleScaling, tempVectors[1]);
|
|
|
+ const maxBbox = modelBoundingInfo.maximum.multiplyToRef(particleScaling, tempVectors[2]);
|
|
|
+
|
|
|
+ const bSphereCenter = maxBbox.addToRef(minBbox, tempVectors[3]).scaleInPlace(0.5);
|
|
|
+ const halfDiag = maxBbox.subtractToRef(minBbox, tempVectors[4]).scaleInPlace(0.5 * this._bSphereRadiusFactor);
|
|
|
+ const bSphereMinBbox = bSphereCenter.subtractToRef(halfDiag, tempVectors[1]);
|
|
|
+ const bSphereMaxBbox = bSphereCenter.addToRef(halfDiag, tempVectors[2]);
|
|
|
+ bSphere.reConstruct(bSphereMinBbox, bSphereMaxBbox, mesh._worldMatrix);
|
|
|
}
|
|
|
|
|
|
// increment indexes for the next particle
|
|
@@ -1002,86 +904,53 @@ module BABYLON {
|
|
|
// if the VBO must be updated
|
|
|
if (update) {
|
|
|
if (this._computeParticleColor) {
|
|
|
- this.mesh.updateVerticesData(VertexBuffer.ColorKind, this._colors32, false, false);
|
|
|
+ mesh.updateVerticesData(VertexBuffer.ColorKind, colors32, false, false);
|
|
|
}
|
|
|
if (this._computeParticleTexture) {
|
|
|
- this.mesh.updateVerticesData(VertexBuffer.UVKind, this._uvs32, false, false);
|
|
|
+ mesh.updateVerticesData(VertexBuffer.UVKind, uvs32, false, false);
|
|
|
}
|
|
|
- this.mesh.updateVerticesData(VertexBuffer.PositionKind, this._positions32, false, false);
|
|
|
- if (!this.mesh.areNormalsFrozen || this.mesh.isFacetDataEnabled) {
|
|
|
- if (this._computeParticleVertex || this.mesh.isFacetDataEnabled) {
|
|
|
+ mesh.updateVerticesData(VertexBuffer.PositionKind, positions32, false, false);
|
|
|
+ if (!mesh.areNormalsFrozen || mesh.isFacetDataEnabled) {
|
|
|
+ if (this._computeParticleVertex || mesh.isFacetDataEnabled) {
|
|
|
// recompute the normals only if the particles can be morphed, update then also the normal reference array _fixedNormal32[]
|
|
|
- var params = this.mesh.isFacetDataEnabled ? this.mesh.getFacetDataParameters() : null;
|
|
|
- VertexData.ComputeNormals(this._positions32, this._indices32, this._normals32, params);
|
|
|
- for (var i = 0; i < this._normals32.length; i++) {
|
|
|
- this._fixedNormal32[i] = this._normals32[i];
|
|
|
+ var params = mesh.isFacetDataEnabled ? mesh.getFacetDataParameters() : null;
|
|
|
+ VertexData.ComputeNormals(positions32, indices32, normals32, params);
|
|
|
+ for (var i = 0; i < normals32.length; i++) {
|
|
|
+ fixedNormal32[i] = normals32[i];
|
|
|
}
|
|
|
}
|
|
|
- if (!this.mesh.areNormalsFrozen) {
|
|
|
- this.mesh.updateVerticesData(VertexBuffer.NormalKind, this._normals32, false, false);
|
|
|
+ if (!mesh.areNormalsFrozen) {
|
|
|
+ mesh.updateVerticesData(VertexBuffer.NormalKind, normals32, false, false);
|
|
|
}
|
|
|
}
|
|
|
if (this._depthSort && this._depthSortParticles) {
|
|
|
- this.depthSortedParticles.sort(this._depthSortFunction);
|
|
|
- var dspl = this.depthSortedParticles.length;
|
|
|
- var sorted = 0;
|
|
|
- var lind = 0;
|
|
|
- var sind = 0;
|
|
|
- var sid = 0;
|
|
|
- for (sorted = 0; sorted < dspl; sorted++) {
|
|
|
- lind = this.depthSortedParticles[sorted].indicesLength;
|
|
|
- sind = this.depthSortedParticles[sorted].ind;
|
|
|
+ const depthSortedParticles = this.depthSortedParticles;
|
|
|
+ depthSortedParticles.sort(depthSortFunction);
|
|
|
+ const dspl = depthSortedParticles.length;
|
|
|
+ let sid = 0;
|
|
|
+ for (let sorted = 0; sorted < dspl; sorted++) {
|
|
|
+ const lind = depthSortedParticles[sorted].indicesLength;
|
|
|
+ const sind = depthSortedParticles[sorted].ind;
|
|
|
for (var i = 0; i < lind; i++) {
|
|
|
- this._indices32[sid] = this._indices[sind + i];
|
|
|
+ indices32[sid] = indices[sind + i];
|
|
|
sid++;
|
|
|
}
|
|
|
}
|
|
|
- this.mesh.updateIndices(this._indices32);
|
|
|
+ mesh.updateIndices(indices32);
|
|
|
}
|
|
|
}
|
|
|
if (this._computeBoundingBox) {
|
|
|
- this.mesh._boundingInfo = new BoundingInfo(this._minimum, this._maximum);
|
|
|
- this.mesh._boundingInfo.update(this.mesh._worldMatrix);
|
|
|
+ if (mesh._boundingInfo) {
|
|
|
+ mesh._boundingInfo.reConstruct(minimum, maximum, mesh._worldMatrix);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ mesh._boundingInfo = new BoundingInfo(minimum, maximum, mesh._worldMatrix);
|
|
|
+ }
|
|
|
}
|
|
|
this.afterUpdateParticles(start, end, update);
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
- private _quaternionRotationYPR(): void {
|
|
|
- this._halfroll = this._roll * 0.5;
|
|
|
- this._halfpitch = this._pitch * 0.5;
|
|
|
- this._halfyaw = this._yaw * 0.5;
|
|
|
- this._sinRoll = Math.sin(this._halfroll);
|
|
|
- this._cosRoll = Math.cos(this._halfroll);
|
|
|
- this._sinPitch = Math.sin(this._halfpitch);
|
|
|
- this._cosPitch = Math.cos(this._halfpitch);
|
|
|
- this._sinYaw = Math.sin(this._halfyaw);
|
|
|
- this._cosYaw = Math.cos(this._halfyaw);
|
|
|
- this._quaternion.x = this._cosYaw * this._sinPitch * this._cosRoll + this._sinYaw * this._cosPitch * this._sinRoll;
|
|
|
- this._quaternion.y = this._sinYaw * this._cosPitch * this._cosRoll - this._cosYaw * this._sinPitch * this._sinRoll;
|
|
|
- this._quaternion.z = this._cosYaw * this._cosPitch * this._sinRoll - this._sinYaw * this._sinPitch * this._cosRoll;
|
|
|
- this._quaternion.w = this._cosYaw * this._cosPitch * this._cosRoll + this._sinYaw * this._sinPitch * this._sinRoll;
|
|
|
- }
|
|
|
-
|
|
|
- private _quaternionToRotationMatrix(): void {
|
|
|
- this._rotMatrix.m[0] = 1.0 - (2.0 * (this._quaternion.y * this._quaternion.y + this._quaternion.z * this._quaternion.z));
|
|
|
- this._rotMatrix.m[1] = 2.0 * (this._quaternion.x * this._quaternion.y + this._quaternion.z * this._quaternion.w);
|
|
|
- this._rotMatrix.m[2] = 2.0 * (this._quaternion.z * this._quaternion.x - this._quaternion.y * this._quaternion.w);
|
|
|
- this._rotMatrix.m[3] = 0;
|
|
|
- this._rotMatrix.m[4] = 2.0 * (this._quaternion.x * this._quaternion.y - this._quaternion.z * this._quaternion.w);
|
|
|
- this._rotMatrix.m[5] = 1.0 - (2.0 * (this._quaternion.z * this._quaternion.z + this._quaternion.x * this._quaternion.x));
|
|
|
- this._rotMatrix.m[6] = 2.0 * (this._quaternion.y * this._quaternion.z + this._quaternion.x * this._quaternion.w);
|
|
|
- this._rotMatrix.m[7] = 0;
|
|
|
- this._rotMatrix.m[8] = 2.0 * (this._quaternion.z * this._quaternion.x + this._quaternion.y * this._quaternion.w);
|
|
|
- this._rotMatrix.m[9] = 2.0 * (this._quaternion.y * this._quaternion.z - this._quaternion.x * this._quaternion.w);
|
|
|
- this._rotMatrix.m[10] = 1.0 - (2.0 * (this._quaternion.y * this._quaternion.y + this._quaternion.x * this._quaternion.x));
|
|
|
- this._rotMatrix.m[11] = 0;
|
|
|
- this._rotMatrix.m[12] = 0;
|
|
|
- this._rotMatrix.m[13] = 0;
|
|
|
- this._rotMatrix.m[14] = 0;
|
|
|
- this._rotMatrix.m[15] = 1.0;
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* Disposes the SPS.
|
|
|
*/
|