/**
* Creates new particle system
* @param {Ayce.Scene} scene
* @param {Ayce.Object3D} geometry
* @param {Number} quantity
* @param {Number} prewarmTime
* @class
* @constructor
*/
Ayce.ParticleSystem = function (scene, geometry, quantity, prewarmTime) {
Ayce.Object3D.call(this);
var VALUES_PER_POSITION = 3;
var VALUES_PER_VELOCITY = 3;
var VALUES_PER_ROTATION = 3;
var VALUES_PER_LIFETIME = 1;
var VALUES_PER_GRAVITY = 1;
var VALUES_PER_GRAVITY_EXP = 1;
this.particles = [];
var i;
for(i=0;i<quantity;i++){
this.particles.push(new Ayce.Particle());
}
this.vertices = [];
this.colors = null;
this.textureCoords = null;
this.indices = [];
this.velocities = [];
this.lifetimes = [];
this.gravities = [];
this.gravityExps = [];
this.geometries = [];
this.rotationAngles = [];
this.normals = null;
this.imageSrc = geometry.imageSrc;
this.shader = null;
var timeObject = {
time: 0,
startTime: Date.now()
};
this.shaderAttributes = [];
this.shaderAttributes.push(["aGeometryPosition", VALUES_PER_POSITION, this.geometries]);
this.shaderAttributes.push(["aVertexVelocity", VALUES_PER_VELOCITY, this.velocities]);
this.shaderAttributes.push(["aVertexRotation", VALUES_PER_ROTATION, this.rotationAngles]);
this.shaderAttributes.push(["aLifetime", VALUES_PER_LIFETIME, this.lifetimes]);
this.shaderAttributes.push(["aGravity", VALUES_PER_GRAVITY, this.gravities]);
this.shaderAttributes.push(["aGravityExponent", VALUES_PER_GRAVITY_EXP, this.gravityExps]);
this.shaderUniforms = [];
this.shaderUniforms.push(["uTime", "uniform1f", timeObject, ["time"]]);
/**
* Initializes particle system after all values have been set
*/
this.initParticleArrays = function() {
var j;
for (i = 0; i < this.particles.length; i++) { // create global vertex for every vertex in the particle system
var particle = this.particles[i];
for (j = 0; j < geometry.vertices.length; j += 3) {
this.vertices.push(geometry.vertices[j]*particle.scale.x + particle.position.x); //x
this.vertices.push(geometry.vertices[j + 1]*particle.scale.y + particle.position.y); //y
this.vertices.push(geometry.vertices[j + 2]*particle.scale.z + particle.position.z); //z
this.geometries.push(geometry.vertices[j] * particle.scale.x);
this.geometries.push(geometry.vertices[j + 1] * particle.scale.y);
this.geometries.push(geometry.vertices[j + 2] * particle.scale.z);
}
}
if(geometry.textureCoords&&geometry.textureCoords[0]!=-1){
this.textureCoords = [];
for (i = 0; i < this.particles.length; i++) {
this.textureCoords = this.textureCoords.concat(geometry.textureCoords);
}
}else {
this.colors = [];
for (i = 0; i < this.particles.length; i++) {
if(this.particles[i].colors){
this.colors = this.colors.concat(this.particles[i].colors);
}else{
this.colors = this.colors.concat(geometry.colors);
}
}
}
for (i = 0; i < this.particles.length; i++) {
for (j = 0; j < geometry.indices.length; j++) {
this.indices.push(geometry.indices[j] + i * geometry.vertices.length / VALUES_PER_POSITION);
}
}
for (i = 0; i < this.particles.length; i++) {
for (j = 0; j < geometry.vertices.length/VALUES_PER_POSITION; j++) {
if(geometry.velocities){ // if geometry is particle system
this.velocities.push(this.particles[i].velocity.x+geometry.velocities[j*VALUES_PER_VELOCITY]);
this.velocities.push(this.particles[i].velocity.y+geometry.velocities[j*VALUES_PER_VELOCITY+1]);
this.velocities.push(this.particles[i].velocity.z+geometry.velocities[j*VALUES_PER_VELOCITY+2]);
}else { // geometry is regular geometry
this.velocities.push(this.particles[i].velocity.x);
this.velocities.push(this.particles[i].velocity.y);
this.velocities.push(this.particles[i].velocity.z);
}
}
}
for (i = 0; i < this.particles.length; i++) {
for (j = 0; j < geometry.vertices.length/VALUES_PER_POSITION; j++) {
if(geometry.lifetimes){ // if geometry is particle system
if(geometry.lifetimes[j] === 0.0){
this.lifetimes.push(this.particles[i].lifetime);
}else {
this.lifetimes.push(Math.min(this.particles[i].lifetime, geometry.lifetimes[j]));
}
}else{ // geometry is regular geometry
this.lifetimes.push(this.particles[i].lifetime);
}
}
}
for (i = 0; i < this.particles.length; i++) {
for (j = 0; j < geometry.vertices.length/VALUES_PER_POSITION; j++) {
if(geometry.gravities){
this.gravities.push(this.particles[i].gravity+geometry.gravities[j]);
}else{
this.gravities.push(this.particles[i].gravity);
}
this.gravityExps.push(this.particles[i].gravityExponent);
}
}
for (i = 0; i < this.particles.length; i++) {
for (j = 0; j < geometry.vertices.length/VALUES_PER_POSITION; j++) {
this.rotationAngles.push(this.particles[i].rotationAngle.x);
this.rotationAngles.push(this.particles[i].rotationAngle.y);
this.rotationAngles.push(this.particles[i].rotationAngle.z);
}
}
if(geometry.normals){
this.normals = [];
for (i = 0; i < this.particles.length; i++) {
this.normals = this.normals.concat(geometry.normals);
}
}
// console.log(
// this.vertices.length / VALUES_PER_POSITION + " vertices;\n" +
// this.geometries.length / VALUES_PER_POSITION + " geometries;\n" +
// this.colors.length / 4 + " colors;\n" +
// this.indices.length + " indices;\n" +
// this.velocities.length / 3 + " velocities;\n" +
// this.lifetimes.length + " lifetimes;\n" +
// this.gravities.length + " gravities;\n" +
// this.gravityExps.length + " gravity exponents;\n" +
// this.rotationAngles.length / 3 + " rotationAngles."
// );
};
var superUpdate = this.update;
/**
* Updates time for particle system animation
*/
this.update = function(){
superUpdate.call(this);
timeObject.time = Date.now()+prewarmTime-timeObject.startTime;
};
};
Ayce.ParticleSystem.prototype = new Ayce.Object3D();
/**
* Creates new particle
* @class
* @constructor
*/
Ayce.Particle = function () {
this.position = new Ayce.Vector3(0.0, 0.0, 0.0);
this.rotationAngle = new Ayce.Vector3(0.0, 0.0, 0.0);
this.scale = new Ayce.Vector3(1, 1, 1);
this.vertices = [];
this.colors = null;
this.velocity = new Ayce.Vector3(0.0,0.0,0.0);
this.lifetime = 0.0;
this.gravity = 0.0;
this.gravityExponent = 1.0;
};