mdx-m3-viewer
Version:
A browser WebGL model viewer. Mainly focused on models of the games Warcraft 3 and Starcraft 2.
111 lines (91 loc) • 3.67 kB
text/typescript
import { vec3, quat } from 'gl-matrix';
import { VEC3_UNIT_Z } from '../../../common/gl-matrix-addon';
import { degToRad, randomInRange } from '../../../common/math';
import EmittedObject from '../../emittedobject';
import ParticleEmitter2Object from './particleemitter2object';
import ParticleEmitter2 from './particleemitter2';
import MdxModelInstance from './modelinstance';
const rotationHeap = quat.create();
const widthHeap = new Float32Array(1);
const lengthHeap = new Float32Array(1);
const latitudeHeap = new Float32Array(1);
const variationHeap = new Float32Array(1);
const speedHeap = new Float32Array(1);
const gravityHeap = new Float32Array(1);
/**
* A type 2 particle.
*/
export default class Particle2 extends EmittedObject {
tail: number = 0;
gravity: number = 0;
location: vec3 = vec3.create();
velocity: vec3 = vec3.create();
scale: vec3 = vec3.create();
bind(tail: number) {
let emitter = <ParticleEmitter2>this.emitter;
let instance = <MdxModelInstance>emitter.instance;
let sequence = instance.sequence;
let frame = instance.frame;
let counter = instance.counter;
let emitterObject = <ParticleEmitter2Object>emitter.emitterObject;
emitterObject.getWidth(widthHeap, sequence, frame, counter);
emitterObject.getLength(lengthHeap, sequence, frame, counter);
emitterObject.getLatitude(latitudeHeap, sequence, frame, counter);
emitterObject.getVariation(variationHeap, sequence, frame, counter);
emitterObject.getSpeed(speedHeap, sequence, frame, counter);
emitterObject.getGravity(gravityHeap, sequence, frame, counter);
let node = emitter.node;
let pivot = node.pivot;
let scale = node.worldScale;
let width = widthHeap[0] * 0.5;
let length = lengthHeap[0] * 0.5;
let latitude = degToRad(latitudeHeap[0]);
let variation = variationHeap[0];
let speed = speedHeap[0];
let location = this.location;
let velocity = this.velocity;
this.health = emitterObject.lifeSpan;
this.tail = tail;
this.gravity = gravityHeap[0] * scale[2];
vec3.copy(this.scale, scale);
// Local location
location[0] = pivot[0] + randomInRange(-width, width);
location[1] = pivot[1] + randomInRange(-length, length);
location[2] = pivot[2];
// World location
if (!emitterObject.modelSpace) {
vec3.transformMat4(location, location, node.worldMatrix);
}
// Local rotation
quat.identity(rotationHeap);
quat.rotateZ(rotationHeap, rotationHeap, Math.PI / 2);
quat.rotateY(rotationHeap, rotationHeap, randomInRange(-latitude, latitude));
// If this is not a line emitter, emit in a sphere rather than a circle.
if (!emitterObject.lineEmitter) {
quat.rotateX(rotationHeap, rotationHeap, randomInRange(-latitude, latitude));
}
// World rotation
if (!emitterObject.modelSpace) {
quat.mul(rotationHeap, node.worldRotation, rotationHeap);
}
// Apply the rotation
vec3.transformQuat(velocity, VEC3_UNIT_Z, rotationHeap);
// Apply speed
vec3.scale(velocity, velocity, speed + randomInRange(-variation, variation));
// Apply the parent's scale
if (!emitterObject.modelSpace) {
vec3.mul(velocity, velocity, scale);
}
}
update(dt: number) {
this.health -= dt;
if (this.health > 0) {
let location = this.location;
let velocity = this.velocity;
velocity[2] -= this.gravity * dt;
location[0] += velocity[0] * dt;
location[1] += velocity[1] * dt;
location[2] += velocity[2] * dt;
}
}
}