solidParticle.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. import { Nullable } from "../types";
  2. import { Vector3, Matrix, TmpVectors, Quaternion, Vector4 } 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. * The culling strategy to use to check whether the solid particle must be culled or not when using isInFrustum().
  121. * The possible values are :
  122. * - AbstractMesh.CULLINGSTRATEGY_STANDARD
  123. * - AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY
  124. * - AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION
  125. * - AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY
  126. * The default value for solid particles is AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY
  127. * Please read each static variable documentation in the class AbstractMesh to get details about the culling process.
  128. * */
  129. public cullingStrategy = AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY;
  130. /**
  131. * @hidden Internal global position in the SPS.
  132. */
  133. public _globalPosition: Vector3 = Vector3.Zero();
  134. /**
  135. * Creates a Solid Particle object.
  136. * Don't create particles manually, use instead the Solid Particle System internal tools like _addParticle()
  137. * @param particleIndex (integer) is the particle index in the Solid Particle System pool.
  138. * @param particleId (integer) is the particle identifier. Unless some particles are removed from the SPS, it's the same value than the particle idx.
  139. * @param positionIndex (integer) is the starting index of the particle vertices in the SPS "positions" array.
  140. * @param indiceIndex (integer) is the starting index of the particle indices in the SPS "indices" array.
  141. * @param model (ModelShape) is a reference to the model shape on what the particle is designed.
  142. * @param shapeId (integer) is the model shape identifier in the SPS.
  143. * @param idxInShape (integer) is the index of the particle in the current model (ex: the 10th box of addShape(box, 30))
  144. * @param sps defines the sps it is associated to
  145. * @param modelBoundingInfo is the reference to the model BoundingInfo used for intersection computations.
  146. * @param materialIndex is the particle material identifier (integer) when the MultiMaterials are enabled in the SPS.
  147. */
  148. 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) {
  149. this.idx = particleIndex;
  150. this.id = particleId;
  151. this._pos = positionIndex;
  152. this._ind = indiceIndex;
  153. this._model = <ModelShape>model;
  154. this.shapeId = shapeId;
  155. this.idxInShape = idxInShape;
  156. this._sps = sps;
  157. if (modelBoundingInfo) {
  158. this._modelBoundingInfo = modelBoundingInfo;
  159. this._boundingInfo = new BoundingInfo(modelBoundingInfo.minimum, modelBoundingInfo.maximum);
  160. }
  161. if (materialIndex !== null) {
  162. this.materialIndex = materialIndex;
  163. }
  164. }
  165. /**
  166. * Copies the particle property values into the existing target : position, rotation, scaling, uvs, colors, pivot, parent, visibility, alive
  167. * @param target the particle target
  168. * @returns the current particle
  169. */
  170. public copyToRef(target: SolidParticle): SolidParticle {
  171. target.position.copyFrom(this.position);
  172. target.rotation.copyFrom(this.rotation);
  173. if (this.rotationQuaternion) {
  174. if (target.rotationQuaternion) {
  175. target.rotationQuaternion!.copyFrom(this.rotationQuaternion!);
  176. }
  177. else {
  178. target.rotationQuaternion = this.rotationQuaternion.clone();
  179. }
  180. }
  181. target.scaling.copyFrom(this.scaling);
  182. if (this.color) {
  183. if (target.color) {
  184. target.color!.copyFrom(this.color!);
  185. }
  186. else {
  187. target.color = this.color.clone();
  188. }
  189. }
  190. target.uvs.copyFrom(this.uvs);
  191. target.velocity.copyFrom(this.velocity);
  192. target.pivot.copyFrom(this.pivot);
  193. target.translateFromPivot = this.translateFromPivot;
  194. target.alive = this.alive;
  195. target.isVisible = this.isVisible;
  196. target.parentId = this.parentId;
  197. target.cullingStrategy = this.cullingStrategy;
  198. if (this.materialIndex !== null) {
  199. target.materialIndex = this.materialIndex;
  200. }
  201. return this;
  202. }
  203. /**
  204. * Legacy support, changed scale to scaling
  205. */
  206. public get scale(): Vector3 {
  207. return this.scaling;
  208. }
  209. /**
  210. * Legacy support, changed scale to scaling
  211. */
  212. public set scale(scale: Vector3) {
  213. this.scaling = scale;
  214. }
  215. /**
  216. * Legacy support, changed quaternion to rotationQuaternion
  217. */
  218. public get quaternion(): Nullable<Quaternion> {
  219. return this.rotationQuaternion;
  220. }
  221. /**
  222. * Legacy support, changed quaternion to rotationQuaternion
  223. */
  224. public set quaternion(q: Nullable<Quaternion>) {
  225. this.rotationQuaternion = q;
  226. }
  227. /**
  228. * Returns a boolean. True if the particle intersects another particle or another mesh, else false.
  229. * The intersection is computed on the particle bounding sphere and Axis Aligned Bounding Box (AABB)
  230. * @param target is the object (solid particle or mesh) what the intersection is computed against.
  231. * @returns true if it intersects
  232. */
  233. public intersectsMesh(target: Mesh | SolidParticle): boolean {
  234. if (!this._boundingInfo || !target._boundingInfo) {
  235. return false;
  236. }
  237. if (this._sps._bSphereOnly) {
  238. return BoundingSphere.Intersects(this._boundingInfo.boundingSphere, target._boundingInfo.boundingSphere);
  239. }
  240. return this._boundingInfo.intersects(target._boundingInfo, false);
  241. }
  242. /**
  243. * Returns `true` if the solid particle is within the frustum defined by the passed array of planes.
  244. * A particle is in the frustum if its bounding box intersects the frustum
  245. * @param frustumPlanes defines the frustum to test
  246. * @returns true if the particle is in the frustum planes
  247. */
  248. public isInFrustum(frustumPlanes: Plane[]): boolean {
  249. return this._boundingInfo !== null && this._boundingInfo.isInFrustum(frustumPlanes, this.cullingStrategy);
  250. }
  251. /**
  252. * get the rotation matrix of the particle
  253. * @hidden
  254. */
  255. public getRotationMatrix(m: Matrix) {
  256. let quaternion: Quaternion;
  257. if (this.rotationQuaternion) {
  258. quaternion = this.rotationQuaternion;
  259. }
  260. else {
  261. quaternion = TmpVectors.Quaternion[0];
  262. const rotation = this.rotation;
  263. Quaternion.RotationYawPitchRollToRef(rotation.y, rotation.x, rotation.z, quaternion);
  264. }
  265. quaternion.toRotationMatrix(m);
  266. }
  267. }
  268. /**
  269. * Represents the shape of the model used by one particle of a solid particle system.
  270. * SPS internal tool, don't use it manually.
  271. */
  272. export class ModelShape {
  273. /**
  274. * The shape id
  275. * @hidden
  276. */
  277. public shapeID: number;
  278. /**
  279. * flat array of model positions (internal use)
  280. * @hidden
  281. */
  282. public _shape: Vector3[];
  283. /**
  284. * flat array of model UVs (internal use)
  285. * @hidden
  286. */
  287. public _shapeUV: number[];
  288. /**
  289. * color array of the model
  290. * @hidden
  291. */
  292. public _shapeColors: number[];
  293. /**
  294. * indices array of the model
  295. * @hidden
  296. */
  297. public _indices: number[];
  298. /**
  299. * normals array of the model
  300. * @hidden
  301. */
  302. public _normals: number[];
  303. /**
  304. * length of the shape in the model indices array (internal use)
  305. * @hidden
  306. */
  307. public _indicesLength: number = 0;
  308. /**
  309. * Custom position function (internal use)
  310. * @hidden
  311. */
  312. public _positionFunction: Nullable<(particle: SolidParticle, i: number, s: number) => void>;
  313. /**
  314. * Custom vertex function (internal use)
  315. * @hidden
  316. */
  317. public _vertexFunction: Nullable<(particle: SolidParticle, vertex: Vector3, i: number) => void>;
  318. /**
  319. * Model material (internal use)
  320. * @hidden
  321. */
  322. public _material: Nullable<Material>;
  323. /**
  324. * 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.
  325. * SPS internal tool, don't use it manually.
  326. * @hidden
  327. */
  328. constructor(id: number, shape: Vector3[], indices: number[], normals: number[], colors: number[], shapeUV: number[],
  329. posFunction: Nullable<(particle: SolidParticle, i: number, s: number) => void>, vtxFunction: Nullable<(particle: SolidParticle, vertex: Vector3, i: number) => void>,
  330. material: Nullable<Material>) {
  331. this.shapeID = id;
  332. this._shape = shape;
  333. this._indices = indices;
  334. this._indicesLength = indices.length;
  335. this._shapeUV = shapeUV;
  336. this._shapeColors = colors;
  337. this._normals = normals;
  338. this._positionFunction = posFunction;
  339. this._vertexFunction = vtxFunction;
  340. this._material = material;
  341. }
  342. }
  343. /**
  344. * Represents a Depth Sorted Particle in the solid particle system.
  345. * @hidden
  346. */
  347. export class DepthSortedParticle {
  348. /**
  349. * Particle index
  350. */
  351. public idx: number = 0;
  352. /**
  353. * Index of the particle in the "indices" array
  354. */
  355. public ind: number = 0;
  356. /**
  357. * Length of the particle shape in the "indices" array
  358. */
  359. public indicesLength: number = 0;
  360. /**
  361. * Squared distance from the particle to the camera
  362. */
  363. public sqDistance: number = 0.0;
  364. /**
  365. * Material index when used with MultiMaterials
  366. */
  367. public materialIndex: number = 0;
  368. /**
  369. * Creates a new sorted particle
  370. * @param materialIndex
  371. */
  372. constructor(idx: number, ind: number, indLength: number, materialIndex: number) {
  373. this.idx = idx;
  374. this.ind = ind;
  375. this.indicesLength = indLength;
  376. this.materialIndex = materialIndex;
  377. }
  378. }