solidParticle.ts 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. import { Nullable } from "../types";
  2. import { Vector3, Matrix, TmpVectors, Quaternion, Vector4, Vector2 } from "../Maths/math.vector";
  3. import { Color4 } from '../Maths/math.color';
  4. import { Mesh } from "../Meshes/mesh";
  5. import { BoundingInfo } from "../Culling/boundingInfo";
  6. import { BoundingSphere } from "../Culling/boundingSphere";
  7. import { SolidParticleSystem } from "./solidParticleSystem";
  8. import { AbstractMesh } from '../Meshes/abstractMesh';
  9. import { Plane } from '../Maths/math.plane';
  10. import { Material } from '../Materials/material';
  11. /**
  12. * Represents one particle of a solid particle system.
  13. */
  14. export class SolidParticle {
  15. /**
  16. * particle global index
  17. */
  18. public idx: number = 0;
  19. /**
  20. * particle identifier
  21. */
  22. public id: number = 0;
  23. /**
  24. * The color of the particle
  25. */
  26. public color: Nullable<Color4> = new Color4(1.0, 1.0, 1.0, 1.0);
  27. /**
  28. * The world space position of the particle.
  29. */
  30. public position: Vector3 = Vector3.Zero();
  31. /**
  32. * The world space rotation of the particle. (Not use if rotationQuaternion is set)
  33. */
  34. public rotation: Vector3 = Vector3.Zero();
  35. /**
  36. * The world space rotation quaternion of the particle.
  37. */
  38. public rotationQuaternion: Nullable<Quaternion>;
  39. /**
  40. * The scaling of the particle.
  41. */
  42. public scaling: Vector3 = Vector3.One();
  43. /**
  44. * The uvs of the particle.
  45. */
  46. public uvs: Vector4 = new Vector4(0.0, 0.0, 1.0, 1.0);
  47. /**
  48. * The current speed of the particle.
  49. */
  50. public velocity: Vector3 = Vector3.Zero();
  51. /**
  52. * The pivot point in the particle local space.
  53. */
  54. public pivot: Vector3 = Vector3.Zero();
  55. /**
  56. * Must the particle be translated from its pivot point in its local space ?
  57. * In this case, the pivot point is set at the origin of the particle local space and the particle is translated.
  58. * Default : false
  59. */
  60. public translateFromPivot: boolean = false;
  61. /**
  62. * Is the particle active or not ?
  63. */
  64. public alive: boolean = true;
  65. /**
  66. * Is the particle visible or not ?
  67. */
  68. public isVisible: boolean = true;
  69. /**
  70. * Index of this particle in the global "positions" array (Internal use)
  71. * @hidden
  72. */
  73. public _pos: number = 0;
  74. /**
  75. * @hidden Index of this particle in the global "indices" array (Internal use)
  76. */
  77. public _ind: number = 0;
  78. /**
  79. * @hidden ModelShape of this particle (Internal use)
  80. */
  81. public _model: ModelShape;
  82. /**
  83. * ModelShape id of this particle
  84. */
  85. public shapeId: number = 0;
  86. /**
  87. * Index of the particle in its shape id
  88. */
  89. public idxInShape: number = 0;
  90. /**
  91. * @hidden Reference to the shape model BoundingInfo object (Internal use)
  92. */
  93. public _modelBoundingInfo: BoundingInfo;
  94. /**
  95. * @hidden Particle BoundingInfo object (Internal use)
  96. */
  97. public _boundingInfo: BoundingInfo;
  98. /**
  99. * @hidden Reference to the SPS what the particle belongs to (Internal use)
  100. */
  101. public _sps: SolidParticleSystem;
  102. /**
  103. * @hidden Still set as invisible in order to skip useless computations (Internal use)
  104. */
  105. public _stillInvisible: boolean = false;
  106. /**
  107. * @hidden Last computed particle rotation matrix
  108. */
  109. public _rotationMatrix: number[] = [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0];
  110. /**
  111. * Parent particle Id, if any.
  112. * Default null.
  113. */
  114. public parentId: Nullable<number> = null;
  115. /**
  116. * The particle material identifier (integer) when MultiMaterials are enabled in the SPS.
  117. */
  118. public materialIndex: Nullable<number> = null;
  119. /**
  120. * Custom object or properties.
  121. */
  122. public props: Nullable<any> = null;
  123. /**
  124. * The culling strategy to use to check whether the solid particle must be culled or not when using isInFrustum().
  125. * The possible values are :
  126. * - AbstractMesh.CULLINGSTRATEGY_STANDARD
  127. * - AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY
  128. * - AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION
  129. * - AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY
  130. * The default value for solid particles is AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY
  131. * Please read each static variable documentation in the class AbstractMesh to get details about the culling process.
  132. * */
  133. public cullingStrategy = AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY;
  134. /**
  135. * @hidden Internal global position in the SPS.
  136. */
  137. public _globalPosition: Vector3 = Vector3.Zero();
  138. /**
  139. * Creates a Solid Particle object.
  140. * Don't create particles manually, use instead the Solid Particle System internal tools like _addParticle()
  141. * @param particleIndex (integer) is the particle index in the Solid Particle System pool.
  142. * @param particleId (integer) is the particle identifier. Unless some particles are removed from the SPS, it's the same value than the particle idx.
  143. * @param positionIndex (integer) is the starting index of the particle vertices in the SPS "positions" array.
  144. * @param indiceIndex (integer) is the starting index of the particle indices in the SPS "indices" array.
  145. * @param model (ModelShape) is a reference to the model shape on what the particle is designed.
  146. * @param shapeId (integer) is the model shape identifier in the SPS.
  147. * @param idxInShape (integer) is the index of the particle in the current model (ex: the 10th box of addShape(box, 30))
  148. * @param sps defines the sps it is associated to
  149. * @param modelBoundingInfo is the reference to the model BoundingInfo used for intersection computations.
  150. * @param materialIndex is the particle material identifier (integer) when the MultiMaterials are enabled in the SPS.
  151. */
  152. constructor(particleIndex: number, particleId: number, positionIndex: number, indiceIndex: number, model: Nullable<ModelShape>, shapeId: number, idxInShape: number, sps: SolidParticleSystem, modelBoundingInfo: Nullable<BoundingInfo> = null, materialIndex: Nullable<number> = null) {
  153. this.idx = particleIndex;
  154. this.id = particleId;
  155. this._pos = positionIndex;
  156. this._ind = indiceIndex;
  157. this._model = <ModelShape>model;
  158. this.shapeId = shapeId;
  159. this.idxInShape = idxInShape;
  160. this._sps = sps;
  161. if (modelBoundingInfo) {
  162. this._modelBoundingInfo = modelBoundingInfo;
  163. this._boundingInfo = new BoundingInfo(modelBoundingInfo.minimum, modelBoundingInfo.maximum);
  164. }
  165. if (materialIndex !== null) {
  166. this.materialIndex = materialIndex;
  167. }
  168. }
  169. /**
  170. * Copies the particle property values into the existing target : position, rotation, scaling, uvs, colors, pivot, parent, visibility, alive
  171. * @param target the particle target
  172. * @returns the current particle
  173. */
  174. public copyToRef(target: SolidParticle): SolidParticle {
  175. target.position.copyFrom(this.position);
  176. target.rotation.copyFrom(this.rotation);
  177. if (this.rotationQuaternion) {
  178. if (target.rotationQuaternion) {
  179. target.rotationQuaternion!.copyFrom(this.rotationQuaternion!);
  180. }
  181. else {
  182. target.rotationQuaternion = this.rotationQuaternion.clone();
  183. }
  184. }
  185. target.scaling.copyFrom(this.scaling);
  186. if (this.color) {
  187. if (target.color) {
  188. target.color!.copyFrom(this.color!);
  189. }
  190. else {
  191. target.color = this.color.clone();
  192. }
  193. }
  194. target.uvs.copyFrom(this.uvs);
  195. target.velocity.copyFrom(this.velocity);
  196. target.pivot.copyFrom(this.pivot);
  197. target.translateFromPivot = this.translateFromPivot;
  198. target.alive = this.alive;
  199. target.isVisible = this.isVisible;
  200. target.parentId = this.parentId;
  201. target.cullingStrategy = this.cullingStrategy;
  202. if (this.materialIndex !== null) {
  203. target.materialIndex = this.materialIndex;
  204. }
  205. return this;
  206. }
  207. /**
  208. * Legacy support, changed scale to scaling
  209. */
  210. public get scale(): Vector3 {
  211. return this.scaling;
  212. }
  213. /**
  214. * Legacy support, changed scale to scaling
  215. */
  216. public set scale(scale: Vector3) {
  217. this.scaling = scale;
  218. }
  219. /**
  220. * Legacy support, changed quaternion to rotationQuaternion
  221. */
  222. public get quaternion(): Nullable<Quaternion> {
  223. return this.rotationQuaternion;
  224. }
  225. /**
  226. * Legacy support, changed quaternion to rotationQuaternion
  227. */
  228. public set quaternion(q: Nullable<Quaternion>) {
  229. this.rotationQuaternion = q;
  230. }
  231. /**
  232. * Returns a boolean. True if the particle intersects another particle or another mesh, else false.
  233. * The intersection is computed on the particle bounding sphere and Axis Aligned Bounding Box (AABB)
  234. * @param target is the object (solid particle or mesh) what the intersection is computed against.
  235. * @returns true if it intersects
  236. */
  237. public intersectsMesh(target: Mesh | SolidParticle): boolean {
  238. if (!this._boundingInfo || !target._boundingInfo) {
  239. return false;
  240. }
  241. if (this._sps._bSphereOnly) {
  242. return BoundingSphere.Intersects(this._boundingInfo.boundingSphere, target._boundingInfo.boundingSphere);
  243. }
  244. return this._boundingInfo.intersects(target._boundingInfo, false);
  245. }
  246. /**
  247. * Returns `true` if the solid particle is within the frustum defined by the passed array of planes.
  248. * A particle is in the frustum if its bounding box intersects the frustum
  249. * @param frustumPlanes defines the frustum to test
  250. * @returns true if the particle is in the frustum planes
  251. */
  252. public isInFrustum(frustumPlanes: Plane[]): boolean {
  253. return this._boundingInfo !== null && this._boundingInfo.isInFrustum(frustumPlanes, this.cullingStrategy);
  254. }
  255. /**
  256. * get the rotation matrix of the particle
  257. * @hidden
  258. */
  259. public getRotationMatrix(m: Matrix) {
  260. let quaternion: Quaternion;
  261. if (this.rotationQuaternion) {
  262. quaternion = this.rotationQuaternion;
  263. }
  264. else {
  265. quaternion = TmpVectors.Quaternion[0];
  266. const rotation = this.rotation;
  267. Quaternion.RotationYawPitchRollToRef(rotation.y, rotation.x, rotation.z, quaternion);
  268. }
  269. quaternion.toRotationMatrix(m);
  270. }
  271. }
  272. /**
  273. * Represents the shape of the model used by one particle of a solid particle system.
  274. * SPS internal tool, don't use it manually.
  275. */
  276. export class ModelShape {
  277. /**
  278. * The shape id
  279. * @hidden
  280. */
  281. public shapeID: number;
  282. /**
  283. * flat array of model positions (internal use)
  284. * @hidden
  285. */
  286. public _shape: Vector3[];
  287. /**
  288. * flat array of model UVs (internal use)
  289. * @hidden
  290. */
  291. public _shapeUV: number[];
  292. /**
  293. * color array of the model
  294. * @hidden
  295. */
  296. public _shapeColors: number[];
  297. /**
  298. * indices array of the model
  299. * @hidden
  300. */
  301. public _indices: number[];
  302. /**
  303. * normals array of the model
  304. * @hidden
  305. */
  306. public _normals: number[];
  307. /**
  308. * length of the shape in the model indices array (internal use)
  309. * @hidden
  310. */
  311. public _indicesLength: number = 0;
  312. /**
  313. * Custom position function (internal use)
  314. * @hidden
  315. */
  316. public _positionFunction: Nullable<(particle: SolidParticle, i: number, s: number) => void>;
  317. /**
  318. * Custom vertex function (internal use)
  319. * @hidden
  320. */
  321. public _vertexFunction: Nullable<(particle: SolidParticle, vertex: Vector3, i: number) => void>;
  322. /**
  323. * Model material (internal use)
  324. * @hidden
  325. */
  326. public _material: Nullable<Material>;
  327. /**
  328. * Creates a ModelShape object. This is an internal simplified reference to a mesh used as for a model to replicate particles from by the SPS.
  329. * SPS internal tool, don't use it manually.
  330. * @hidden
  331. */
  332. constructor(id: number, shape: Vector3[], indices: number[], normals: number[], colors: number[], shapeUV: number[],
  333. posFunction: Nullable<(particle: SolidParticle, i: number, s: number) => void>, vtxFunction: Nullable<(particle: SolidParticle, vertex: Vector3, i: number) => void>,
  334. material: Nullable<Material>) {
  335. this.shapeID = id;
  336. this._shape = shape;
  337. this._indices = indices;
  338. this._indicesLength = indices.length;
  339. this._shapeUV = shapeUV;
  340. this._shapeColors = colors;
  341. this._normals = normals;
  342. this._positionFunction = posFunction;
  343. this._vertexFunction = vtxFunction;
  344. this._material = material;
  345. }
  346. }
  347. /**
  348. * Represents a Depth Sorted Particle in the solid particle system.
  349. * @hidden
  350. */
  351. export class DepthSortedParticle {
  352. /**
  353. * Particle index
  354. */
  355. public idx: number = 0;
  356. /**
  357. * Index of the particle in the "indices" array
  358. */
  359. public ind: number = 0;
  360. /**
  361. * Length of the particle shape in the "indices" array
  362. */
  363. public indicesLength: number = 0;
  364. /**
  365. * Squared distance from the particle to the camera
  366. */
  367. public sqDistance: number = 0.0;
  368. /**
  369. * Material index when used with MultiMaterials
  370. */
  371. public materialIndex: number = 0;
  372. /**
  373. * Creates a new sorted particle
  374. * @param materialIndex
  375. */
  376. constructor(idx: number, ind: number, indLength: number, materialIndex: number) {
  377. this.idx = idx;
  378. this.ind = ind;
  379. this.indicesLength = indLength;
  380. this.materialIndex = materialIndex;
  381. }
  382. }
  383. /**
  384. * Represents a solid particle vertex
  385. */
  386. export class SolidParticleVertex {
  387. /**
  388. * Vertex position
  389. */
  390. public position: Vector3;
  391. /**
  392. * Vertex color
  393. */
  394. public color: Color4;
  395. /**
  396. * Vertex UV
  397. */
  398. public uv: Vector2;
  399. /**
  400. * Creates a new solid particle vertex
  401. */
  402. constructor() {
  403. this.position = Vector3.Zero();
  404. this.color = new Color4(1.0, 1.0, 1.0, 1.0);
  405. this.uv = Vector2.Zero();
  406. }
  407. // Getters and Setters for back-compatibility
  408. /** Vertex x coordinate */
  409. public get x(): number {
  410. return this.position.x;
  411. }
  412. public set x(val: number) {
  413. this.position.x = val;
  414. }
  415. /** Vertex y coordinate */
  416. public get y(): number {
  417. return this.position.y;
  418. }
  419. public set y(val: number) {
  420. this.position.y = val;
  421. }
  422. /** Vertex z coordinate */
  423. public get z(): number {
  424. return this.position.z;
  425. }
  426. public set z(val: number) {
  427. this.position.z = val;
  428. }
  429. }