solidParticle.ts 13 KB

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