Skip to content

Instantly share code, notes, and snippets.

@dmbfm
Created January 31, 2019 22:34
Show Gist options
  • Save dmbfm/6c78fbd4d627eebfba630141e054cbd2 to your computer and use it in GitHub Desktop.
Save dmbfm/6c78fbd4d627eebfba630141e054cbd2 to your computer and use it in GitHub Desktop.
import * as THREE from "three";
class Particle {
constructor(mesh, body, meshIndex = 0, lifeTime = 0) {
this.meshIndex = meshIndex;
this.lifeTime = lifeTime;
this.elapsedTime = 0;
this.dead = false;
this.mesh = mesh;
this.body = body;
this.onDeath = null;
}
relive() {
this.elapsedTime = 0;
this.dead = false;
}
update(dt) {
this.elapsedTime += dt;
if (this.elapsedTime >= this.lifeTime) {
this.dead = true;
this.onDeath && this.onDeath();
return false;
}
// this.mesh.position.y -= 100 * dt;
this.mesh.position.copy(this.body.getPosition());
this.mesh.quaternion.copy(this.body.getQuaternion());
return true;
}
}
export class Rain {
/**
*
* @param {THREE.Mesh[]} meshes
* @param {number[]} probabilities
*/
constructor(
world,
scene,
meshes,
height,
xmin,
xdelta,
zmin,
zdelta,
scale = 10
) {
this.scene = scene;
this.particles = [];
this.meshes = meshes;
this.particleLifeTime = 5;
this.maxParticles = 600;
this.world = world;
this.height = height;
this.xmin = xmin;
this.xdelta = xdelta;
this.zmin = zmin;
this.zdelta = zdelta;
this.scale = scale;
this.deadParticles = new Map();
for (let i = 0; i < this.meshes.length; i++) {
this.deadParticles.set(i, []);
}
}
/**
* @param {number} typeIndex
* @returns {Particle|null}
*/
requestDeadParticleOfType(typeIndex) {
let deadParticleArray = this.deadParticles.get(typeIndex);
if (!deadParticleArray) {
return null;
}
if (deadParticleArray.length <= 0) {
return null;
} else return deadParticleArray.pop();
}
getInitialParticlePosition() {
let x = this.xmin + this.xdelta * Math.random();
let z = this.zmin + this.zdelta * Math.random();
let y = this.height;
return new THREE.Vector3(x, y, z);
}
removeParticle(particle) {
let index = this.particles.indexOf(particle);
if (index < 0) {
return;
}
this.particles.splice(index, 1);
}
emitParticleOfType(typeIndex) {
let particle = this.requestDeadParticleOfType(typeIndex);
let position = this.getInitialParticlePosition();
let x = position.x;
let y = position.y;
let z = position.z;
if (!particle) {
let w = 4 * (this.scale / 10);
let h = 4 * (this.scale / 10);
let d = 8 * (this.scale / 10);
let body = this.world.add({
type: "box",
size: [w, h, d],
pos: [x, y, z],
rot: [100, 2, 2],
move: true,
world: this.world,
belongsTo: 0x02,
collidesWith: 0x01
});
let mesh = this.meshes[typeIndex].clone();
mesh.castShadow = true;
mesh.receiveShadow = false;
mesh.scale.set(this.scale, this.scale, this.scale);
particle = new Particle(
mesh,
body,
typeIndex,
this.particleLifeTime
);
particle.onDeath = () => {
this.scene.remove(particle.mesh);
this.removeParticle(particle);
};
} else {
particle.relive();
body.resetPosition(x, y, z);
}
particle.mesh.position.copy(position);
this.scene.add(particle.mesh);
this.particles.push(particle);
}
emit() {
const index = Math.floor(Math.random() * this.meshes.length);
this.emitParticleOfType(index);
}
update(dt) {
if (this.particles.length < this.maxParticles) {
this.emit();
}
for (let i = 0; i < this.particles.length; i++) {
this.particles[i].update(dt);
}
}
}
export const createStaticBox = (size, position, rotation, material) => {
var mesh = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
material
? material
: new THREE.MeshStandardMaterial({
color: new THREE.Color(0.2, 0.2, 0.2)
})
);
const ToRad = Math.PI / 180;
mesh.scale.set(size[0], size[1], size[2]);
mesh.position.set(position[0], position[1], position[2]);
mesh.rotation.set(
rotation[0] * ToRad,
rotation[1] * ToRad,
rotation[2] * ToRad
);
// mesh.castShadow = false;
mesh.receiveShadow = true;
return mesh;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment