173 lines
5.7 KiB
JavaScript
173 lines
5.7 KiB
JavaScript
|
//
|
||
|
// nitroEmitter.js
|
||
|
//--------------------
|
||
|
// Implemtents the generic nitro particle emitter.
|
||
|
// by riperiperi
|
||
|
//
|
||
|
|
||
|
window.NitroEmitter = function(scene, targ, emitterID, vector, offset) {
|
||
|
var t = this;
|
||
|
t.update = update;
|
||
|
t.draw = draw;
|
||
|
|
||
|
var pRes = scene.gameRes.RaceEffect;
|
||
|
var emitter = (emitterID == -1)?null:pRes.particles[emitterID];
|
||
|
t.attached = targ; //an entity with pos and vel.
|
||
|
|
||
|
if (vector == null) vector = [0, 1, 0];
|
||
|
if (offset == null) offset = [0,0,0];
|
||
|
t.offset = offset;
|
||
|
t.vector = vector;
|
||
|
t.pctParticle = 0;
|
||
|
t.time = 0;
|
||
|
t.dead = false;
|
||
|
t.curPrio = 0;
|
||
|
t.doNotDelete = (emitter == null);
|
||
|
t.pause = false;
|
||
|
|
||
|
t.setEmitter = setEmitter;
|
||
|
t.clearEmitter = clearEmitter;
|
||
|
|
||
|
var particleList = [emitterID, -1, -1, -1];
|
||
|
|
||
|
function setEmitter(emitterID, prio) {
|
||
|
particleList[prio] = emitterID;
|
||
|
if (t.curPrio <= prio) {
|
||
|
//activate this emitter immediately.
|
||
|
t.curPrio = prio;
|
||
|
t.dead = false;
|
||
|
emitter = pRes.particles[emitterID];
|
||
|
t.time = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function clearEmitter(prio) {
|
||
|
//if (t.curPrio > prio) return; //this emitter cannot be unset
|
||
|
if (prio == t.curPrio) {
|
||
|
findNextEmitter();
|
||
|
} else {
|
||
|
particleList[prio] = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function findNextEmitter() {
|
||
|
particleList[t.curPrio] = -1;
|
||
|
var em = t.curPrio-1;
|
||
|
while (em >= 0) {
|
||
|
if (particleList[em] != -1) {
|
||
|
t.dead = false;
|
||
|
emitter = pRes.particles[particleList[em]];
|
||
|
t.time = 0;
|
||
|
t.curPrio = em;
|
||
|
return;
|
||
|
}
|
||
|
em--;
|
||
|
}
|
||
|
if (em == -1) {
|
||
|
t.curPrio = 0;
|
||
|
emitter = null;
|
||
|
dead = true;
|
||
|
}
|
||
|
t.curPrio = em;
|
||
|
}
|
||
|
|
||
|
function update(scene) {
|
||
|
if (emitter == null || t.dead || t.pause) return;
|
||
|
if ((t.time % (emitter.frequency)) == 0 && t.time >= emitter.delay) {
|
||
|
//should we create new particles? fractional logic for doing this
|
||
|
t.pctParticle += emitter.particleChance;
|
||
|
while (t.pctParticle >= 1) {
|
||
|
|
||
|
var attach = (emitter.flag & 0x8000) > 0;
|
||
|
|
||
|
t.pctParticle -= 1;
|
||
|
//create a new particle
|
||
|
//TODO: make these transform with the target's world matrix
|
||
|
var pos = vec3.create();
|
||
|
//add offset
|
||
|
vec3.add(pos, pos, t.offset);
|
||
|
//add emitter properties
|
||
|
vec3.add(pos, pos, emitter.position);
|
||
|
var spread = [Math.random()*2-1, Math.random()*2-1, Math.random()*2-1];
|
||
|
var spreadMode = (emitter.flag & 0xF);
|
||
|
if (spreadMode == 2) {
|
||
|
spread[1] = 0; //spread is only in xz direction
|
||
|
}
|
||
|
vec3.normalize(spread, spread);
|
||
|
if (spreadMode == 0) {
|
||
|
spread = [0,0,0];
|
||
|
}
|
||
|
vec3.scale(spread, spread, Math.random()*emitter.areaSpread*2);
|
||
|
vec3.add(pos, pos, spread);
|
||
|
|
||
|
vec3.scale(pos, pos, 16);
|
||
|
if (!attach) {
|
||
|
if (targ.mat != null) {
|
||
|
vec3.transformMat4(pos, pos, targ.mat);
|
||
|
} else {
|
||
|
vec3.add(pos, pos, targ.pos);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//inherit velocity
|
||
|
var vel = (attach)?vec3.create():vec3.clone(targ.vel);
|
||
|
vec3.scale(vel, vel, 1/32);
|
||
|
|
||
|
var vector = vec3.clone(t.vector);
|
||
|
if (!attach) {
|
||
|
if (targ.mat != null) {
|
||
|
//tranform our vector by the target matrix
|
||
|
var mat = targ.mat;
|
||
|
var org = [];
|
||
|
mat4.getTranslation(org, mat);
|
||
|
mat[12] = 0;
|
||
|
mat[13] = 0;
|
||
|
mat[14] = 0;
|
||
|
|
||
|
vec3.transformMat4(vector, vector, mat);
|
||
|
|
||
|
mat[12] = org[0];
|
||
|
mat[13] = org[1];
|
||
|
mat[14] = org[2];
|
||
|
}
|
||
|
}
|
||
|
vec3.normalize(vector, vector);
|
||
|
vec3.add(vel, vel, vec3.scale([], vector, emitter.velocity));
|
||
|
|
||
|
var xz = [Math.random()*2-1, 0, Math.random()*2-1];
|
||
|
vec3.normalize(xz, xz);
|
||
|
vec3.scale(xz, xz, Math.random()*emitter.randomxz);
|
||
|
vec3.add(vel, vel, xz);
|
||
|
|
||
|
var rotVel = ((emitter.rotVelFrom + ((Math.random()*emitter.rotVelTo-emitter.rotVelFrom) | 0))/65535) * Math.PI*2;
|
||
|
var dir = ((emitter.flag & 0x2000) > 0)?(Math.random()*Math.PI*2):0;
|
||
|
var duration = emitter.duration + emitter.duration * emitter.varDuration/0xFF * (Math.random() * 2 - 1);
|
||
|
var scaleMod = (emitter.varScale/0xFF * (Math.random() * 2 - 1)) + 1;
|
||
|
|
||
|
var scale = [scaleMod * emitter.size, scaleMod * emitter.size * emitter.aspect];
|
||
|
|
||
|
var particle = new NitroParticle(scene, emitter, pos, vel, dir, rotVel, duration, scale, (attach?t.attached:null));
|
||
|
particle.ovel = (attach)?vec3.create():vec3.scale([], targ.vel, 1/32);
|
||
|
|
||
|
scene.particles.push(particle);
|
||
|
}
|
||
|
|
||
|
|
||
|
var pos = vec3.clone(targ.pos);
|
||
|
|
||
|
}
|
||
|
t.time++;
|
||
|
|
||
|
if (t.time == emitter.emitterLifetime) {
|
||
|
t.dead = true;
|
||
|
if (!t.doNotDelete) scene.removeParticle(t);
|
||
|
else {
|
||
|
findNextEmitter();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function draw(view, pMatrix, gl) {
|
||
|
|
||
|
}
|
||
|
}
|