-
Notifications
You must be signed in to change notification settings - Fork 5
/
Particle.js
126 lines (106 loc) · 3.84 KB
/
Particle.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
"use strict"
/*
* Particle.js
*
* Version:
* $1.0$
*
* Revisions:
* $1.0$
*/
import MyMath from "../lang/MyMath.js";
import Dynamics from "./Dynamics.js";
import RigidSphere from "./RigidSphere.js";
/**
* data structure of Particle
*
* @author Xiaoyu Tongyang, or call me sora for short
*/
export default class Particle extends RigidSphere {
static IDStatic = 0;
/**
* @param {TextureLoader} texture
* @param {Number} color
* @param {Scene} scene
*/
constructor( texture, color, scene ) {
super( null, 0.01, 0.01, "sprite" + Particle.IDStatic++ );
this.material = new THREE.SpriteMaterial( {
color: color,
map: texture,
transparent: true
} );
this.mesh = new THREE.Sprite( this.material );
scene.add( this.mesh );
this.alive = true;
}
updateOpacity() {
this.material.opacity = this.alive ? this.remeanedLifeTime / this.lifeTime : 0;
}
updateLifetime() {
this.alive = --this.remeanedLifeTime > 0;
}
/**
* initialize a particle
*
* @param {Vector3} center
* @param {Vector3} direction
* @param {Number} radius
* @param {Number} speed
* @param {Number} psi, emission angle, side Angle
* @param {Vector3} scale
* @param {Number} lifeTime
*/
init( center, direction,
radius, speed,
psi, scale, lifeTime ) {
const k = radius / 0.5;
// get position
let x = ( Math.random() - 0.5 ) * k;
let y = ( Math.random() - 0.5 ) * k;
let z = ( Math.random() - 0.5 ) * k;
let pos = new THREE.Vector3( x, y, z ).add( center );
// pos= new THREE.Vector3();
// console.log( pos, pos.clone().sub( center ).length() );
this.reset();
// get unit velocity in the cone
let unitDirection = Particle.randomUnitVector3InCone( center, direction, psi );
// get Momentum for this particle
let m = speed * this.m;
this.M = unitDirection.clone().negate().multiplyScalar( m );
// set position and scale
this.mesh.scale.set( scale.x, scale.y, 1 ); // set y scale only
this.mesh.position.set( pos.x, pos.y, pos.z );
// set life time
this.lifeTime = lifeTime;
this.remeanedLifeTime = lifeTime;
this.alive = true;
}
/**
* get random Unit Vector3 bounded by the Cone.
* This is defined by the direction of the cone and its side angle, a.k.a., emission angle
*
* Reference resource:
* Generating uniform unit random vectors in Rn, UMONS, Belgium, Andersen Ang
*
* @param {Vector3} center center of the cone
* @param {Vector3} direction direction of the cone
* @param {Number} sideAngle in degrees
*/
static randomUnitVector3InCone( center, direction, sideAngle ) {
let theta = Math.random() * 360;
// side angle of the cone is sideAngle degrees
let cosPhi = Math.cos( MyMath.radians( sideAngle ) );
let z = MyMath.randomInRange( cosPhi, 1 );
console.assert( MyMath.doubleCompare( 1 - z * z, 0 ) >= 0, 1 - z * z );
let sinPhi = Math.sqrt( 1 - z * z );
let x = sinPhi * Math.cos( MyMath.radians( theta ) );
let y = sinPhi * Math.sin( MyMath.radians( theta ) );
// hit it with a rotation matrix to get it aligned with the direction of the cone
// let rotation = new THREE.Matrix4().lookAt( center, direction.clone().add( center ), Dynamics.zAxis.clone() );
let rotation = new THREE.Matrix4().lookAt( center, direction.clone(), Dynamics.zAxis.clone() );
let directionV = new THREE.Vector3( x, y, z ).clone().transformDirection( rotation );
// console.log( MyMath.degrees( direction.angleTo( directionV ) ), direction.length() );
return directionV;
}
}