|
@@ -1,968 +0,0 @@
|
|
|
-/**
|
|
|
-* @author Mark Kellogg - http://www.github.com/mkkellogg
|
|
|
-*/
|
|
|
-
|
|
|
-//=======================================
|
|
|
-// Particle system
|
|
|
-//=======================================
|
|
|
-
|
|
|
-THREE.Particles = THREE.Particles || {};
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem = function() {
|
|
|
-
|
|
|
- THREE.Object3D.call( this );
|
|
|
-
|
|
|
- this.zSort = false;
|
|
|
- this.simulateInLocalSpace = true;
|
|
|
- this.matrixAutoUpdate = true;
|
|
|
-
|
|
|
- this.releaseAtOnce = false;
|
|
|
- this.releaseAtOnceCount = 0.0;
|
|
|
- this.hasInitialReleaseOccurred = false;
|
|
|
- this.isActive = false;
|
|
|
-
|
|
|
- this.atlasInitializer = THREE.Particles.ParticleSystem.DefaultInitializer;
|
|
|
- this.colorInitializer = THREE.Particles.ParticleSystem.DefaultInitializer;
|
|
|
- this.alphaInitializer = THREE.Particles.ParticleSystem.DefaultInitializer;
|
|
|
- this.sizeInitializer = THREE.Particles.ParticleSystem.DefaultInitializer;
|
|
|
- this.atlasUpdater = THREE.Particles.ParticleSystem.DefaultUpdater;
|
|
|
- this.colorUpdater = THREE.Particles.ParticleSystem.DefaultUpdater;
|
|
|
- this.alphaUpdater = THREE.Particles.ParticleSystem.DefaultUpdater;
|
|
|
- this.sizeUpdater = THREE.Particles.ParticleSystem.DefaultUpdater;
|
|
|
-
|
|
|
- // Particle position and position modifiers (velocity and acceleration)
|
|
|
- this.positionUpdater = THREE.Particles.ParticleSystem.DefaultPositionUpdater;
|
|
|
- this.velocityUpdater = THREE.Particles.ParticleSystem.DefaultVelocityUpdater;
|
|
|
- this.accelerationUpdater = THREE.Particles.ParticleSystem.DefaultUpdater;
|
|
|
- this.positionInitializer = THREE.Particles.ParticleSystem.DefaultInitializer;
|
|
|
- this.velocityInitializer = THREE.Particles.ParticleSystem.DefaultInitializer;
|
|
|
- this.accelerationInitializer = THREE.Particles.ParticleSystem.DefaultInitializer;
|
|
|
-
|
|
|
- // Particle rotation and rotation modifiers (rotational speed and rotational acceleration)
|
|
|
- this.rotationUpdater = THREE.Particles.ParticleSystem.DefaultRotationUpdater;
|
|
|
- this.rotationalSpeedUpdater = THREE.Particles.ParticleSystem.DefaultRotationalSpeedUpdater;
|
|
|
- this.rotationalAccelerationUpdater = THREE.Particles.ParticleSystem.DefaultUpdater;
|
|
|
- this.rotationInitializer = THREE.Particles.ParticleSystem.DefaultInitializer;
|
|
|
- this.rotationalSpeedInitializer = THREE.Particles.ParticleSystem.DefaultInitializer;
|
|
|
- this.rotationalAccelerationInitializer = THREE.Particles.ParticleSystem.DefaultInitializer;
|
|
|
-
|
|
|
- this.particleReleaseRate = 100;
|
|
|
- this.particleLifeSpan = 1.0;
|
|
|
- this.averageParticleLifeSpan = 1.0;
|
|
|
- this.calculateAverageParticleLifeSpan();
|
|
|
-
|
|
|
- this.calculateMaxParticleCount();
|
|
|
- this.liveParticleCount = 0;
|
|
|
- this.deadParticleCount = 0;
|
|
|
- this.liveParticleArray = [];
|
|
|
- this.deadParticleArray = [];
|
|
|
-
|
|
|
- this._tempParticleArray = [];
|
|
|
-
|
|
|
- this.timeSinceLastEmit = 0.0;
|
|
|
- this.emitting = true;
|
|
|
- this.age = 0.0;
|
|
|
- this.lifespan = 0;
|
|
|
-
|
|
|
- // temporary storage
|
|
|
- this._tempVector3 = new THREE.Vector3();
|
|
|
- this._tempQuaternion = new THREE.Quaternion();
|
|
|
- this._tempMatrix4 = new THREE.Matrix4();
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype = Object.create( THREE.Object3D.prototype );
|
|
|
-THREE.Particles.ParticleSystem.prototype.constructor = THREE.Particles.ParticleSystem;
|
|
|
-
|
|
|
-//=======================================
|
|
|
-// Particle system default shader
|
|
|
-//=======================================
|
|
|
-THREE.Particles.ParticleSystem.Shader = THREE.Particles.ParticleSystem.Shader || {};
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.Shader.VertexVars = [
|
|
|
-
|
|
|
- "attribute vec4 customColor;",
|
|
|
- "attribute vec2 size;",
|
|
|
- "attribute float rotation;",
|
|
|
- "attribute float customIndex;",
|
|
|
- "varying vec2 vUV;",
|
|
|
- "varying vec4 vColor;",
|
|
|
- "uniform vec3 cameraaxisx;",
|
|
|
- "uniform vec3 cameraaxisy;",
|
|
|
- "uniform vec3 cameraaxisz;",
|
|
|
-
|
|
|
-].join( "\n" );
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.Shader.FragmentVars = [
|
|
|
-
|
|
|
- "varying vec2 vUV;",
|
|
|
- "varying vec4 vColor;",
|
|
|
- "uniform sampler2D texture;",
|
|
|
-
|
|
|
-].join( "\n" );
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.Shader.ParticleVertexQuadPositionFunction = [
|
|
|
-
|
|
|
- "vec4 getQuadPosition() {",
|
|
|
-
|
|
|
- "vec3 axisX = cameraaxisx;",
|
|
|
- "vec3 axisY = cameraaxisy;",
|
|
|
- "vec3 axisZ = cameraaxisz;",
|
|
|
-
|
|
|
- "axisX *= cos( rotation );",
|
|
|
- "axisY *= sin( rotation );",
|
|
|
-
|
|
|
- "axisX += axisY;",
|
|
|
- "axisY = cross( axisZ, axisX );",
|
|
|
-
|
|
|
- "vec3 edge = vec3( 2.0, customIndex, 3.0 );",
|
|
|
- "vec3 test = vec3( customIndex, 0.5, customIndex );",
|
|
|
- "vec3 result = step( edge, test );",
|
|
|
-
|
|
|
- "float xFactor = -1.0 + ( result.x * 2.0 );",
|
|
|
- "float yFactor = -1.0 + ( result.y * 2.0 ) + ( result.z * 2.0 );",
|
|
|
-
|
|
|
- "axisX *= size.x * xFactor;",
|
|
|
- "axisY *= size.y * yFactor;",
|
|
|
-
|
|
|
- "return ( modelMatrix * vec4( position, 1.0 ) ) + vec4( axisX + axisY, 0.0 );",
|
|
|
-
|
|
|
- "}",
|
|
|
-
|
|
|
-].join( "\n" );
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.Shader.VertexShader = [
|
|
|
-
|
|
|
- THREE.Particles.ParticleSystem.Shader.VertexVars,
|
|
|
- THREE.Particles.ParticleSystem.Shader.ParticleVertexQuadPositionFunction,
|
|
|
-
|
|
|
- "void main() { ",
|
|
|
-
|
|
|
- "vColor = customColor;",
|
|
|
- "vUV = uv;",
|
|
|
- "vec4 quadPos = getQuadPosition();",
|
|
|
- "gl_Position = projectionMatrix * viewMatrix * quadPos;",
|
|
|
-
|
|
|
- "}"
|
|
|
-
|
|
|
-].join( "\n" );
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.Shader.FragmentShader = [
|
|
|
-
|
|
|
- THREE.Particles.ParticleSystem.Shader.FragmentVars,
|
|
|
-
|
|
|
- "void main() { ",
|
|
|
-
|
|
|
- "vec4 textureColor = texture2D( texture, vUV );",
|
|
|
- "gl_FragColor = vColor * textureColor;",
|
|
|
-
|
|
|
- "}"
|
|
|
-
|
|
|
-].join( "\n" );
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.createMaterial = function( vertexShader, fragmentShader, customUniforms ) {
|
|
|
-
|
|
|
- customUniforms = customUniforms || {};
|
|
|
-
|
|
|
- customUniforms.texture = { type: "t", value: null };
|
|
|
- customUniforms.cameraaxisx = { type: "v3", value: new THREE.Vector3() };
|
|
|
- customUniforms.cameraaxisy = { type: "v3", value: new THREE.Vector3() };
|
|
|
- customUniforms.cameraaxisz = { type: "v3", value: new THREE.Vector3() };
|
|
|
-
|
|
|
- vertexShader = vertexShader || THREE.Particles.ParticleSystem.Shader.VertexShader;
|
|
|
- fragmentShader = fragmentShader || THREE.Particles.ParticleSystem.Shader.FragmentShader;
|
|
|
-
|
|
|
- return new THREE.ShaderMaterial(
|
|
|
- {
|
|
|
- uniforms: customUniforms,
|
|
|
- vertexShader: vertexShader,
|
|
|
- fragmentShader: fragmentShader,
|
|
|
-
|
|
|
- transparent: true,
|
|
|
- alphaTest: 0.5,
|
|
|
-
|
|
|
- blending: THREE.NormalBlending,
|
|
|
-
|
|
|
- depthTest: true,
|
|
|
- depthWrite: false
|
|
|
- } );
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//=======================================
|
|
|
-// Particle system functions
|
|
|
-//=======================================
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.calculateAverageParticleLifeSpan = function() {
|
|
|
-
|
|
|
- var total = 0.0;
|
|
|
-
|
|
|
- for ( var i = 0; i < 100; i ++ ) {
|
|
|
-
|
|
|
- total += this.particleLifeSpan;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- total /= 100.0;
|
|
|
-
|
|
|
- this.averageParticleLifeSpan = total;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.calculateMaxParticleCount = function() {
|
|
|
-
|
|
|
- if ( this.releaseAtOnce ) {
|
|
|
-
|
|
|
- this.maxParticleCount = this.releaseAtOnceCount;
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- var minLifeSpan = this.particleLifeSpan;
|
|
|
- if ( this.lifespan != 0 && this.lifespan < minLifeSpan ) minLifeSpan = this.lifespan;
|
|
|
- this.maxParticleCount = Math.max( this.particleReleaseRate * minLifeSpan * 2, 1.0 );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- this.vertexCount = this.maxParticleCount * THREE.Particles.Constants.VerticesPerParticle;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.initializeGeometry = function() {
|
|
|
-
|
|
|
- this.particleGeometry = new THREE.BufferGeometry();
|
|
|
- var particleColor = new Float32Array( this.vertexCount * 4 );
|
|
|
- var particleAlpha = new Float32Array( this.vertexCount );
|
|
|
- var positions = new Float32Array( this.vertexCount * 3 );
|
|
|
- var uvs = new Float32Array( this.vertexCount * 2 );
|
|
|
- var size = new Float32Array( this.vertexCount * 2 );
|
|
|
- var rotation = new Float32Array( this.vertexCount );
|
|
|
- var index = new Float32Array( this.vertexCount );
|
|
|
-
|
|
|
- var particleColorAttribute = new THREE.BufferAttribute( particleColor, 4 );
|
|
|
- particleColorAttribute.setDynamic( true );
|
|
|
- this.particleGeometry.addAttribute( 'customColor', particleColorAttribute );
|
|
|
-
|
|
|
- var positionAttribute = new THREE.BufferAttribute( positions, 3 );
|
|
|
- positionAttribute.setDynamic( true );
|
|
|
- this.particleGeometry.addAttribute( 'position', positionAttribute );
|
|
|
-
|
|
|
- var uvAttribute = new THREE.BufferAttribute( uvs, 2 );
|
|
|
- uvAttribute.setDynamic( true );
|
|
|
- this.particleGeometry.addAttribute( 'uv', uvAttribute );
|
|
|
-
|
|
|
- var sizeAttribute = new THREE.BufferAttribute( size, 2 );
|
|
|
- sizeAttribute.setDynamic( true );
|
|
|
- this.particleGeometry.addAttribute( 'size', sizeAttribute );
|
|
|
-
|
|
|
- var rotationAttribute = new THREE.BufferAttribute( rotation, 1 );
|
|
|
- rotationAttribute.setDynamic( true );
|
|
|
- this.particleGeometry.addAttribute( 'rotation', rotationAttribute );
|
|
|
-
|
|
|
- var indexAttribute = new THREE.BufferAttribute( index, 1 );
|
|
|
- indexAttribute.setDynamic( true );
|
|
|
- this.particleGeometry.addAttribute( 'customIndex', indexAttribute );
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.initializeMaterial = function( material ) {
|
|
|
-
|
|
|
- this.particleMaterial = material;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.initializeMesh = function() {
|
|
|
-
|
|
|
- this.destroyMesh();
|
|
|
-
|
|
|
- this.particleMesh = new THREE.Mesh( this.particleGeometry, this.particleMaterial );
|
|
|
- this.particleMesh.dynamic = true;
|
|
|
- this.particleMesh.matrixAutoUpdate = false;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.destroyMesh = function() {
|
|
|
-
|
|
|
- if ( this.particleMesh ) {
|
|
|
-
|
|
|
- scene.remove( this.particleMesh );
|
|
|
- this.particleMesh = undefined;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.initializeParticleArray = function() {
|
|
|
-
|
|
|
- for ( var i = 0; i < this.maxParticleCount; i ++ ) {
|
|
|
-
|
|
|
- var particle = this.createParticle();
|
|
|
- this.initializeParticle( particle );
|
|
|
- this.deadParticleArray[ i ] = particle;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- this.liveParticleCount = 0;
|
|
|
- this.deadParticleCount = this.maxParticleCount;
|
|
|
-
|
|
|
- this.liveParticleArray.length = this.liveParticleCount;
|
|
|
- this.deadParticleArray.length = this.deadParticleCount;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.mergeParameters = function( parameters ) {
|
|
|
-
|
|
|
- for ( var key in parameters ) {
|
|
|
-
|
|
|
- this[ key ] = parameters[ key ];
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.bindInitializer = function( name, modifier ) {
|
|
|
-
|
|
|
- if ( name ) {
|
|
|
-
|
|
|
- this[ name + "Initializer" ] = modifier;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.bindUpdater = function( name, modifier ) {
|
|
|
-
|
|
|
- if ( name ) {
|
|
|
-
|
|
|
- this[ name + "Updater" ] = modifier;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.bindModifier = function( name, modifier ) {
|
|
|
-
|
|
|
- this.bindInitializer( name, modifier );
|
|
|
- this.bindUpdater( name, modifier );
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.initialize = function( camera, parameters ) {
|
|
|
-
|
|
|
- this.camera = camera;
|
|
|
-
|
|
|
- this.sizeFrameSet = undefined;
|
|
|
- this.colorFrameSet = undefined;
|
|
|
- this.alphaFrameSet = undefined;
|
|
|
-
|
|
|
- if ( parameters ) {
|
|
|
-
|
|
|
- this.mergeParameters ( parameters );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( ! this.sizeFrameSet ) this.sizeFrameSet = new THREE.Particles.FrameSet();
|
|
|
- if ( ! this.colorFrameSet ) this.colorFrameSet = new THREE.Particles.FrameSet();
|
|
|
- if ( ! this.alphaFrameSet ) this.alphaFrameSet = new THREE.Particles.FrameSet();
|
|
|
-
|
|
|
- this.liveParticleArray = [];
|
|
|
- this.timeSinceLastEmit = 0.0;
|
|
|
- this.age = 0.0;
|
|
|
- this.emitting = true;
|
|
|
-
|
|
|
- this.calculateAverageParticleLifeSpan();
|
|
|
- this.calculateMaxParticleCount();
|
|
|
- this.initializeParticleArray();
|
|
|
-
|
|
|
- this.initializeGeometry();
|
|
|
- this.initializeMaterial( parameters.material );
|
|
|
- this.updateAttributesWithParticleData();
|
|
|
- this.initializeMesh();
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.getCameraWorldAxes = function() {
|
|
|
-
|
|
|
- var quaternion = new THREE.Quaternion();
|
|
|
-
|
|
|
- return function getCameraWorldAxes( camera, axisX, axisY, axisZ ) {
|
|
|
-
|
|
|
- camera.getWorldQuaternion( quaternion );
|
|
|
- axisZ.set( 0, 0, 1 ).applyQuaternion( quaternion );
|
|
|
- axisY.set( 0, 1, 0 ).applyQuaternion( quaternion );
|
|
|
- axisX.crossVectors( axisY, axisZ );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}();
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.generateXYAlignedQuadForParticle = function() {
|
|
|
-
|
|
|
- var vectorX = new THREE.Vector3();
|
|
|
- var vectorY = new THREE.Vector3();
|
|
|
-
|
|
|
- return function generateXYAlignedQuadForParticle( particle, axisX, axisY, axisZ, pos1, pos2, pos3, pos4 ) {
|
|
|
-
|
|
|
- var position = particle.position;
|
|
|
- var rotation = particle.rotation;
|
|
|
-
|
|
|
- vectorX.copy( axisX );
|
|
|
- vectorY.copy( axisY );
|
|
|
-
|
|
|
- vectorX.multiplyScalar( Math.cos( rotation * THREE.Particles.Constants.DegreesToRadians ) );
|
|
|
- vectorY.multiplyScalar( Math.sin( rotation * THREE.Particles.Constants.DegreesToRadians ) );
|
|
|
-
|
|
|
- vectorX.addVectors( vectorX, vectorY );
|
|
|
- vectorY.crossVectors( axisZ, vectorX );
|
|
|
-
|
|
|
- vectorX.multiplyScalar( particle.size.x );
|
|
|
- vectorY.multiplyScalar( particle.size.y );
|
|
|
-
|
|
|
- pos1.subVectors( position, vectorX ).addVectors( pos1, vectorY );
|
|
|
- pos2.subVectors( position, vectorX ).subVectors( pos2, vectorY );
|
|
|
- pos3.addVectors( position, vectorX ).subVectors( pos3, vectorY );
|
|
|
- pos4.addVectors( position, vectorX ).addVectors( pos4, vectorY );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}();
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.updateAttributesWithParticleData = function() {
|
|
|
-
|
|
|
- var vectorY = new THREE.Vector3();
|
|
|
- var vectorX = new THREE.Vector3();
|
|
|
- var vectorZ = new THREE.Vector3();
|
|
|
-
|
|
|
- var quadPos1 = new THREE.Vector3();
|
|
|
- var quadPos2 = new THREE.Vector3();
|
|
|
- var quadPos3 = new THREE.Vector3();
|
|
|
- var quadPos4 = new THREE.Vector3();
|
|
|
-
|
|
|
- return function updateAttributesWithParticleData() {
|
|
|
-
|
|
|
- this.getCameraWorldAxes( this.camera, vectorX, vectorY, vectorZ );
|
|
|
-
|
|
|
- this.particleMaterial.uniforms.cameraaxisx.value.copy( vectorX );
|
|
|
- this.particleMaterial.uniforms.cameraaxisy.value.copy( vectorY );
|
|
|
- this.particleMaterial.uniforms.cameraaxisz.value.copy( vectorZ );
|
|
|
- this.particleMaterial.uniforms.texture.value = this.particleAtlas.getTexture();
|
|
|
-
|
|
|
- for ( var p = 0; p < this.liveParticleCount; p ++ ) {
|
|
|
-
|
|
|
- var particle = this.liveParticleArray[ p ];
|
|
|
- var position = particle.position;
|
|
|
-
|
|
|
- var baseIndex = p * THREE.Particles.Constants.VerticesPerParticle;
|
|
|
-
|
|
|
- var attributePosition = this.particleGeometry.getAttribute( 'position' );
|
|
|
- this.updateAttributeVector3( attributePosition, baseIndex, position );
|
|
|
- this.updateAttributeVector3( attributePosition, baseIndex + 1, position );
|
|
|
- this.updateAttributeVector3( attributePosition, baseIndex + 2, position );
|
|
|
- this.updateAttributeVector3( attributePosition, baseIndex + 3, position );
|
|
|
- this.updateAttributeVector3( attributePosition, baseIndex + 4, position );
|
|
|
- this.updateAttributeVector3( attributePosition, baseIndex + 5, position );
|
|
|
-
|
|
|
- var imageDesc = this.particleAtlas.getImageDescriptor( particle.atlasIndex.x );
|
|
|
- var attributeUV = this.particleGeometry.getAttribute( 'uv' );
|
|
|
- this.updateAttributeVector2XY( attributeUV, baseIndex, imageDesc.left, imageDesc.top );
|
|
|
- this.updateAttributeVector2XY( attributeUV, baseIndex + 1, imageDesc.left, imageDesc.bottom );
|
|
|
- this.updateAttributeVector2XY( attributeUV, baseIndex + 2, imageDesc.right, imageDesc.top );
|
|
|
- this.updateAttributeVector2XY( attributeUV, baseIndex + 3, imageDesc.left, imageDesc.bottom );
|
|
|
- this.updateAttributeVector2XY( attributeUV, baseIndex + 4, imageDesc.right, imageDesc.bottom );
|
|
|
- this.updateAttributeVector2XY( attributeUV, baseIndex + 5, imageDesc.right, imageDesc.top );
|
|
|
-
|
|
|
- var color = particle.color;
|
|
|
- var alpha = particle.alpha.x;
|
|
|
- color.a = alpha;
|
|
|
- var size = particle.size;
|
|
|
- var rotation = particle.rotation.x * THREE.Particles.Constants.DegreesToRadians
|
|
|
-
|
|
|
- var attributeColor = this.particleGeometry.getAttribute( 'customColor' );
|
|
|
- var attributeSize = this.particleGeometry.getAttribute( 'size' );
|
|
|
- var attributeRotation = this.particleGeometry.getAttribute( 'rotation' );
|
|
|
- for ( var i = 0; i < THREE.Particles.Constants.VerticesPerParticle; i ++ ) {
|
|
|
-
|
|
|
- var index = baseIndex + i;
|
|
|
- this.updateAttributeColor( attributeColor, index, color );
|
|
|
- this.updateAttributeVector2XY( attributeSize, index, size.x, size.y );
|
|
|
- this.updateAttributeScalar( attributeRotation, index, rotation );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- var attributeIndex = this.particleGeometry.getAttribute( 'customIndex' );
|
|
|
- this.updateAttributeScalar( attributeIndex, baseIndex, 0 );
|
|
|
- this.updateAttributeScalar( attributeIndex, baseIndex + 1, 1 );
|
|
|
- this.updateAttributeScalar( attributeIndex, baseIndex + 2, 3 );
|
|
|
- this.updateAttributeScalar( attributeIndex, baseIndex + 3, 1 );
|
|
|
- this.updateAttributeScalar( attributeIndex, baseIndex + 4, 2 );
|
|
|
- this.updateAttributeScalar( attributeIndex, baseIndex + 5, 3 );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- this.particleGeometry.setDrawRange( 0, THREE.Particles.Constants.VerticesPerParticle * this.liveParticleCount );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}();
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.updateAttributeVector2XY = function( attribute, index, x, y ) {
|
|
|
-
|
|
|
- attribute.array[ index * 2 ] = x;
|
|
|
- attribute.array[ index * 2 + 1 ] = y;
|
|
|
- attribute.needsUpdate = true;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.updateAttributeVector3 = function( attribute, index, value ) {
|
|
|
-
|
|
|
- attribute.array[ index * 3 ] = value.x;
|
|
|
- attribute.array[ index * 3 + 1 ] = value.y;
|
|
|
- attribute.array[ index * 3 + 2 ] = value.z;
|
|
|
- attribute.needsUpdate = true;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.updateAttributeColor = function( attribute, index, value ) {
|
|
|
-
|
|
|
- attribute.array[ index * 4 ] = value.r;
|
|
|
- attribute.array[ index * 4 + 1 ] = value.g;
|
|
|
- attribute.array[ index * 4 + 2 ] = value.b;
|
|
|
- attribute.array[ index * 4 + 3 ] = value.a;
|
|
|
- attribute.needsUpdate = true;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.updateAttributeScalar = function( attribute, index, value ) {
|
|
|
-
|
|
|
- attribute.array[ index ] = value;
|
|
|
- attribute.needsUpdate = true;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.createParticle = function() {
|
|
|
-
|
|
|
- var particle = new THREE.Particles.Particle();
|
|
|
- return particle;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.initializeParticle = function( particle ) {
|
|
|
-
|
|
|
- this.resetParticle( particle );
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.resetParticle = function( particle ) {
|
|
|
-
|
|
|
- particle.age = 0;
|
|
|
- particle.alive = 0;
|
|
|
-
|
|
|
- this.resetParticleDisplayAttributes( particle );
|
|
|
- this.resetParticlePositionData( particle );
|
|
|
- this.resetParticleRotationData( particle );
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.resetParticleDisplayAttributes = function( particle ) {
|
|
|
-
|
|
|
- this.atlasInitializer.update( particle, particle.atlasIndex, 0 );
|
|
|
- this.sizeInitializer.update( particle, particle.size, 0 );
|
|
|
- this.colorInitializer.update( particle, particle._tempVector3, 0 );
|
|
|
- particle.color.setRGB( particle._tempVector3.x, particle._tempVector3.y, particle._tempVector3.z );
|
|
|
- this.alphaInitializer.update( particle, particle.alpha, 0 );
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.resetParticlePositionData = function( particle ) {
|
|
|
-
|
|
|
- this.positionInitializer.update( particle, particle.position, 0 );
|
|
|
-
|
|
|
- if ( ! this.simulateInLocalSpace ) {
|
|
|
-
|
|
|
- particle._tempVector3.setFromMatrixPosition( this.matrixWorld );
|
|
|
- particle.position.addVectors( particle._tempVector3, particle.position );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- this.velocityInitializer.update( particle, particle.velocity, 0 );
|
|
|
- this.accelerationInitializer.update( particle, particle.acceleration, 0 );
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.resetParticleRotationData = function( particle ) {
|
|
|
-
|
|
|
- this.rotationInitializer.update( particle, particle.rotation );
|
|
|
- this.rotationalSpeedInitializer.update( particle, particle.rotationalSpeed );
|
|
|
- this.rotationalAccelerationInitializer.update( particle, particle.rotationalAcceleration );
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.advanceParticle = function( particle, deltaTime ) {
|
|
|
-
|
|
|
- particle.age += deltaTime;
|
|
|
-
|
|
|
- this.advanceParticleDisplayAttributes( particle, deltaTime );
|
|
|
- this.advanceParticlePositionData( particle, deltaTime );
|
|
|
- this.advanceParticleRotationData( particle, deltaTime );
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.advanceParticleDisplayAttributes = function( particle, deltaTime ) {
|
|
|
-
|
|
|
- this.atlasUpdater.update( particle, particle.atlasIndex, deltaTime );
|
|
|
- this.sizeUpdater.update( particle, particle.size, deltaTime );
|
|
|
- this.colorUpdater.update( particle, particle._tempVector3, deltaTime );
|
|
|
- particle.color.setRGB( particle._tempVector3.x, particle._tempVector3.y, particle._tempVector3.z );
|
|
|
- this.alphaUpdater.update( particle, particle.alpha, deltaTime );
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.advanceParticlePositionData = function( particle, deltaTime ) {
|
|
|
-
|
|
|
- this.positionUpdater.update( particle, particle.position, deltaTime );
|
|
|
- this.velocityUpdater.update( particle, particle.velocity, deltaTime );
|
|
|
- this.accelerationUpdater.update( particle, particle.acceleration, deltaTime );
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.advanceParticleRotationData = function( particle, deltaTime ) {
|
|
|
-
|
|
|
- this.rotationUpdater.update( particle, particle.rotation, deltaTime );
|
|
|
- this.rotationalSpeedUpdater.update( particle, particle.rotationalSpeed, deltaTime );
|
|
|
- this.rotationalAccelerationUpdater.update( particle, particle.rotationalAcceleration, deltaTime );
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.advanceParticles = function( deltaTime ) {
|
|
|
-
|
|
|
- var deadCount = 0;
|
|
|
-
|
|
|
- for ( var i = 0; i < this.liveParticleCount; i ++ )
|
|
|
- {
|
|
|
-
|
|
|
- var particle = this.liveParticleArray[ i ];
|
|
|
- this.advanceParticle( particle, deltaTime );
|
|
|
-
|
|
|
- if ( particle.age > particle.lifeSpan )
|
|
|
- {
|
|
|
-
|
|
|
- this.killParticle( particle );
|
|
|
- deadCount ++;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( deadCount > 0 ) {
|
|
|
-
|
|
|
- this.cleanupDeadParticles();
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.killParticle = function( particle ) {
|
|
|
-
|
|
|
- particle.alive = 0.0;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.activateParticle = function( particle ) {
|
|
|
-
|
|
|
- this.resetParticle( particle );
|
|
|
- particle.lifeSpan = this.particleLifeSpan;
|
|
|
- particle.alive = 1.0;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.cleanupDeadParticles = function() {
|
|
|
-
|
|
|
- var topAlive = this.liveParticleCount - 1;
|
|
|
- var bottomDead = 0;
|
|
|
- while ( topAlive > bottomDead ) {
|
|
|
-
|
|
|
- while ( this.liveParticleArray[ topAlive ].alive == 0.0 && topAlive > 0 ) {
|
|
|
-
|
|
|
- topAlive --;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- while ( this.liveParticleArray[ bottomDead ].alive == 1.0 && bottomDead < this.liveParticleCount - 1 ) {
|
|
|
-
|
|
|
- bottomDead ++;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( topAlive <= bottomDead ) {
|
|
|
-
|
|
|
- break;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- var swap = this.liveParticleArray[ bottomDead ];
|
|
|
- this.liveParticleArray[ bottomDead ] = this.liveParticleArray[ topAlive ];
|
|
|
- this.liveParticleArray[ topAlive ] = swap;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- while ( this.liveParticleCount > 0 && this.liveParticleArray[ this.liveParticleCount - 1 ].alive == 0.0 ) {
|
|
|
-
|
|
|
- this.deadParticleArray[ this.deadParticleCount ] = this.liveParticleArray[ this.liveParticleCount - 1 ];
|
|
|
- this.deadParticleCount ++;
|
|
|
- this.liveParticleCount --;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- this.liveParticleArray.length = this.liveParticleCount;
|
|
|
- this.deadParticleArray.length = this.deadParticleCount;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.sortParticleArray = function() {
|
|
|
-
|
|
|
- function numericalSort( a, b ) {
|
|
|
-
|
|
|
- return a[ 0 ] - b[ 0 ];
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
- var _sortParticleArray = [];
|
|
|
- var projectedPosition = new THREE.Vector3();
|
|
|
-
|
|
|
- return function sortParticleArray( mvpMatrix ) {
|
|
|
-
|
|
|
- for ( var p = 0; p < this.liveParticleCount; p ++ ) {
|
|
|
-
|
|
|
- var position = this.liveParticleArray[ p ].position;
|
|
|
- projectedPosition.copy( position );
|
|
|
- projectedPosition.applyProjection( mvpMatrix );
|
|
|
-
|
|
|
- if ( ! _sortParticleArray[ p ] ) {
|
|
|
-
|
|
|
- _sortParticleArray[ p ] = [ 0, 0 ];
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- _sortParticleArray[ p ][ 0 ] = projectedPosition.z;
|
|
|
- _sortParticleArray[ p ][ 1 ] = p;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- _sortParticleArray.length = this.liveParticleCount;
|
|
|
- _sortParticleArray.sort( numericalSort );
|
|
|
-
|
|
|
- for ( p = 0; p < this.liveParticleCount; p ++ ) {
|
|
|
-
|
|
|
- var originalIndex = _sortParticleArray[ p ][ 1 ];
|
|
|
- this._tempParticleArray[ p ] = this.liveParticleArray[ originalIndex ];
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- this._tempParticleArray.length = this.liveParticleCount;
|
|
|
-
|
|
|
- var temp = this.liveParticleArray;
|
|
|
- this.liveParticleArray = this._tempParticleArray;
|
|
|
- this._tempParticleArray = temp;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}();
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.activateParticles = function( count ) {
|
|
|
-
|
|
|
- for ( var i = 0; i < count; i ++ ) {
|
|
|
-
|
|
|
- if ( this.liveParticleCount < this.maxParticleCount && this.deadParticleCount > 0 ) {
|
|
|
-
|
|
|
- var newParticle = this.deadParticleArray[ this.deadParticleCount - 1 ];
|
|
|
- this.liveParticleArray[ this.liveParticleCount ] = newParticle;
|
|
|
- this.deadParticleCount --;
|
|
|
- this.liveParticleCount ++;
|
|
|
-
|
|
|
- this.activateParticle ( newParticle );
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- break;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- this.liveParticleArray.length = this.liveParticleCount;
|
|
|
- this.deadParticleArray.length = this.deadParticleCount;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.update = function() {
|
|
|
-
|
|
|
- var tempMatrix4 = new THREE.Matrix4();
|
|
|
-
|
|
|
- return function update( deltaTime ) {
|
|
|
-
|
|
|
- if ( ! this.emitting )return;
|
|
|
- if ( ! this.isActive )return;
|
|
|
-
|
|
|
- this.timeSinceLastEmit += deltaTime;
|
|
|
-
|
|
|
- if ( this.releaseAtOnce ) {
|
|
|
-
|
|
|
- var waitTime = this.averageParticleLifeSpan;
|
|
|
-
|
|
|
- if ( ! this.hasInitialReleaseOccurred || ( this.timeSinceLastEmit > waitTime && this.liveParticleCount <= 0 ) ) {
|
|
|
-
|
|
|
- this.activateParticles( this.maxParticleCount );
|
|
|
- this.timeSinceLastEmit = 0.0;
|
|
|
- this.hasInitialReleaseOccurred = true;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- var emitUnitTime = 1.0 / this.particleReleaseRate;
|
|
|
- if ( ! this.hasInitialReleaseOccurred || this.timeSinceLastEmit > emitUnitTime ) {
|
|
|
-
|
|
|
- var releaseCount = Math.max( 1, Math.floor( this.timeSinceLastEmit / emitUnitTime ) );
|
|
|
- this.activateParticles( releaseCount );
|
|
|
- this.timeSinceLastEmit = 0.0;
|
|
|
- this.hasInitialReleaseOccurred = true;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- this.advanceParticles( deltaTime );
|
|
|
-
|
|
|
- if ( this.zSort ) {
|
|
|
-
|
|
|
- this.camera.updateMatrixWorld();
|
|
|
- tempMatrix4.copy( this.camera.matrixWorld );
|
|
|
- tempMatrix4.getInverse( tempMatrix4 );
|
|
|
- this.sortParticleArray( tempMatrix4 );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- this.updateAttributesWithParticleData();
|
|
|
-
|
|
|
- this.age += deltaTime;
|
|
|
- if ( this.lifespan != 0 && this.age > this.lifespan ) {
|
|
|
-
|
|
|
- this.emitting = false;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( this.simulateInLocalSpace ) {
|
|
|
-
|
|
|
- this.particleMesh.matrix.copy( this.matrixWorld );
|
|
|
- this.particleMesh.updateMatrixWorld();
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}();
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.deactivate = function() {
|
|
|
-
|
|
|
- if ( this.isActive ) {
|
|
|
-
|
|
|
- scene.remove( this.particleMesh );
|
|
|
- this.isActive = false;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.prototype.activate = function() {
|
|
|
-
|
|
|
- if ( ! this.isActive ) {
|
|
|
-
|
|
|
- scene.add( this.particleMesh );
|
|
|
- this.isActive = true;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.DefaultPositionUpdater = {
|
|
|
-
|
|
|
- update : function( particle, target, deltaTime ) {
|
|
|
-
|
|
|
- particle._tempVector3.copy( particle.velocity );
|
|
|
- particle._tempVector3.multiplyScalar( deltaTime );
|
|
|
- particle.position.add( particle._tempVector3 );
|
|
|
-
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.DefaultVelocityUpdater = {
|
|
|
-
|
|
|
- update : function( particle, target, deltaTime ) {
|
|
|
-
|
|
|
- particle._tempVector3.copy( particle.acceleration );
|
|
|
- particle._tempVector3.multiplyScalar( deltaTime );
|
|
|
- particle.velocity.add( particle._tempVector3 );
|
|
|
-
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.DefaultRotationUpdater = {
|
|
|
-
|
|
|
- update : function( particle, target, deltaTime ) {
|
|
|
-
|
|
|
- particle.rotation.set( particle.rotation.x += particle.rotationalSpeed.x * deltaTime );
|
|
|
-
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.DefaultRotationalSpeedUpdater = {
|
|
|
-
|
|
|
- update : function( particle, target, deltaTime ) {
|
|
|
-
|
|
|
- particle.rotationalSpeed.set( particle.rotationalSpeed.x += particle.rotationalAcceleration.x * deltaTime );
|
|
|
-
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.DefaultUpdater = {
|
|
|
-
|
|
|
- update : function( particle, target, deltaTime ) {
|
|
|
-
|
|
|
-
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-THREE.Particles.ParticleSystem.DefaultInitializer = {
|
|
|
-
|
|
|
- update : function( particle, target, deltaTime ) {
|
|
|
-
|
|
|
- target.set( 0, 0, 0, 0 );
|
|
|
-
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-//=======================================
|
|
|
-// Particle object
|
|
|
-//=======================================
|
|
|
-
|
|
|
-THREE.Particles.Particle = function() {
|
|
|
-
|
|
|
- this.age = 0;
|
|
|
- this.alive = 0;
|
|
|
- this.lifeSpan = 0;
|
|
|
-
|
|
|
- this.size = new THREE.Vector3();
|
|
|
- this.color = new THREE.Color();
|
|
|
- this.alpha = new THREE.Particles.SingularVector( 0 );
|
|
|
- this.atlasIndex = new THREE.Particles.SingularVector( 0 );
|
|
|
-
|
|
|
- this.position = new THREE.Vector3();
|
|
|
- this.velocity = new THREE.Vector3();
|
|
|
- this.acceleration = new THREE.Vector3();
|
|
|
-
|
|
|
- this.rotation = new THREE.Particles.SingularVector( 0 );
|
|
|
- this.rotationalSpeed = new THREE.Particles.SingularVector( 0 );
|
|
|
- this.rotationalAcceleration = new THREE.Particles.SingularVector( 0 );
|
|
|
-
|
|
|
- this._tempVector3 = new THREE.Vector3();
|
|
|
-
|
|
|
-}
|