Skip to content

Commit

Permalink
more shape and shape examples
Browse files Browse the repository at this point in the history
  • Loading branch information
Alchemist0823 committed Oct 8, 2023
1 parent abe4978 commit d85f405
Show file tree
Hide file tree
Showing 9 changed files with 420 additions and 50 deletions.
5 changes: 4 additions & 1 deletion examples/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ export class Demo {
})
);

while (Math.floor(this.totalTime * this.groups.length) > this.refreshIndex) {
while (Math.floor((this.totalTime / this.refreshTime) * this.groups.length) >= this.refreshIndex) {
if (this.refreshIndex < this.groups.length) {
this.groups[this.refreshIndex].traverse((object) => {
if (object instanceof ParticleEmitter) {
object.system.restart();
}
});
if (this.groups[this.refreshIndex] instanceof ParticleEmitter) {
this.groups[this.refreshIndex].system.restart();
}
}
this.refreshIndex++;
}
Expand Down
170 changes: 170 additions & 0 deletions examples/emitterShapeDemo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import {
Group,
DoubleSide,
Mesh,
Vector4,
Vector3,
Color,
AdditiveBlending,
NormalBlending,
TextureLoader,
MeshBasicMaterial,
} from 'three';
import {
GridEmitter,
SphereEmitter,
CircleEmitter,
ConeEmitter,
HemisphereEmitter,
ConstantValue,
IntervalValue,
DonutEmitter,
PointEmitter,
RandomColor,
RenderMode,
ParticleSystem,
ParticleEmitter,
BatchedParticleRenderer,
} from 'three.quarks';
import {Demo} from './demo.js';

export class EmitterShapeDemo extends Demo {
name = 'Different Emitter Shapes';
refreshTime = 10;
initParticleSystem() {
return new ParticleSystem({
duration: 5,
looping: true,
startLife: new IntervalValue(1.0, 1.0),
startSpeed: new IntervalValue(1, 1),
startSize: new IntervalValue(0.1, 0.1),
startColor: new RandomColor(new Vector4(1, 0.91, 0.51, 1), new Vector4(1, 0.44, 0.16, 1)),
worldSpace: true,

maxParticle: 1000,
emissionOverTime: new ConstantValue(1000),
emissionBursts: [
/*{
time: 0,
count: new ConstantValue(100),
cycle: 1,
interval: 0.01,
probability: 1,
},*/
],

shape: new PointEmitter(),
material: new MeshBasicMaterial({
map: this.texture,
blending: AdditiveBlending,
transparent: true,
side: DoubleSide,
}),
startTileIndex: new ConstantValue(0),
uTileCount: 10,
vTileCount: 10,
renderMode: RenderMode.BillBoard,
renderOrder: 1,
});
}

initScene() {
this.scene = super.initScene();
this.batchRenderer = new BatchedParticleRenderer();
this.scene.add(this.batchRenderer);

this.texture = new TextureLoader().load('textures/texture1.png', (texture) => {
this.texture.name = 'textures/texture1.png';

let particles = this.initParticleSystem();
particles.emitterShape = new PointEmitter();
particles.emitter.name = 'point';
//particles.emitter.rotation.y = Math.PI / 2;
particles.emitter.position.set(-5, -5, 2);
this.batchRenderer.addSystem(particles);
this.scene.add(particles.emitter);
this.groups.push(particles.emitter);

particles = this.initParticleSystem();
particles.emitterShape = new SphereEmitter({
radius: 1,
thickness: 0.2,
arc: Math.PI * 2,
});
particles.emitter.name = 'Sphere';
//particles.emitter.rotation.y = Math.PI / 2;
particles.emitter.position.set(-5, 0, 2);
this.batchRenderer.addSystem(particles);
this.scene.add(particles.emitter);
this.groups.push(particles.emitter);

particles = this.initParticleSystem();
particles.emitterShape = new HemisphereEmitter({
radius: 1,
thickness: 0.2,
arc: Math.PI * 2,
});
particles.emitter.name = 'Hemisphere';
particles.emitter.rotation.x = -Math.PI / 2;
particles.emitter.position.set(-5, 5, 2);
this.batchRenderer.addSystem(particles);
this.scene.add(particles.emitter);
this.groups.push(particles.emitter);

particles = this.initParticleSystem();
particles.emitterShape = new ConeEmitter({
radius: 1,
thickness: 1,
arc: Math.PI * 2,
angle: Math.PI / 4,
});
particles.emitter.name = 'Cone';
particles.emitter.position.set(0, -5, 2);
this.batchRenderer.addSystem(particles);
this.scene.add(particles.emitter);
this.groups.push(particles.emitter);

particles = this.initParticleSystem();
particles.emitterShape = new CircleEmitter({
radius: 1,
thickness: 0.2,
arc: Math.PI * 2,
});
particles.emitter.name = 'Circle';
//particles.emitter.rotation.y = Math.PI / 2;
particles.emitter.position.set(0, 0, 2);
this.batchRenderer.addSystem(particles);
this.scene.add(particles.emitter);
this.groups.push(particles.emitter);

particles = this.initParticleSystem();
particles.emitterShape = new DonutEmitter({
radius: 2,
thickness: 1,
arc: Math.PI * 2,
donutRadius: 0.2,
});
particles.emitter.name = 'Donut';
//particles.emitter.rotation.y = Math.PI / 2;
particles.emitter.position.set(0, 5, 2);
this.batchRenderer.addSystem(particles);
this.scene.add(particles.emitter);
this.groups.push(particles.emitter);

particles = this.initParticleSystem();
particles.emitterShape = new GridEmitter({
width: 2,
height: 2,
rows: 10,
columns: 10,
});
particles.emitter.name = 'Grid';
//particles.emitter.rotation.y = Math.PI / 2;
particles.emitter.position.set(5, -5, 2);
this.batchRenderer.addSystem(particles);
this.scene.add(particles.emitter);
this.groups.push(particles.emitter);
});
return this.scene;
}
}
3 changes: 2 additions & 1 deletion examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
import {TrailDemo} from "./trailDemo.js";
import {TurbulenceDemo} from "./turbulenceDemo.js";
import {ExplosionDemo} from "./explosionDemo.js";
import {EmitterShapeDemo} from "./emitterShapeDemo.js";
import {CustomPluginDemo} from "./customPluginDemo.js";
import {SequencerDemo} from "./sequencerDemo.js";
import {MeshMaterialDemo} from "./meshMaterialDemo.js";
Expand Down Expand Up @@ -154,7 +155,7 @@
let scene;
let demo;

let demos = [MuzzleFlashDemo, ExplosionDemo, TrailDemo, SequencerDemo, MeshMaterialDemo, TurbulenceDemo, AlphaTestDemo, CustomPluginDemo, BillboardDemo, NodeBasedVFXDemo];
let demos = [MuzzleFlashDemo, ExplosionDemo, EmitterShapeDemo, TrailDemo, SequencerDemo, MeshMaterialDemo, TurbulenceDemo, AlphaTestDemo, CustomPluginDemo, BillboardDemo, NodeBasedVFXDemo];
let demoIndex = 0;

function init() {
Expand Down
55 changes: 55 additions & 0 deletions src/shape/CircleEmitter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {EmitterShape, ShapeJSON} from './EmitterShape';
import {Particle} from '../Particle';
import {MathUtils} from 'three';

export interface CircleEmitterParameters {
radius?: number;
arc?: number;
thickness?: number;
}

export class CircleEmitter implements EmitterShape {
type = 'circle';
radius: number;
arc: number; // [0, Math.PI * 2]
thickness: number; // [0, 1]

constructor(parameters: CircleEmitterParameters = {}) {
this.radius = parameters.radius ?? 10;
this.arc = parameters.arc ?? 2.0 * Math.PI;
this.thickness = parameters.thickness ?? 1;
}

initialize(p: Particle) {
const u = Math.random();
const r = MathUtils.lerp(1 - this.thickness, 1, Math.random());
const theta = u * this.arc;
p.position.x = Math.cos(theta);
p.position.y = Math.sin(theta);
p.position.z = 0;
p.velocity.copy(p.position).multiplyScalar(p.startSpeed);
//const v = Math.random();
p.position.multiplyScalar(this.radius * r);
}

toJSON(): ShapeJSON {
return {
type: 'circle',
radius: this.radius,
arc: this.arc,
thickness: this.thickness,
};
}

static fromJSON(json: any): CircleEmitter {
return new CircleEmitter(json);
}

clone(): EmitterShape {
return new CircleEmitter({
radius: this.radius,
arc: this.arc,
thickness: this.thickness,
});
}
}
48 changes: 29 additions & 19 deletions src/shape/DonutEmitter.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,63 @@
import {EmitterShape, ShapeJSON} from "./EmitterShape";
import {Particle} from "../Particle";
import { MathUtils} from "three";

import {EmitterShape, ShapeJSON} from './EmitterShape';
import {Particle} from '../Particle';
import {MathUtils} from 'three';

export interface DonutEmitterParameters {
radius?: number;
arc?: number;
thickness?: number;
angle?: number; // [0, Math.PI / 2]
donutRadius?: number;
}

export class DonutEmitter implements EmitterShape {
type = "donut";
type = 'donut';
radius: number;
donutRadius: number;
arc: number; // [0, Math.PI * 2]
thickness: number;
angle: number; // [0, Math.PI / 2]

constructor(parameters: DonutEmitterParameters = {}) {
this.radius = parameters.radius ?? 10;
this.arc = parameters.arc ?? 2.0 * Math.PI;
this.thickness = parameters.thickness ?? 1;
this.angle = parameters.angle ?? Math.PI / 6;
this.donutRadius = parameters.donutRadius ?? this.radius * 0.2;
}

initialize(p: Particle) {
const u = Math.random();
const rand = MathUtils.lerp(this.thickness, 1, Math.random());
const v = Math.random();
const rand = MathUtils.lerp(1 - this.thickness, 1, Math.random());
const theta = u * this.arc;
const r = Math.sqrt(rand);
const phi = v * Math.PI * 2;
//const r = Math.sqrt(rand);
const sinTheta = Math.sin(theta);
const cosTheta = Math.cos(theta);
p.position.x = r * cosTheta;
p.position.y = r * sinTheta;
p.position.x = this.radius * cosTheta;
p.position.y = this.radius * sinTheta;
p.position.z = 0;

const angle = this.angle * r;
p.velocity.set(0, 0, Math.cos(angle)).addScaledVector(p.position, Math.sin(angle)).multiplyScalar(p.startSpeed);
p.velocity.z = this.donutRadius * rand * Math.sin(phi);
p.velocity.x = this.donutRadius * rand * Math.cos(phi) * cosTheta;
p.velocity.y = this.donutRadius * rand * Math.cos(phi) * sinTheta;

p.position.add(p.velocity);

p.velocity.normalize().multiplyScalar(p.startSpeed);

//const angle = this.angle * r;
//p.velocity.set(0, 0, Math.cos(angle)).addScaledVector(p.position, Math.sin(angle)).multiplyScalar(p.startSpeed);
//const v = Math.random();
p.position.multiplyScalar(this.radius);

//.multiplyScalar(this.radius);
}

toJSON(): ShapeJSON {
return {
type: "donut",
type: 'donut',
radius: this.radius,
arc: this.arc,
thickness: this.thickness,
angle: this.angle
donutRadius: this.donutRadius,
};
}

Expand All @@ -56,11 +66,11 @@ export class DonutEmitter implements EmitterShape {
}

clone(): EmitterShape {
return new DonutEmitter({
return new DonutEmitter({
radius: this.radius,
arc: this.arc,
thickness: this.thickness,
angle: this.angle,
donutRadius: this.donutRadius,
});
}
}
Loading

0 comments on commit d85f405

Please sign in to comment.