From 648ee61ae84216d0236e0dbc211addc13b2cfa3a Mon Sep 17 00:00:00 2001
From: Kris Kowal
Date: Fri, 6 Jul 2012 11:52:06 -0700
Subject: Expand tabs
---
js/helper-classes/RDGE/src/core/script/particle.js | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
(limited to 'js/helper-classes/RDGE/src/core/script/particle.js')
diff --git a/js/helper-classes/RDGE/src/core/script/particle.js b/js/helper-classes/RDGE/src/core/script/particle.js
index d1ab6239..158807bb 100755
--- a/js/helper-classes/RDGE/src/core/script/particle.js
+++ b/js/helper-classes/RDGE/src/core/script/particle.js
@@ -62,8 +62,8 @@ RDGE.particle = function (def, id) {
this.randomize3 = function (min, max) {
return [this.randomize(min[0], max[0]),
- this.randomize(min[1], max[1]),
- this.randomize(min[2], max[2])];
+ this.randomize(min[1], max[1]),
+ this.randomize(min[2], max[2])];
};
this.spawn = function (spawnMatrix) {
@@ -148,7 +148,7 @@ RDGE.particleBuffer = function (pdef, emitter, size) {
'u_textureSize': { 'type': 'vec2' },
'u_frameSize': { 'type': 'vec2' },
's_texture0': { 'type': 'tex2d' }
- // 's_texture1' : { 'type' : 'tex2d' }
+ // 's_texture1' : { 'type' : 'tex2d' }
}
}]
}
@@ -336,8 +336,8 @@ RDGE.particleBuffer = function (pdef, emitter, size) {
var age = (p.age / p.lifespan); // normalized age
// combine frame number and age and store in w.
// to decode :
- // frame = floor( w );
- // age = fract( w );
+ // frame = floor( w );
+ // age = fract( w );
var pw = Math.min(age, 0.999) + Math.floor(p.frame);
if (age < 1.0) { // || (pdef.persist != undefined && pdef.persist == true)) {
var px = p.pos[0];
@@ -481,7 +481,7 @@ RDGE.particleBuffer = function (pdef, emitter, size) {
else {
shaderparms.u_viewMatrix.set(activeCam.view);
shaderparms.u_worldMatrix.set(this.owner.world);
- // shaderparms.u_mvMatrix.set(RDGE.mat4.mul(this.owner.world, activeCam.view));
+ // shaderparms.u_mvMatrix.set(RDGE.mat4.mul(this.owner.world, activeCam.view));
}
shaderparms.u_projMatrix.set(activeCam.proj);
@@ -492,7 +492,7 @@ RDGE.particleBuffer = function (pdef, emitter, size) {
shaderparms.u_textureSize.set(pdef.textureSize);
shaderparms.u_frameSize.set(pdef.frameSize);
shaderparms.s_texture0.set(this.texture);
- // shaderparms.s_texture1.set(null);
+ // shaderparms.s_texture1.set(null);
var passCount = this.shader.begin();
for (passIdx = 0; passIdx < passCount; ++passIdx) {
--
cgit v1.2.3
From 04343eda8c2f870b0da55cfdc8003c99fe1cc4de Mon Sep 17 00:00:00 2001
From: Kris Kowal
Date: Fri, 6 Jul 2012 11:53:10 -0700
Subject: Remove trailing spaces
---
js/helper-classes/RDGE/src/core/script/particle.js | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
(limited to 'js/helper-classes/RDGE/src/core/script/particle.js')
diff --git a/js/helper-classes/RDGE/src/core/script/particle.js b/js/helper-classes/RDGE/src/core/script/particle.js
index 158807bb..1730e823 100755
--- a/js/helper-classes/RDGE/src/core/script/particle.js
+++ b/js/helper-classes/RDGE/src/core/script/particle.js
@@ -77,7 +77,7 @@ RDGE.particle = function (def, id) {
// calculate the initial position in world space.
this.pos = RDGE.mat4.transformPoint(spawnMatrix, this.pos);
}
- // all other values are assumed to be defined in local or world space depending on
+ // all other values are assumed to be defined in local or world space depending on
// the particles worldSpace designation.
var toRadians = Math.PI / 180.0;
if (this.def.initialsize) {
@@ -334,10 +334,10 @@ RDGE.particleBuffer = function (pdef, emitter, size) {
var x, y, z, w;
var p = this.particles[i];
var age = (p.age / p.lifespan); // normalized age
- // combine frame number and age and store in w.
- // to decode :
- // frame = floor( w );
- // age = fract( w );
+ // combine frame number and age and store in w.
+ // to decode :
+ // frame = floor( w );
+ // age = fract( w );
var pw = Math.min(age, 0.999) + Math.floor(p.frame);
if (age < 1.0) { // || (pdef.persist != undefined && pdef.persist == true)) {
var px = p.pos[0];
@@ -747,7 +747,7 @@ RDGE.particleSys = function (addr) {
var emin = emitter.pbuffer.bounds.min;
var emax = emitter.pbuffer.bounds.max;
- // calculate a bounds that fits all particles.
+ // calculate a bounds that fits all particles.
if (emin[0] < bmin[0]) { bmin[0] = emin[0]; }
if (emin[1] < bmin[1]) { bmin[1] = emin[1]; }
if (emin[2] < bmin[2]) { bmin[2] = emin[2]; }
--
cgit v1.2.3
From 3644cb6def4f681c99959e5729e78ea353441fad Mon Sep 17 00:00:00 2001
From: Kris Kowal
Date: Fri, 6 Jul 2012 12:34:53 -0700
Subject: Normalize to unix line terminators
---
js/helper-classes/RDGE/src/core/script/particle.js | 1594 ++++++++++----------
1 file changed, 797 insertions(+), 797 deletions(-)
(limited to 'js/helper-classes/RDGE/src/core/script/particle.js')
diff --git a/js/helper-classes/RDGE/src/core/script/particle.js b/js/helper-classes/RDGE/src/core/script/particle.js
index 1730e823..59894e9a 100755
--- a/js/helper-classes/RDGE/src/core/script/particle.js
+++ b/js/helper-classes/RDGE/src/core/script/particle.js
@@ -1,797 +1,797 @@
-/*
-Copyright (c) 2012, Motorola Mobility, Inc
-All Rights Reserved.
-BSD License.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- - Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of Motorola Mobility nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
- */
-
-var RDGE = RDGE || {};
-
-RDGE.particle = function (def, id) {
- this.id = id;
- this.def = def;
- if (this.def.numFrames == undefined) {
- if (this.def.textureSize && this.def.frameSize) {
- this.def.numFrames = (this.def.textureSize[0] / this.def.frameSize[0]) * (this.def.textureSize[1] / this.def.frameSize[1]);
- } else {
- this.def.numFrames = 0;
- }
- }
-
- this.pos = RDGE.vec3.zero();
- this.delta = RDGE.vec3.zero();
- this.rotate = 0.0;
- this.age = 0.0;
- this.lifespan = 0.0;
- this.velocity = RDGE.vec3.zero();
- this.gravity = RDGE.vec3.zero();
- this.frame = 0;
- this.frameCount = 0;
- this.lastPos = RDGE.vec3.zero();
- this.state = 0;
- this.hide = false;
- this.color = RDGE.vec4.zero();
-
- this.randomize = function (min, max) {
- return min + (max - min) * Math.random();
- };
- this.rate = this.randomize(-1.0, 1.0);
-
- this.randomize3 = function (min, max) {
- return [this.randomize(min[0], max[0]),
- this.randomize(min[1], max[1]),
- this.randomize(min[2], max[2])];
- };
-
- this.spawn = function (spawnMatrix) {
- if (this.def.initialframe == undefined) {
- this.frame = this.id % this.def.numFrames;
- } else {
- this.frame = this.randomize(this.def.initialframe[0], this.def.initialframe[1]);
- }
- this.pos = this.randomize3(this.def.initialpos[0], this.def.initialpos[1]);
- if (this.def.worldSpace) {
- // calculate the initial position in world space.
- this.pos = RDGE.mat4.transformPoint(spawnMatrix, this.pos);
- }
- // all other values are assumed to be defined in local or world space depending on
- // the particles worldSpace designation.
- var toRadians = Math.PI / 180.0;
- if (this.def.initialsize) {
- this.size = this.randomize(this.def.initialsize[0], this.def.initialsize[1]);
- } else {
- this.size = 1.0;
- }
- this.velocity = this.randomize3(this.def.initialvel[0], this.def.initialvel[1]);
- this.gravity = [this.def.gravity[0], this.def.gravity[1], this.def.gravity[2]];
- this.rotate = this.randomize(this.def.initialrot[0] * toRadians, this.def.initialrot[1] * toRadians);
- this.lifespan = this.randomize(this.def.lifespan[0], this.def.lifespan[1]);
- this.age = 0.0;
- this.delta = [0.0, 0.0, 0.0];
- this.lastPos = RDGE.vec3.add(this.pos, RDGE.vec3.scale(this.velocity, -1.0 / 30.0));
- this.color = [1, 1, 1, 1]; //RDGE.vec4.random( [0.0, 0.0, 0.0, 1.0], [1.0, 1.0, 1.0, 1.0] );
- };
-};
-
-// double buffered array utility class
-RDGE.DoubleBuffer = function (arrType, size) {
- this.buffer = {};
- this.buffer[0] = new arrType(size);
- this.buffer[1] = new arrType(size);
- this.bufferIndex = 0;
-
- this.flip = function () {
- this.bufferIndex = 1 - this.bufferIndex;
- }
- this.front = function () {
- return this.buffer[this.bufferIndex];
- }
- this.back = function () {
- return this.buffer[1 - this.bufferIndex];
- }
-};
-
-
-// cycling buffer
-RDGE.particleBuffer = function (pdef, emitter, size) {
- var renderer = RDGE.globals.engine.getContext().renderer;
- var ctx = renderer.ctx;
-
- s_particleShader = new RDGE.jshader();
- s_particleShader.def = {
- 'shaders': {
- 'defaultVShader': "assets/shaders/particle_vshader.glsl",
- 'defaultFShader': "assets/shaders/particle_fshader.glsl"
- },
- 'techniques': {
- 'defaultTechnique': [{
- 'vshader': 'defaultVShader',
- 'fshader': 'defaultFShader',
- 'attributes': {
- 'a_pos': { 'type': 'vec4' },
- 'a_posId': { 'type': 'float' },
- 'a_rotation': { 'type': 'float' },
- 'a_size': { 'type': 'float' },
- 'a_color': { 'type': 'vec4' }
- },
- 'params': {
- 'u_projMatrix': { 'type': 'mat4' },
- 'u_viewMatrix': { 'type': 'mat4' },
- 'u_worldMatrix': { 'type': 'mat4' },
- 'u_particleSizeX': { 'type': 'vec4' },
- 'u_particleSizeY': { 'type': 'vec4' },
- 'u_particleRot': { 'type': 'vec4' },
- 'u_particleColors': { 'type': 'mat4' },
- 'u_textureSize': { 'type': 'vec2' },
- 'u_frameSize': { 'type': 'vec2' },
- 's_texture0': { 'type': 'tex2d' }
- // 's_texture1' : { 'type' : 'tex2d' }
- }
- }]
- }
- }
- s_particleShader.init();
- s_particleTextures = {};
-
- this.shader = s_particleShader;
- this.owner = emitter;
- if (pdef.texture && s_particleTextures[pdef.texture] == undefined) {
- s_particleTextures[pdef.texture] = renderer.createTexture(pdef.texture);
- if (!pdef.textureSize || !pdef.frameSize) {
- pdef.textureSize = [];
- pdef.textureSize[0] = s_particleTextures[pdef.texture].image.width;
- pdef.textureSize[1] = s_particleTextures[pdef.texture].image.height;
-
- }
-
- if (!pdef.frameSize) {
- pdef.frameSize = [];
- pdef.frameSize[0] = s_particleTextures[pdef.texture].image.width;
- pdef.frameSize[1] = s_particleTextures[pdef.texture].image.height;
- }
- }
- if (pdef.texture2 && s_particleTextures[pdef.texture2] == undefined) {
- s_particleTextures[pdef.texture2] = renderer.createTexture(pdef.texture2);
- }
- this.texture = s_particleTextures[pdef.texture];
- this.texture2 = s_particleTextures[pdef.texture2];
- this.bounds = {};
- this.bounds.min = RDGE.vec3.zero();
- this.bounds.max = RDGE.vec3.zero();
-
- this.srcBlend = pdef.srcBlend;
- this.dstBlend = pdef.dstBlend;
-
- this.particles = new Array();
-
- this.posBuffer = new RDGE.DoubleBuffer(Float32Array, 16 * size); // 4 positions per particle, 4 components per position (particle age in w)
- this.posIdBuffer = new Float32Array(4 * size);
- this.sizeBuffer = new RDGE.DoubleBuffer(Float32Array, 4 * size);
- this.rotBuffer = new RDGE.DoubleBuffer(Float32Array, 4 * size);
- this.colorBuffer = new RDGE.DoubleBuffer(Float32Array, 16 * size);
- this.indexBuffer = new RDGE.DoubleBuffer(Uint16Array, 6 * size);
- this.indexBuffer.front().numIndices = 0;
- this.indexBuffer.back().numIndices = 0;
-
- for (i = 0; i < size; ++i) {
- this.particles.push(new RDGE.particle(pdef, i));
-
- // initialize double buffers.
- // the first pass will init the front buffers.
- // the second pass will init the back buffers.
- for (j = 0; j < 2; ++j) {
- // init position buffer
- var pfb = this.posBuffer.front();
- var i16 = i * 16;
- for (j = 0; j < 4; ++j) {
- var cmpBaseIndex = i16 + j * 4;
- pfb[cmpBaseIndex + 0] = 0;
- pfb[cmpBaseIndex + 1] = 0;
- pfb[cmpBaseIndex + 2] = 0;
- pfb[cmpBaseIndex + 3] = 1;
- }
-
- // init rotation buffer
- var i4 = i * 4;
- var rfb = this.rotBuffer.front();
- rfb[i4 + 0] = 0;
- rfb[i4 + 1] = 0;
- rfb[i4 + 2] = 0;
- rfb[i4 + 3] = 0;
-
- // init rotation buffer
- var i4 = i * 4;
- var sfb = this.sizeBuffer.front();
- rfb[i4 + 0] = 1;
- rfb[i4 + 1] = 1;
- rfb[i4 + 2] = 1;
- rfb[i4 + 3] = 1;
-
- // init color buffer
- var i4 = i * 4;
- var cfb = this.colorBuffer.front();
- cfb[i4] = 0xFFFFFF;
-
- // init index buffer
- var ifb = this.indexBuffer.front();
- var i6 = i * 6;
- ifb[i6 + 0] = i4 + 1;
- ifb[i6 + 1] = i4 + 0;
- ifb[i6 + 2] = i4 + 3;
- ifb[i6 + 3] = i4 + 1;
- ifb[i6 + 4] = i4 + 3;
- ifb[i6 + 5] = i4 + 2;
-
- // flip buffers
- this.posBuffer.flip();
- this.rotBuffer.flip();
- this.indexBuffer.flip();
- }
-
- var i4 = i * 4;
- this.posIdBuffer[i4 + 0] = 0;
- this.posIdBuffer[i4 + 1] = 1;
- this.posIdBuffer[i4 + 2] = 2;
- this.posIdBuffer[i4 + 3] = 3;
- }
-
- this.posBufferObject = ctx.createBuffer();
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this.posBufferObject);
- ctx.bufferData(ctx.ARRAY_BUFFER, this.posBuffer.front(), ctx.DYNAMIC_DRAW);
-
- this.posIdBufferObject = ctx.createBuffer();
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this.posIdBufferObject);
- ctx.bufferData(ctx.ARRAY_BUFFER, this.posIdBuffer, ctx.DYNAMIC_DRAW);
-
- this.rotBufferObject = ctx.createBuffer();
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this.rotBufferObject);
- ctx.bufferData(ctx.ARRAY_BUFFER, this.rotBuffer.front(), ctx.DYNAMIC_DRAW);
-
- this.sizeBufferObject = ctx.createBuffer();
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this.sizeBufferObject);
- ctx.bufferData(ctx.ARRAY_BUFFER, this.sizeBuffer.front(), ctx.DYNAMIC_DRAW);
-
- this.colorBufferObject = ctx.createBuffer();
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this.colorBufferObject);
- ctx.bufferData(ctx.ARRAY_BUFFER, this.colorBuffer.front(), ctx.DYNAMIC_DRAW);
-
- this.indexBufferObject = ctx.createBuffer();
- ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, this.indexBufferObject);
- ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, this.indexBuffer.front(), ctx.DYNAMIC_DRAW);
-
- this.start = 0;
- this.end = 0;
- this.cap = size;
-
- this.kill = function () {
- this.start++;
- if (this.start > (this.cap - 1))
- this.start = 0;
- };
-
- this.emit = function (parent) {
- this.end++;
- if (this.end >= this.cap) {
- this.end = 0;
- }
- if (this.end == this.start) {
- this.kill();
- }
- this.particles[this.end].spawn(this.owner.world);
- };
-
- this.sync = function () {
- this.posBuffer.flip();
- this.rotBuffer.flip();
- this.sizeBuffer.flip();
- this.colorBuffer.flip();
- this.indexBuffer.flip();
-
- // update the back buffer.
- var dstPosBuffer = this.posBuffer.back();
- var dstRotBuffer = this.rotBuffer.back();
- var dstSizeBuffer = this.sizeBuffer.back();
- var dstColorBuffer = this.colorBuffer.back();
- var dstIdxBuffer = this.indexBuffer.back();
-
- var bmin = this.bounds.min;
- var bmax = this.bounds.max;
-
- bmin[0] = 1e10;
- bmin[1] = 1e10;
- bmin[2] = 1e10;
-
- bmax[0] = -1e10;
- bmax[1] = -1e10;
- bmax[2] = -1e10;
-
- var numIndices = 0;
- var i = this.start;
- while (1) {
- var x, y, z, w;
- var p = this.particles[i];
- var age = (p.age / p.lifespan); // normalized age
- // combine frame number and age and store in w.
- // to decode :
- // frame = floor( w );
- // age = fract( w );
- var pw = Math.min(age, 0.999) + Math.floor(p.frame);
- if (age < 1.0) { // || (pdef.persist != undefined && pdef.persist == true)) {
- var px = p.pos[0];
- var py = p.pos[1];
- var pz = p.pos[2];
-
- if (px > bmax[0]) { bmax[0] = px; }
- if (px > bmax[1]) { bmax[1] = py; }
- if (px > bmax[2]) { bmax[2] = pz; }
-
- if (px < bmin[0]) { bmin[0] = px; }
- if (px < bmin[1]) { bmin[1] = py; }
- if (px < bmin[2]) { bmin[2] = pz; }
-
- var i16 = i * 16;
- for (j = 0; j < 4; ++j) {
- var cmpBaseIndex = i16 + j * 4;
- dstPosBuffer[cmpBaseIndex + 0] = px;
- dstPosBuffer[cmpBaseIndex + 1] = py;
- dstPosBuffer[cmpBaseIndex + 2] = pz;
- dstPosBuffer[cmpBaseIndex + 3] = pw;
- }
-
- var i4 = i * 4;
- var r = 0.0;
- if (pdef.velocityAligned) {
- r = Math.atan2(p.delta[0], p.delta[1]);
- }
- dstRotBuffer[i4 + 0] = p.rotate + r;
- dstRotBuffer[i4 + 1] = p.rotate + r;
- dstRotBuffer[i4 + 2] = p.rotate + r;
- dstRotBuffer[i4 + 3] = p.rotate + r;
-
- dstSizeBuffer[i4 + 0] = p.size;
- dstSizeBuffer[i4 + 1] = p.size;
- dstSizeBuffer[i4 + 2] = p.size;
- dstSizeBuffer[i4 + 3] = p.size;
-
- var i16 = i * 16;
- for (j = 0; j < 4; ++j) {
- var cmpBaseIndex = i16 + j * 4;
- dstColorBuffer[cmpBaseIndex + 0] = p.color[0];
- dstColorBuffer[cmpBaseIndex + 1] = p.color[1];
- dstColorBuffer[cmpBaseIndex + 2] = p.color[2];
- dstColorBuffer[cmpBaseIndex + 3] = p.color[3];
- }
-
- dstIdxBuffer[numIndices + 0] = i4 + 1;
- dstIdxBuffer[numIndices + 1] = i4 + 0;
- dstIdxBuffer[numIndices + 2] = i4 + 3;
- dstIdxBuffer[numIndices + 3] = i4 + 1;
- dstIdxBuffer[numIndices + 4] = i4 + 2;
- dstIdxBuffer[numIndices + 5] = i4 + 3;
-
- numIndices += 6;
- }
-
- if (i == this.end) {
- break;
- }
- i++;
- if (i == this.cap && this.end != this.cap) {
- i = 0;
- }
- }
- dstIdxBuffer.numIndices = numIndices;
-
- if (!pdef.worldSpace) {
- // calculate the world space bounds from local space.
- // first transform our local space min-max coordinates to world space.
- var bminW = RDGE.mat4.mul(bmin, this.owner.world);
- var bmaxW = RDGE.mat4.mul(bmax, this.owner.world);
-
- // now calculate axis aligned bounds based on the world space coordinates.
- if (bmaxW[0] > bmax[0]) { bmax[0] = bmaxW[0]; }
- if (bmaxW[1] > bmax[1]) { bmax[1] = bmaxW[1]; }
- if (bmaxW[2] > bmax[2]) { bmax[2] = bmaxW[2]; }
- if (bminW[0] < bmin[0]) { bmin[0] = bminW[0]; }
- if (bminW[1] < bmin[1]) { bmin[1] = bminW[1]; }
- if (bminW[2] < bmin[2]) { bmin[2] = bminW[2]; }
- }
- };
-
- this.update = function (dt, movers) {
- var i = this.start;
- if (pdef.persist != undefined && pdef.persist == false) {
- while (1) {
- var p = this.particles[i];
- if (p.age < p.lifespan)
- break;
- this.kill();
- if (i == this.end) {
- break;
- }
- i++;
- if (i == this.cap && this.end != this.cap) {
- i = 0;
- }
- }
- }
-
- i = this.start;
- while (1) {
- var p = this.particles[i];
- var j = movers.length;
- while (j) {
- movers[--j].move(p, dt);
- }
- if (i == this.end) {
- break;
- }
- i++;
- if (i == this.cap && this.end != this.cap) {
- i = 0;
- }
- }
-
- this.sync();
- };
-
- this.render = function () {
-
- var renderer = RDGE.globals.engine.getContext().renderer;
- var ctx = RDGE.globals.engine.getContext().renderer.ctx;
-
- // draw using the front buffer.
- var srcPosBuffer = this.posBuffer.front();
- var srcRotBuffer = this.rotBuffer.front();
- var srcSizeBuffer = this.sizeBuffer.front();
- var srcColBuffer = this.colorBuffer.front();
- var srcIdxBuffer = this.indexBuffer.front();
-
- if (srcIdxBuffer.numIndices > 0) {
- // set modelview matrix
- var shaderparms = this.shader.defaultTechnique;
- var activeCam = renderer.cameraManager().getActiveCamera();
- if (pdef.worldSpace) {
- shaderparms.u_viewMatrix.set(activeCam.view);
- shaderparms.u_worldMatrix.set(RDGE.mat4.identity());
- }
- else {
- shaderparms.u_viewMatrix.set(activeCam.view);
- shaderparms.u_worldMatrix.set(this.owner.world);
- // shaderparms.u_mvMatrix.set(RDGE.mat4.mul(this.owner.world, activeCam.view));
- }
- shaderparms.u_projMatrix.set(activeCam.proj);
-
- shaderparms.u_particleSizeX.set(pdef.sizeX);
- shaderparms.u_particleSizeY.set(pdef.sizeY);
- shaderparms.u_particleRot.set(RDGE.vec4.scale(pdef.rotation, Math.PI / 180.0));
- shaderparms.u_particleColors.set(RDGE.mat4.transpose(pdef.colors));
- shaderparms.u_textureSize.set(pdef.textureSize);
- shaderparms.u_frameSize.set(pdef.frameSize);
- shaderparms.s_texture0.set(this.texture);
- // shaderparms.s_texture1.set(null);
-
- var passCount = this.shader.begin();
- for (passIdx = 0; passIdx < passCount; ++passIdx) {
- this.shader.beginPass(passIdx);
-
- // setup render states
- if (!pdef.depthTest) {
- ctx.disable(ctx.DEPTH_TEST);
- }
-
- ctx.enable(ctx.BLEND);
- ctx.blendFunc(ctx[pdef.srcBlend], ctx[pdef.dstBlend]);
-
- ctx.enableVertexAttribArray(0);
- ctx.enableVertexAttribArray(1);
- ctx.enableVertexAttribArray(2);
- ctx.enableVertexAttribArray(3);
- ctx.enableVertexAttribArray(4);
-
- // update position buffer
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this.posBufferObject);
- ctx.bufferSubData(ctx.ARRAY_BUFFER, 0, srcPosBuffer);
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this.posBufferObject);
- ctx.vertexAttribPointer(0, 4, ctx.FLOAT, false, 0, 0);
-
- // position id buffer
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this.posIdBufferObject);
- ctx.vertexAttribPointer(1, 1, ctx.FLOAT, false, 0, 0);
-
- // update rotation buffer
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this.rotBufferObject);
- ctx.bufferSubData(ctx.ARRAY_BUFFER, 0, srcRotBuffer);
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this.rotBufferObject);
- ctx.vertexAttribPointer(2, 1, ctx.FLOAT, false, 0, 0);
-
- // update size buffer
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this.sizeBufferObject);
- ctx.bufferSubData(ctx.ARRAY_BUFFER, 0, srcSizeBuffer);
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this.sizeBufferObject);
- ctx.vertexAttribPointer(3, 1, ctx.FLOAT, false, 0, 0);
-
- // update color buffer
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this.colorBufferObject);
- ctx.bufferSubData(ctx.ARRAY_BUFFER, 0, srcColBuffer);
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this.colorBufferObject);
- ctx.vertexAttribPointer(4, 4, ctx.FLOAT, false, 0, 0);
-
- // update index buffer
- ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, this.indexBufferObject);
- ctx.bufferSubData(ctx.ELEMENT_ARRAY_BUFFER, 0, srcIdxBuffer);
-
- // draw
- ctx.drawElements(ctx.TRIANGLES, srcIdxBuffer.numIndices, ctx.UNSIGNED_SHORT, 0);
-
- // restore render states
- ctx.disable(ctx.BLEND);
- if (!pdef.depthTest) {
- ctx.enable(ctx.DEPTH_TEST);
- }
- ctx.blendFunc(ctx.ONE, ctx.ZERO);
-
- this.shader.endPass();
- }
- this.shader.end();
- }
- };
-};
-
-particleMoverDefault = function () {
- this.move = function (particle, dt) {
- particle.age += dt;
-
- if (particle.def.persist) {
- if (particle.def.cycle && particle.age > particle.lifespan * 0.99) {
- particle.age -= particle.lifespan * 0.99;
- } else {
- particle.age = Math.min(particle.age, particle.lifespan * 0.99);
- }
-
- } else {
- particle.age = Math.min(particle.age, particle.lifespan);
- }
-
- if (particle.def.frameRate > 0.0) {
- particle.frame += particle.def.frameRate * dt; //Math.min( particle.def.numFrames - 1, particle.frame + particle.def.frameRate * dt );
- if (particle.def.frameLoop) {
- particle.frame = particle.frame % particle.def.numFrames;
- }
- else {
- particle.frame = Math.min(particle.def.numFrames - 1, particle.frame)
- }
- }
-
- var oldPos = particle.pos;
- var pg = particle.gravity;
- var pv = particle.velocity;
- var pp = particle.pos;
- var pd = particle.delta;
-
- pv[0] += pg[0] * dt;
- pv[1] += pg[1] * dt;
- pv[2] += pg[2] * dt;
- pp[0] = pp[0] + pv[0] * dt;
- pp[1] = pp[1] + pv[1] * dt;
- pp[2] = pp[2] + pv[2] * dt;
- pd[0] = pp[0] - oldPos[0];
- pd[1] = pp[1] - oldPos[1];
- pd[2] = pp[2] - oldPos[2];
-
- // particle turbulence
- if (particle.def.turbulence) {
- var tMin = particle.def.turbulence[0];
- var tMax = particle.def.turbulence[1];
- var tx = Math.random() * (tMax[0] - tMin[0]) + tMin[0];
- var ty = Math.random() * (tMax[1] - tMin[1]) + tMin[1];
- var tz = Math.random() * (tMax[2] - tMin[2]) + tMin[2];
- pv[0] += tx;
- pv[1] += ty;
- pv[2] += tz;
- }
-
- // particle jitter
- if (particle.def.jitter) {
- var jMin = particle.def.jitter[0];
- var jMax = particle.def.jitter[1];
- var jx = Math.random() * (jMax[0] - jMin[0]) + jMin[0];
- var jy = Math.random() * (jMax[1] - jMin[1]) + jMin[1];
- var jz = Math.random() * (jMax[2] - jMin[2]) + jMin[2];
- pp[0] += jx;
- pp[1] += jy;
- pp[2] += jz;
- }
- };
-};
-
-RDGE.particleEmitter = function (def) {
- this.def = def;
- this.world = RDGE.mat4.identity();
- this.pbuffer = new RDGE.particleBuffer(this.def.particle, this, this.def.maxParticles);
-
- this.movers = new Array();
- var creatorFunc = particleMoverDefault;
- if (def.particle.moverFunc) {
- creatorFunc = eval(def.particle.moverFunc);
- }
- this.movers.push(new creatorFunc());
-
- this.localTime = 0.0;
- this.lastEmitTime = 0.0;
- this.emitCounter = 0;
- this.firstUpdate = true;
-
- this.attachToNode = function (node) {
- this.controller = node;
- };
-
- this.update = function (dt) {
- this.localTime += dt;
- if (this.firstUpdate) {
- this.lastEmitTime = this.localTime;
- this.firstUpdate = false;
- }
-
- if (this.def.emit != undefined && this.def.emit == false) {
- this.lastEmitTime = this.localTime - 1.0 / this.def.emitRate;
- }
-
- // this needs to be handled differently..
- var maxParticles = this.def.maxParticles;
- var emitOnce = this.def.emitOnce;
- var emitCount = (this.def.emit == undefined || this.def.emit == true) ? Math.floor((this.localTime - this.lastEmitTime) * this.def.emitRate) : 0;
- while (emitCount--) {
- if (emitOnce && this.emitCounter++ >= maxParticles) {
- break;
- }
- this.pbuffer.emit(this.world);
- this.lastEmitTime = this.localTime;
- }
-
- this.pbuffer.update(dt, this.movers);
- };
-};
-
-RDGE.particleSys = function (addr) {
- loaded = (typeof loaded == 'undefined') ? {} : loaded;
-
- this.def = null;
- this.node = null;
- this.world = RDGE.mat4.identity();
- this.emitters = {};
-
- // load particle system definition at addr
- this.init = function () {
- if (this.def == null) {
- return;
- }
- for (e in this.def.emitters) {
- this.emitters[e] = new RDGE.particleEmitter(this.def.emitters[e]);
- }
-
- this.bounds = {};
- this.bounds.min = RDGE.vec3.zero();
- this.bounds.max = RDGE.vec3.zero();
- };
-
- if (!loaded[addr]) {
- var request = new XMLHttpRequest();
- request.sender = this;
-
- request.onreadystatechange = function () {
- if (request.readyState == 4) {
- if (request.status == 200 || window.location.href.indexOf("http") == -1) {
- request.sender.def = eval("(" + request.responseText + ")"); //retrieve result as an JavaScript object
- loaded[addr] = request.sender.def;
- request.sender.init();
- }
- else {
- alert("An error has occured loading particle system.");
- }
- }
- }
-
- request.open("GET", addr, true);
- request.send(null);
- } else {
- this.def = loaded[addr];
- this.init();
- }
-
- this.update = function (dt) {
- if (this.def == null) {
- return;
- }
-
- var bmin = this.bounds.min;
- var bmax = this.bounds.max;
-
- bmin[0] = 1e10;
- bmin[1] = 1e10;
- bmin[2] = 1e10;
-
- bmax[0] = -1e10;
- bmax[1] = -1e10;
- bmax[2] = -1e10;
-
- var parent = this.node ? this.node.world : this.world;
- for (em in this.emitters) {
- var emitter = this.emitters[em];
- emitter.world = parent;
- emitter.update(dt);
-
- var emin = emitter.pbuffer.bounds.min;
- var emax = emitter.pbuffer.bounds.max;
-
- // calculate a bounds that fits all particles.
- if (emin[0] < bmin[0]) { bmin[0] = emin[0]; }
- if (emin[1] < bmin[1]) { bmin[1] = emin[1]; }
- if (emin[2] < bmin[2]) { bmin[2] = emin[2]; }
- if (emax[0] > bmax[0]) { bmax[0] = emax[0]; }
- if (emax[1] > bmax[1]) { bmax[1] = emax[1]; }
- if (emax[2] > bmax[2]) { bmax[2] = emax[2]; }
- }
- };
-
- this.render = function () {
- if (this.def == null) {
- return;
- }
- for (em in this.emitters) {
- var pbuffer = this.emitters[em].pbuffer;
- pbuffer.render();
- }
- };
-
- this.attachToNode = function (node) {
- this.node = node;
- };
-};
-
-RDGE.g_particleSystemManager = new RDGE.objectManager();
-RDGE.g_particleSystemManager.update = function (dt) {
- var i = this.objects.length - 1;
- while (i >= 0) {
- var psys = this.objects[i];
- if (psys) {
- psys.update(dt);
- }
- i--;
- }
-};
-
-RDGE.g_particleSystemManager.render = function (dt) {
- var i = 0;
- while (i < this.objects.length) {
- var psys = this.objects[i];
- if (psys) {
- psys.render();
- }
- i++;
- }
-};
-
+/*
+Copyright (c) 2012, Motorola Mobility, Inc
+All Rights Reserved.
+BSD License.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ - Neither the name of Motorola Mobility nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+ */
+
+var RDGE = RDGE || {};
+
+RDGE.particle = function (def, id) {
+ this.id = id;
+ this.def = def;
+ if (this.def.numFrames == undefined) {
+ if (this.def.textureSize && this.def.frameSize) {
+ this.def.numFrames = (this.def.textureSize[0] / this.def.frameSize[0]) * (this.def.textureSize[1] / this.def.frameSize[1]);
+ } else {
+ this.def.numFrames = 0;
+ }
+ }
+
+ this.pos = RDGE.vec3.zero();
+ this.delta = RDGE.vec3.zero();
+ this.rotate = 0.0;
+ this.age = 0.0;
+ this.lifespan = 0.0;
+ this.velocity = RDGE.vec3.zero();
+ this.gravity = RDGE.vec3.zero();
+ this.frame = 0;
+ this.frameCount = 0;
+ this.lastPos = RDGE.vec3.zero();
+ this.state = 0;
+ this.hide = false;
+ this.color = RDGE.vec4.zero();
+
+ this.randomize = function (min, max) {
+ return min + (max - min) * Math.random();
+ };
+ this.rate = this.randomize(-1.0, 1.0);
+
+ this.randomize3 = function (min, max) {
+ return [this.randomize(min[0], max[0]),
+ this.randomize(min[1], max[1]),
+ this.randomize(min[2], max[2])];
+ };
+
+ this.spawn = function (spawnMatrix) {
+ if (this.def.initialframe == undefined) {
+ this.frame = this.id % this.def.numFrames;
+ } else {
+ this.frame = this.randomize(this.def.initialframe[0], this.def.initialframe[1]);
+ }
+ this.pos = this.randomize3(this.def.initialpos[0], this.def.initialpos[1]);
+ if (this.def.worldSpace) {
+ // calculate the initial position in world space.
+ this.pos = RDGE.mat4.transformPoint(spawnMatrix, this.pos);
+ }
+ // all other values are assumed to be defined in local or world space depending on
+ // the particles worldSpace designation.
+ var toRadians = Math.PI / 180.0;
+ if (this.def.initialsize) {
+ this.size = this.randomize(this.def.initialsize[0], this.def.initialsize[1]);
+ } else {
+ this.size = 1.0;
+ }
+ this.velocity = this.randomize3(this.def.initialvel[0], this.def.initialvel[1]);
+ this.gravity = [this.def.gravity[0], this.def.gravity[1], this.def.gravity[2]];
+ this.rotate = this.randomize(this.def.initialrot[0] * toRadians, this.def.initialrot[1] * toRadians);
+ this.lifespan = this.randomize(this.def.lifespan[0], this.def.lifespan[1]);
+ this.age = 0.0;
+ this.delta = [0.0, 0.0, 0.0];
+ this.lastPos = RDGE.vec3.add(this.pos, RDGE.vec3.scale(this.velocity, -1.0 / 30.0));
+ this.color = [1, 1, 1, 1]; //RDGE.vec4.random( [0.0, 0.0, 0.0, 1.0], [1.0, 1.0, 1.0, 1.0] );
+ };
+};
+
+// double buffered array utility class
+RDGE.DoubleBuffer = function (arrType, size) {
+ this.buffer = {};
+ this.buffer[0] = new arrType(size);
+ this.buffer[1] = new arrType(size);
+ this.bufferIndex = 0;
+
+ this.flip = function () {
+ this.bufferIndex = 1 - this.bufferIndex;
+ }
+ this.front = function () {
+ return this.buffer[this.bufferIndex];
+ }
+ this.back = function () {
+ return this.buffer[1 - this.bufferIndex];
+ }
+};
+
+
+// cycling buffer
+RDGE.particleBuffer = function (pdef, emitter, size) {
+ var renderer = RDGE.globals.engine.getContext().renderer;
+ var ctx = renderer.ctx;
+
+ s_particleShader = new RDGE.jshader();
+ s_particleShader.def = {
+ 'shaders': {
+ 'defaultVShader': "assets/shaders/particle_vshader.glsl",
+ 'defaultFShader': "assets/shaders/particle_fshader.glsl"
+ },
+ 'techniques': {
+ 'defaultTechnique': [{
+ 'vshader': 'defaultVShader',
+ 'fshader': 'defaultFShader',
+ 'attributes': {
+ 'a_pos': { 'type': 'vec4' },
+ 'a_posId': { 'type': 'float' },
+ 'a_rotation': { 'type': 'float' },
+ 'a_size': { 'type': 'float' },
+ 'a_color': { 'type': 'vec4' }
+ },
+ 'params': {
+ 'u_projMatrix': { 'type': 'mat4' },
+ 'u_viewMatrix': { 'type': 'mat4' },
+ 'u_worldMatrix': { 'type': 'mat4' },
+ 'u_particleSizeX': { 'type': 'vec4' },
+ 'u_particleSizeY': { 'type': 'vec4' },
+ 'u_particleRot': { 'type': 'vec4' },
+ 'u_particleColors': { 'type': 'mat4' },
+ 'u_textureSize': { 'type': 'vec2' },
+ 'u_frameSize': { 'type': 'vec2' },
+ 's_texture0': { 'type': 'tex2d' }
+ // 's_texture1' : { 'type' : 'tex2d' }
+ }
+ }]
+ }
+ }
+ s_particleShader.init();
+ s_particleTextures = {};
+
+ this.shader = s_particleShader;
+ this.owner = emitter;
+ if (pdef.texture && s_particleTextures[pdef.texture] == undefined) {
+ s_particleTextures[pdef.texture] = renderer.createTexture(pdef.texture);
+ if (!pdef.textureSize || !pdef.frameSize) {
+ pdef.textureSize = [];
+ pdef.textureSize[0] = s_particleTextures[pdef.texture].image.width;
+ pdef.textureSize[1] = s_particleTextures[pdef.texture].image.height;
+
+ }
+
+ if (!pdef.frameSize) {
+ pdef.frameSize = [];
+ pdef.frameSize[0] = s_particleTextures[pdef.texture].image.width;
+ pdef.frameSize[1] = s_particleTextures[pdef.texture].image.height;
+ }
+ }
+ if (pdef.texture2 && s_particleTextures[pdef.texture2] == undefined) {
+ s_particleTextures[pdef.texture2] = renderer.createTexture(pdef.texture2);
+ }
+ this.texture = s_particleTextures[pdef.texture];
+ this.texture2 = s_particleTextures[pdef.texture2];
+ this.bounds = {};
+ this.bounds.min = RDGE.vec3.zero();
+ this.bounds.max = RDGE.vec3.zero();
+
+ this.srcBlend = pdef.srcBlend;
+ this.dstBlend = pdef.dstBlend;
+
+ this.particles = new Array();
+
+ this.posBuffer = new RDGE.DoubleBuffer(Float32Array, 16 * size); // 4 positions per particle, 4 components per position (particle age in w)
+ this.posIdBuffer = new Float32Array(4 * size);
+ this.sizeBuffer = new RDGE.DoubleBuffer(Float32Array, 4 * size);
+ this.rotBuffer = new RDGE.DoubleBuffer(Float32Array, 4 * size);
+ this.colorBuffer = new RDGE.DoubleBuffer(Float32Array, 16 * size);
+ this.indexBuffer = new RDGE.DoubleBuffer(Uint16Array, 6 * size);
+ this.indexBuffer.front().numIndices = 0;
+ this.indexBuffer.back().numIndices = 0;
+
+ for (i = 0; i < size; ++i) {
+ this.particles.push(new RDGE.particle(pdef, i));
+
+ // initialize double buffers.
+ // the first pass will init the front buffers.
+ // the second pass will init the back buffers.
+ for (j = 0; j < 2; ++j) {
+ // init position buffer
+ var pfb = this.posBuffer.front();
+ var i16 = i * 16;
+ for (j = 0; j < 4; ++j) {
+ var cmpBaseIndex = i16 + j * 4;
+ pfb[cmpBaseIndex + 0] = 0;
+ pfb[cmpBaseIndex + 1] = 0;
+ pfb[cmpBaseIndex + 2] = 0;
+ pfb[cmpBaseIndex + 3] = 1;
+ }
+
+ // init rotation buffer
+ var i4 = i * 4;
+ var rfb = this.rotBuffer.front();
+ rfb[i4 + 0] = 0;
+ rfb[i4 + 1] = 0;
+ rfb[i4 + 2] = 0;
+ rfb[i4 + 3] = 0;
+
+ // init rotation buffer
+ var i4 = i * 4;
+ var sfb = this.sizeBuffer.front();
+ rfb[i4 + 0] = 1;
+ rfb[i4 + 1] = 1;
+ rfb[i4 + 2] = 1;
+ rfb[i4 + 3] = 1;
+
+ // init color buffer
+ var i4 = i * 4;
+ var cfb = this.colorBuffer.front();
+ cfb[i4] = 0xFFFFFF;
+
+ // init index buffer
+ var ifb = this.indexBuffer.front();
+ var i6 = i * 6;
+ ifb[i6 + 0] = i4 + 1;
+ ifb[i6 + 1] = i4 + 0;
+ ifb[i6 + 2] = i4 + 3;
+ ifb[i6 + 3] = i4 + 1;
+ ifb[i6 + 4] = i4 + 3;
+ ifb[i6 + 5] = i4 + 2;
+
+ // flip buffers
+ this.posBuffer.flip();
+ this.rotBuffer.flip();
+ this.indexBuffer.flip();
+ }
+
+ var i4 = i * 4;
+ this.posIdBuffer[i4 + 0] = 0;
+ this.posIdBuffer[i4 + 1] = 1;
+ this.posIdBuffer[i4 + 2] = 2;
+ this.posIdBuffer[i4 + 3] = 3;
+ }
+
+ this.posBufferObject = ctx.createBuffer();
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, this.posBufferObject);
+ ctx.bufferData(ctx.ARRAY_BUFFER, this.posBuffer.front(), ctx.DYNAMIC_DRAW);
+
+ this.posIdBufferObject = ctx.createBuffer();
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, this.posIdBufferObject);
+ ctx.bufferData(ctx.ARRAY_BUFFER, this.posIdBuffer, ctx.DYNAMIC_DRAW);
+
+ this.rotBufferObject = ctx.createBuffer();
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, this.rotBufferObject);
+ ctx.bufferData(ctx.ARRAY_BUFFER, this.rotBuffer.front(), ctx.DYNAMIC_DRAW);
+
+ this.sizeBufferObject = ctx.createBuffer();
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, this.sizeBufferObject);
+ ctx.bufferData(ctx.ARRAY_BUFFER, this.sizeBuffer.front(), ctx.DYNAMIC_DRAW);
+
+ this.colorBufferObject = ctx.createBuffer();
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, this.colorBufferObject);
+ ctx.bufferData(ctx.ARRAY_BUFFER, this.colorBuffer.front(), ctx.DYNAMIC_DRAW);
+
+ this.indexBufferObject = ctx.createBuffer();
+ ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, this.indexBufferObject);
+ ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, this.indexBuffer.front(), ctx.DYNAMIC_DRAW);
+
+ this.start = 0;
+ this.end = 0;
+ this.cap = size;
+
+ this.kill = function () {
+ this.start++;
+ if (this.start > (this.cap - 1))
+ this.start = 0;
+ };
+
+ this.emit = function (parent) {
+ this.end++;
+ if (this.end >= this.cap) {
+ this.end = 0;
+ }
+ if (this.end == this.start) {
+ this.kill();
+ }
+ this.particles[this.end].spawn(this.owner.world);
+ };
+
+ this.sync = function () {
+ this.posBuffer.flip();
+ this.rotBuffer.flip();
+ this.sizeBuffer.flip();
+ this.colorBuffer.flip();
+ this.indexBuffer.flip();
+
+ // update the back buffer.
+ var dstPosBuffer = this.posBuffer.back();
+ var dstRotBuffer = this.rotBuffer.back();
+ var dstSizeBuffer = this.sizeBuffer.back();
+ var dstColorBuffer = this.colorBuffer.back();
+ var dstIdxBuffer = this.indexBuffer.back();
+
+ var bmin = this.bounds.min;
+ var bmax = this.bounds.max;
+
+ bmin[0] = 1e10;
+ bmin[1] = 1e10;
+ bmin[2] = 1e10;
+
+ bmax[0] = -1e10;
+ bmax[1] = -1e10;
+ bmax[2] = -1e10;
+
+ var numIndices = 0;
+ var i = this.start;
+ while (1) {
+ var x, y, z, w;
+ var p = this.particles[i];
+ var age = (p.age / p.lifespan); // normalized age
+ // combine frame number and age and store in w.
+ // to decode :
+ // frame = floor( w );
+ // age = fract( w );
+ var pw = Math.min(age, 0.999) + Math.floor(p.frame);
+ if (age < 1.0) { // || (pdef.persist != undefined && pdef.persist == true)) {
+ var px = p.pos[0];
+ var py = p.pos[1];
+ var pz = p.pos[2];
+
+ if (px > bmax[0]) { bmax[0] = px; }
+ if (px > bmax[1]) { bmax[1] = py; }
+ if (px > bmax[2]) { bmax[2] = pz; }
+
+ if (px < bmin[0]) { bmin[0] = px; }
+ if (px < bmin[1]) { bmin[1] = py; }
+ if (px < bmin[2]) { bmin[2] = pz; }
+
+ var i16 = i * 16;
+ for (j = 0; j < 4; ++j) {
+ var cmpBaseIndex = i16 + j * 4;
+ dstPosBuffer[cmpBaseIndex + 0] = px;
+ dstPosBuffer[cmpBaseIndex + 1] = py;
+ dstPosBuffer[cmpBaseIndex + 2] = pz;
+ dstPosBuffer[cmpBaseIndex + 3] = pw;
+ }
+
+ var i4 = i * 4;
+ var r = 0.0;
+ if (pdef.velocityAligned) {
+ r = Math.atan2(p.delta[0], p.delta[1]);
+ }
+ dstRotBuffer[i4 + 0] = p.rotate + r;
+ dstRotBuffer[i4 + 1] = p.rotate + r;
+ dstRotBuffer[i4 + 2] = p.rotate + r;
+ dstRotBuffer[i4 + 3] = p.rotate + r;
+
+ dstSizeBuffer[i4 + 0] = p.size;
+ dstSizeBuffer[i4 + 1] = p.size;
+ dstSizeBuffer[i4 + 2] = p.size;
+ dstSizeBuffer[i4 + 3] = p.size;
+
+ var i16 = i * 16;
+ for (j = 0; j < 4; ++j) {
+ var cmpBaseIndex = i16 + j * 4;
+ dstColorBuffer[cmpBaseIndex + 0] = p.color[0];
+ dstColorBuffer[cmpBaseIndex + 1] = p.color[1];
+ dstColorBuffer[cmpBaseIndex + 2] = p.color[2];
+ dstColorBuffer[cmpBaseIndex + 3] = p.color[3];
+ }
+
+ dstIdxBuffer[numIndices + 0] = i4 + 1;
+ dstIdxBuffer[numIndices + 1] = i4 + 0;
+ dstIdxBuffer[numIndices + 2] = i4 + 3;
+ dstIdxBuffer[numIndices + 3] = i4 + 1;
+ dstIdxBuffer[numIndices + 4] = i4 + 2;
+ dstIdxBuffer[numIndices + 5] = i4 + 3;
+
+ numIndices += 6;
+ }
+
+ if (i == this.end) {
+ break;
+ }
+ i++;
+ if (i == this.cap && this.end != this.cap) {
+ i = 0;
+ }
+ }
+ dstIdxBuffer.numIndices = numIndices;
+
+ if (!pdef.worldSpace) {
+ // calculate the world space bounds from local space.
+ // first transform our local space min-max coordinates to world space.
+ var bminW = RDGE.mat4.mul(bmin, this.owner.world);
+ var bmaxW = RDGE.mat4.mul(bmax, this.owner.world);
+
+ // now calculate axis aligned bounds based on the world space coordinates.
+ if (bmaxW[0] > bmax[0]) { bmax[0] = bmaxW[0]; }
+ if (bmaxW[1] > bmax[1]) { bmax[1] = bmaxW[1]; }
+ if (bmaxW[2] > bmax[2]) { bmax[2] = bmaxW[2]; }
+ if (bminW[0] < bmin[0]) { bmin[0] = bminW[0]; }
+ if (bminW[1] < bmin[1]) { bmin[1] = bminW[1]; }
+ if (bminW[2] < bmin[2]) { bmin[2] = bminW[2]; }
+ }
+ };
+
+ this.update = function (dt, movers) {
+ var i = this.start;
+ if (pdef.persist != undefined && pdef.persist == false) {
+ while (1) {
+ var p = this.particles[i];
+ if (p.age < p.lifespan)
+ break;
+ this.kill();
+ if (i == this.end) {
+ break;
+ }
+ i++;
+ if (i == this.cap && this.end != this.cap) {
+ i = 0;
+ }
+ }
+ }
+
+ i = this.start;
+ while (1) {
+ var p = this.particles[i];
+ var j = movers.length;
+ while (j) {
+ movers[--j].move(p, dt);
+ }
+ if (i == this.end) {
+ break;
+ }
+ i++;
+ if (i == this.cap && this.end != this.cap) {
+ i = 0;
+ }
+ }
+
+ this.sync();
+ };
+
+ this.render = function () {
+
+ var renderer = RDGE.globals.engine.getContext().renderer;
+ var ctx = RDGE.globals.engine.getContext().renderer.ctx;
+
+ // draw using the front buffer.
+ var srcPosBuffer = this.posBuffer.front();
+ var srcRotBuffer = this.rotBuffer.front();
+ var srcSizeBuffer = this.sizeBuffer.front();
+ var srcColBuffer = this.colorBuffer.front();
+ var srcIdxBuffer = this.indexBuffer.front();
+
+ if (srcIdxBuffer.numIndices > 0) {
+ // set modelview matrix
+ var shaderparms = this.shader.defaultTechnique;
+ var activeCam = renderer.cameraManager().getActiveCamera();
+ if (pdef.worldSpace) {
+ shaderparms.u_viewMatrix.set(activeCam.view);
+ shaderparms.u_worldMatrix.set(RDGE.mat4.identity());
+ }
+ else {
+ shaderparms.u_viewMatrix.set(activeCam.view);
+ shaderparms.u_worldMatrix.set(this.owner.world);
+ // shaderparms.u_mvMatrix.set(RDGE.mat4.mul(this.owner.world, activeCam.view));
+ }
+ shaderparms.u_projMatrix.set(activeCam.proj);
+
+ shaderparms.u_particleSizeX.set(pdef.sizeX);
+ shaderparms.u_particleSizeY.set(pdef.sizeY);
+ shaderparms.u_particleRot.set(RDGE.vec4.scale(pdef.rotation, Math.PI / 180.0));
+ shaderparms.u_particleColors.set(RDGE.mat4.transpose(pdef.colors));
+ shaderparms.u_textureSize.set(pdef.textureSize);
+ shaderparms.u_frameSize.set(pdef.frameSize);
+ shaderparms.s_texture0.set(this.texture);
+ // shaderparms.s_texture1.set(null);
+
+ var passCount = this.shader.begin();
+ for (passIdx = 0; passIdx < passCount; ++passIdx) {
+ this.shader.beginPass(passIdx);
+
+ // setup render states
+ if (!pdef.depthTest) {
+ ctx.disable(ctx.DEPTH_TEST);
+ }
+
+ ctx.enable(ctx.BLEND);
+ ctx.blendFunc(ctx[pdef.srcBlend], ctx[pdef.dstBlend]);
+
+ ctx.enableVertexAttribArray(0);
+ ctx.enableVertexAttribArray(1);
+ ctx.enableVertexAttribArray(2);
+ ctx.enableVertexAttribArray(3);
+ ctx.enableVertexAttribArray(4);
+
+ // update position buffer
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, this.posBufferObject);
+ ctx.bufferSubData(ctx.ARRAY_BUFFER, 0, srcPosBuffer);
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, this.posBufferObject);
+ ctx.vertexAttribPointer(0, 4, ctx.FLOAT, false, 0, 0);
+
+ // position id buffer
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, this.posIdBufferObject);
+ ctx.vertexAttribPointer(1, 1, ctx.FLOAT, false, 0, 0);
+
+ // update rotation buffer
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, this.rotBufferObject);
+ ctx.bufferSubData(ctx.ARRAY_BUFFER, 0, srcRotBuffer);
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, this.rotBufferObject);
+ ctx.vertexAttribPointer(2, 1, ctx.FLOAT, false, 0, 0);
+
+ // update size buffer
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, this.sizeBufferObject);
+ ctx.bufferSubData(ctx.ARRAY_BUFFER, 0, srcSizeBuffer);
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, this.sizeBufferObject);
+ ctx.vertexAttribPointer(3, 1, ctx.FLOAT, false, 0, 0);
+
+ // update color buffer
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, this.colorBufferObject);
+ ctx.bufferSubData(ctx.ARRAY_BUFFER, 0, srcColBuffer);
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, this.colorBufferObject);
+ ctx.vertexAttribPointer(4, 4, ctx.FLOAT, false, 0, 0);
+
+ // update index buffer
+ ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, this.indexBufferObject);
+ ctx.bufferSubData(ctx.ELEMENT_ARRAY_BUFFER, 0, srcIdxBuffer);
+
+ // draw
+ ctx.drawElements(ctx.TRIANGLES, srcIdxBuffer.numIndices, ctx.UNSIGNED_SHORT, 0);
+
+ // restore render states
+ ctx.disable(ctx.BLEND);
+ if (!pdef.depthTest) {
+ ctx.enable(ctx.DEPTH_TEST);
+ }
+ ctx.blendFunc(ctx.ONE, ctx.ZERO);
+
+ this.shader.endPass();
+ }
+ this.shader.end();
+ }
+ };
+};
+
+particleMoverDefault = function () {
+ this.move = function (particle, dt) {
+ particle.age += dt;
+
+ if (particle.def.persist) {
+ if (particle.def.cycle && particle.age > particle.lifespan * 0.99) {
+ particle.age -= particle.lifespan * 0.99;
+ } else {
+ particle.age = Math.min(particle.age, particle.lifespan * 0.99);
+ }
+
+ } else {
+ particle.age = Math.min(particle.age, particle.lifespan);
+ }
+
+ if (particle.def.frameRate > 0.0) {
+ particle.frame += particle.def.frameRate * dt; //Math.min( particle.def.numFrames - 1, particle.frame + particle.def.frameRate * dt );
+ if (particle.def.frameLoop) {
+ particle.frame = particle.frame % particle.def.numFrames;
+ }
+ else {
+ particle.frame = Math.min(particle.def.numFrames - 1, particle.frame)
+ }
+ }
+
+ var oldPos = particle.pos;
+ var pg = particle.gravity;
+ var pv = particle.velocity;
+ var pp = particle.pos;
+ var pd = particle.delta;
+
+ pv[0] += pg[0] * dt;
+ pv[1] += pg[1] * dt;
+ pv[2] += pg[2] * dt;
+ pp[0] = pp[0] + pv[0] * dt;
+ pp[1] = pp[1] + pv[1] * dt;
+ pp[2] = pp[2] + pv[2] * dt;
+ pd[0] = pp[0] - oldPos[0];
+ pd[1] = pp[1] - oldPos[1];
+ pd[2] = pp[2] - oldPos[2];
+
+ // particle turbulence
+ if (particle.def.turbulence) {
+ var tMin = particle.def.turbulence[0];
+ var tMax = particle.def.turbulence[1];
+ var tx = Math.random() * (tMax[0] - tMin[0]) + tMin[0];
+ var ty = Math.random() * (tMax[1] - tMin[1]) + tMin[1];
+ var tz = Math.random() * (tMax[2] - tMin[2]) + tMin[2];
+ pv[0] += tx;
+ pv[1] += ty;
+ pv[2] += tz;
+ }
+
+ // particle jitter
+ if (particle.def.jitter) {
+ var jMin = particle.def.jitter[0];
+ var jMax = particle.def.jitter[1];
+ var jx = Math.random() * (jMax[0] - jMin[0]) + jMin[0];
+ var jy = Math.random() * (jMax[1] - jMin[1]) + jMin[1];
+ var jz = Math.random() * (jMax[2] - jMin[2]) + jMin[2];
+ pp[0] += jx;
+ pp[1] += jy;
+ pp[2] += jz;
+ }
+ };
+};
+
+RDGE.particleEmitter = function (def) {
+ this.def = def;
+ this.world = RDGE.mat4.identity();
+ this.pbuffer = new RDGE.particleBuffer(this.def.particle, this, this.def.maxParticles);
+
+ this.movers = new Array();
+ var creatorFunc = particleMoverDefault;
+ if (def.particle.moverFunc) {
+ creatorFunc = eval(def.particle.moverFunc);
+ }
+ this.movers.push(new creatorFunc());
+
+ this.localTime = 0.0;
+ this.lastEmitTime = 0.0;
+ this.emitCounter = 0;
+ this.firstUpdate = true;
+
+ this.attachToNode = function (node) {
+ this.controller = node;
+ };
+
+ this.update = function (dt) {
+ this.localTime += dt;
+ if (this.firstUpdate) {
+ this.lastEmitTime = this.localTime;
+ this.firstUpdate = false;
+ }
+
+ if (this.def.emit != undefined && this.def.emit == false) {
+ this.lastEmitTime = this.localTime - 1.0 / this.def.emitRate;
+ }
+
+ // this needs to be handled differently..
+ var maxParticles = this.def.maxParticles;
+ var emitOnce = this.def.emitOnce;
+ var emitCount = (this.def.emit == undefined || this.def.emit == true) ? Math.floor((this.localTime - this.lastEmitTime) * this.def.emitRate) : 0;
+ while (emitCount--) {
+ if (emitOnce && this.emitCounter++ >= maxParticles) {
+ break;
+ }
+ this.pbuffer.emit(this.world);
+ this.lastEmitTime = this.localTime;
+ }
+
+ this.pbuffer.update(dt, this.movers);
+ };
+};
+
+RDGE.particleSys = function (addr) {
+ loaded = (typeof loaded == 'undefined') ? {} : loaded;
+
+ this.def = null;
+ this.node = null;
+ this.world = RDGE.mat4.identity();
+ this.emitters = {};
+
+ // load particle system definition at addr
+ this.init = function () {
+ if (this.def == null) {
+ return;
+ }
+ for (e in this.def.emitters) {
+ this.emitters[e] = new RDGE.particleEmitter(this.def.emitters[e]);
+ }
+
+ this.bounds = {};
+ this.bounds.min = RDGE.vec3.zero();
+ this.bounds.max = RDGE.vec3.zero();
+ };
+
+ if (!loaded[addr]) {
+ var request = new XMLHttpRequest();
+ request.sender = this;
+
+ request.onreadystatechange = function () {
+ if (request.readyState == 4) {
+ if (request.status == 200 || window.location.href.indexOf("http") == -1) {
+ request.sender.def = eval("(" + request.responseText + ")"); //retrieve result as an JavaScript object
+ loaded[addr] = request.sender.def;
+ request.sender.init();
+ }
+ else {
+ alert("An error has occured loading particle system.");
+ }
+ }
+ }
+
+ request.open("GET", addr, true);
+ request.send(null);
+ } else {
+ this.def = loaded[addr];
+ this.init();
+ }
+
+ this.update = function (dt) {
+ if (this.def == null) {
+ return;
+ }
+
+ var bmin = this.bounds.min;
+ var bmax = this.bounds.max;
+
+ bmin[0] = 1e10;
+ bmin[1] = 1e10;
+ bmin[2] = 1e10;
+
+ bmax[0] = -1e10;
+ bmax[1] = -1e10;
+ bmax[2] = -1e10;
+
+ var parent = this.node ? this.node.world : this.world;
+ for (em in this.emitters) {
+ var emitter = this.emitters[em];
+ emitter.world = parent;
+ emitter.update(dt);
+
+ var emin = emitter.pbuffer.bounds.min;
+ var emax = emitter.pbuffer.bounds.max;
+
+ // calculate a bounds that fits all particles.
+ if (emin[0] < bmin[0]) { bmin[0] = emin[0]; }
+ if (emin[1] < bmin[1]) { bmin[1] = emin[1]; }
+ if (emin[2] < bmin[2]) { bmin[2] = emin[2]; }
+ if (emax[0] > bmax[0]) { bmax[0] = emax[0]; }
+ if (emax[1] > bmax[1]) { bmax[1] = emax[1]; }
+ if (emax[2] > bmax[2]) { bmax[2] = emax[2]; }
+ }
+ };
+
+ this.render = function () {
+ if (this.def == null) {
+ return;
+ }
+ for (em in this.emitters) {
+ var pbuffer = this.emitters[em].pbuffer;
+ pbuffer.render();
+ }
+ };
+
+ this.attachToNode = function (node) {
+ this.node = node;
+