@babylonjs/core 7.27.1 → 7.27.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/Animations/animatable.core.d.ts +198 -0
  2. package/Animations/animatable.core.js +893 -0
  3. package/Animations/animatable.core.js.map +1 -0
  4. package/Animations/animatable.d.ts +4 -213
  5. package/Animations/animatable.js +5 -886
  6. package/Animations/animatable.js.map +1 -1
  7. package/Animations/animationGroup.d.ts +1 -1
  8. package/Animations/animationGroup.js.map +1 -1
  9. package/Animations/runtimeAnimation.d.ts +1 -0
  10. package/Animations/runtimeAnimation.js +25 -1
  11. package/Animations/runtimeAnimation.js.map +1 -1
  12. package/Audio/audioSceneComponent.d.ts +0 -4
  13. package/Audio/audioSceneComponent.js.map +1 -1
  14. package/Behaviors/Cameras/bouncingBehavior.js.map +1 -1
  15. package/Behaviors/Cameras/framingBehavior.js.map +1 -1
  16. package/Bones/skeleton.d.ts +1 -1
  17. package/Bones/skeleton.js.map +1 -1
  18. package/Culling/ray.core.d.ts +328 -0
  19. package/Culling/ray.core.js +934 -0
  20. package/Culling/ray.core.js.map +1 -0
  21. package/Culling/ray.d.ts +1 -220
  22. package/Culling/ray.js +12 -791
  23. package/Culling/ray.js.map +1 -1
  24. package/Engines/abstractEngine.js +2 -2
  25. package/Engines/abstractEngine.js.map +1 -1
  26. package/FlowGraph/Blocks/Execution/Animation/flowGraphPauseAnimationBlock.d.ts +1 -1
  27. package/FlowGraph/Blocks/Execution/Animation/flowGraphPauseAnimationBlock.js.map +1 -1
  28. package/FlowGraph/Blocks/Execution/Animation/flowGraphPlayAnimationBlock.d.ts +1 -1
  29. package/FlowGraph/Blocks/Execution/Animation/flowGraphPlayAnimationBlock.js.map +1 -1
  30. package/FlowGraph/Blocks/Execution/Animation/flowGraphStopAnimationBlock.d.ts +1 -1
  31. package/FlowGraph/Blocks/Execution/Animation/flowGraphStopAnimationBlock.js.map +1 -1
  32. package/Inputs/scene.inputManager.js +1 -1
  33. package/Inputs/scene.inputManager.js.map +1 -1
  34. package/Layers/effectLayerSceneComponent.d.ts +0 -6
  35. package/Layers/effectLayerSceneComponent.js +0 -1
  36. package/Layers/effectLayerSceneComponent.js.map +1 -1
  37. package/Layers/layerSceneComponent.d.ts +0 -9
  38. package/Layers/layerSceneComponent.js +0 -1
  39. package/Layers/layerSceneComponent.js.map +1 -1
  40. package/LensFlares/lensFlareSystemSceneComponent.d.ts +0 -5
  41. package/LensFlares/lensFlareSystemSceneComponent.js +0 -1
  42. package/LensFlares/lensFlareSystemSceneComponent.js.map +1 -1
  43. package/Lights/light.js.map +1 -1
  44. package/Materials/Textures/Procedurals/proceduralTextureSceneComponent.d.ts +0 -10
  45. package/Materials/Textures/Procedurals/proceduralTextureSceneComponent.js +0 -1
  46. package/Materials/Textures/Procedurals/proceduralTextureSceneComponent.js.map +1 -1
  47. package/Materials/effectRenderer.d.ts +1 -0
  48. package/Materials/effectRenderer.js +2 -0
  49. package/Materials/effectRenderer.js.map +1 -1
  50. package/Meshes/mesh.d.ts +7 -0
  51. package/Meshes/mesh.js +15 -0
  52. package/Meshes/mesh.js.map +1 -1
  53. package/Misc/assetsManager.d.ts +1 -1
  54. package/Misc/assetsManager.js.map +1 -1
  55. package/Misc/tools.js +1 -13
  56. package/Misc/tools.js.map +1 -1
  57. package/Sprites/spriteSceneComponent.d.ts +1 -1
  58. package/Sprites/spriteSceneComponent.js +4 -4
  59. package/Sprites/spriteSceneComponent.js.map +1 -1
  60. package/assetContainer.d.ts +1 -1
  61. package/assetContainer.js.map +1 -1
  62. package/node.d.ts +1 -1
  63. package/node.js.map +1 -1
  64. package/package.json +1 -1
  65. package/scene.d.ts +45 -4
  66. package/scene.js +81 -54
  67. package/scene.js.map +1 -1
package/Culling/ray.js CHANGED
@@ -1,810 +1,31 @@
1
- import { BuildArray } from "../Misc/arrayTools.js";
2
- import { Matrix, Vector3, TmpVectors } from "../Maths/math.vector.js";
3
- import { PickingInfo } from "../Collisions/pickingInfo.js";
4
- import { IntersectionInfo } from "../Collisions/intersectionInfo.js";
5
1
  import { Scene } from "../scene.js";
6
2
  import { Camera } from "../Cameras/camera.js";
7
- import { EngineStore } from "../Engines/engineStore.js";
8
- import { Epsilon } from "../Maths/math.constants.js";
9
- /**
10
- * Class representing a ray with position and direction
11
- */
12
- export class Ray {
13
- /**
14
- * Creates a new ray
15
- * @param origin origin point
16
- * @param direction direction
17
- * @param length length of the ray
18
- * @param epsilon The epsilon value to use when calculating the ray/triangle intersection (default: 0)
19
- */
20
- constructor(
21
- /** origin point */
22
- origin,
23
- /** direction */
24
- direction,
25
- /** [Number.MAX_VALUE] length of the ray */
26
- length = Number.MAX_VALUE,
27
- /** [Epsilon] The epsilon value to use when calculating the ray/triangle intersection (default: Epsilon from math constants) */
28
- epsilon = Epsilon) {
29
- this.origin = origin;
30
- this.direction = direction;
31
- this.length = length;
32
- this.epsilon = epsilon;
33
- }
34
- // Methods
35
- /**
36
- * Clone the current ray
37
- * @returns a new ray
38
- */
39
- clone() {
40
- return new Ray(this.origin.clone(), this.direction.clone(), this.length);
41
- }
42
- /**
43
- * Checks if the ray intersects a box
44
- * This does not account for the ray length by design to improve perfs.
45
- * @param minimum bound of the box
46
- * @param maximum bound of the box
47
- * @param intersectionTreshold extra extend to be added to the box in all direction
48
- * @returns if the box was hit
49
- */
50
- intersectsBoxMinMax(minimum, maximum, intersectionTreshold = 0) {
51
- const newMinimum = Ray._TmpVector3[0].copyFromFloats(minimum.x - intersectionTreshold, minimum.y - intersectionTreshold, minimum.z - intersectionTreshold);
52
- const newMaximum = Ray._TmpVector3[1].copyFromFloats(maximum.x + intersectionTreshold, maximum.y + intersectionTreshold, maximum.z + intersectionTreshold);
53
- let d = 0.0;
54
- let maxValue = Number.MAX_VALUE;
55
- let inv;
56
- let min;
57
- let max;
58
- let temp;
59
- if (Math.abs(this.direction.x) < 0.0000001) {
60
- if (this.origin.x < newMinimum.x || this.origin.x > newMaximum.x) {
61
- return false;
62
- }
63
- }
64
- else {
65
- inv = 1.0 / this.direction.x;
66
- min = (newMinimum.x - this.origin.x) * inv;
67
- max = (newMaximum.x - this.origin.x) * inv;
68
- if (max === -Infinity) {
69
- max = Infinity;
70
- }
71
- if (min > max) {
72
- temp = min;
73
- min = max;
74
- max = temp;
75
- }
76
- d = Math.max(min, d);
77
- maxValue = Math.min(max, maxValue);
78
- if (d > maxValue) {
79
- return false;
80
- }
81
- }
82
- if (Math.abs(this.direction.y) < 0.0000001) {
83
- if (this.origin.y < newMinimum.y || this.origin.y > newMaximum.y) {
84
- return false;
85
- }
86
- }
87
- else {
88
- inv = 1.0 / this.direction.y;
89
- min = (newMinimum.y - this.origin.y) * inv;
90
- max = (newMaximum.y - this.origin.y) * inv;
91
- if (max === -Infinity) {
92
- max = Infinity;
93
- }
94
- if (min > max) {
95
- temp = min;
96
- min = max;
97
- max = temp;
98
- }
99
- d = Math.max(min, d);
100
- maxValue = Math.min(max, maxValue);
101
- if (d > maxValue) {
102
- return false;
103
- }
104
- }
105
- if (Math.abs(this.direction.z) < 0.0000001) {
106
- if (this.origin.z < newMinimum.z || this.origin.z > newMaximum.z) {
107
- return false;
108
- }
109
- }
110
- else {
111
- inv = 1.0 / this.direction.z;
112
- min = (newMinimum.z - this.origin.z) * inv;
113
- max = (newMaximum.z - this.origin.z) * inv;
114
- if (max === -Infinity) {
115
- max = Infinity;
116
- }
117
- if (min > max) {
118
- temp = min;
119
- min = max;
120
- max = temp;
121
- }
122
- d = Math.max(min, d);
123
- maxValue = Math.min(max, maxValue);
124
- if (d > maxValue) {
125
- return false;
126
- }
127
- }
128
- return true;
129
- }
130
- /**
131
- * Checks if the ray intersects a box
132
- * This does not account for the ray lenght by design to improve perfs.
133
- * @param box the bounding box to check
134
- * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
135
- * @returns if the box was hit
136
- */
137
- intersectsBox(box, intersectionTreshold = 0) {
138
- return this.intersectsBoxMinMax(box.minimum, box.maximum, intersectionTreshold);
139
- }
140
- /**
141
- * If the ray hits a sphere
142
- * @param sphere the bounding sphere to check
143
- * @param intersectionTreshold extra extend to be added to the BoundingSphere in all direction
144
- * @returns true if it hits the sphere
145
- */
146
- intersectsSphere(sphere, intersectionTreshold = 0) {
147
- const x = sphere.center.x - this.origin.x;
148
- const y = sphere.center.y - this.origin.y;
149
- const z = sphere.center.z - this.origin.z;
150
- const pyth = x * x + y * y + z * z;
151
- const radius = sphere.radius + intersectionTreshold;
152
- const rr = radius * radius;
153
- if (pyth <= rr) {
154
- return true;
155
- }
156
- const dot = x * this.direction.x + y * this.direction.y + z * this.direction.z;
157
- if (dot < 0.0) {
158
- return false;
159
- }
160
- const temp = pyth - dot * dot;
161
- return temp <= rr;
162
- }
163
- /**
164
- * If the ray hits a triange
165
- * @param vertex0 triangle vertex
166
- * @param vertex1 triangle vertex
167
- * @param vertex2 triangle vertex
168
- * @returns intersection information if hit
169
- */
170
- intersectsTriangle(vertex0, vertex1, vertex2) {
171
- const edge1 = Ray._TmpVector3[0];
172
- const edge2 = Ray._TmpVector3[1];
173
- const pvec = Ray._TmpVector3[2];
174
- const tvec = Ray._TmpVector3[3];
175
- const qvec = Ray._TmpVector3[4];
176
- vertex1.subtractToRef(vertex0, edge1);
177
- vertex2.subtractToRef(vertex0, edge2);
178
- Vector3.CrossToRef(this.direction, edge2, pvec);
179
- const det = Vector3.Dot(edge1, pvec);
180
- if (det === 0) {
181
- return null;
182
- }
183
- const invdet = 1 / det;
184
- this.origin.subtractToRef(vertex0, tvec);
185
- const bv = Vector3.Dot(tvec, pvec) * invdet;
186
- if (bv < -this.epsilon || bv > 1.0 + this.epsilon) {
187
- return null;
188
- }
189
- Vector3.CrossToRef(tvec, edge1, qvec);
190
- const bw = Vector3.Dot(this.direction, qvec) * invdet;
191
- if (bw < -this.epsilon || bv + bw > 1.0 + this.epsilon) {
192
- return null;
193
- }
194
- //check if the distance is longer than the predefined length.
195
- const distance = Vector3.Dot(edge2, qvec) * invdet;
196
- if (distance > this.length) {
197
- return null;
198
- }
199
- return new IntersectionInfo(1 - bv - bw, bv, distance);
200
- }
201
- /**
202
- * Checks if ray intersects a plane
203
- * @param plane the plane to check
204
- * @returns the distance away it was hit
205
- */
206
- intersectsPlane(plane) {
207
- let distance;
208
- const result1 = Vector3.Dot(plane.normal, this.direction);
209
- if (Math.abs(result1) < 9.99999997475243e-7) {
210
- return null;
211
- }
212
- else {
213
- const result2 = Vector3.Dot(plane.normal, this.origin);
214
- distance = (-plane.d - result2) / result1;
215
- if (distance < 0.0) {
216
- if (distance < -9.99999997475243e-7) {
217
- return null;
218
- }
219
- else {
220
- return 0;
221
- }
222
- }
223
- return distance;
224
- }
225
- }
226
- /**
227
- * Calculate the intercept of a ray on a given axis
228
- * @param axis to check 'x' | 'y' | 'z'
229
- * @param offset from axis interception (i.e. an offset of 1y is intercepted above ground)
230
- * @returns a vector containing the coordinates where 'axis' is equal to zero (else offset), or null if there is no intercept.
231
- */
232
- intersectsAxis(axis, offset = 0) {
233
- switch (axis) {
234
- case "y": {
235
- const t = (this.origin.y - offset) / this.direction.y;
236
- if (t > 0) {
237
- return null;
238
- }
239
- return new Vector3(this.origin.x + this.direction.x * -t, offset, this.origin.z + this.direction.z * -t);
240
- }
241
- case "x": {
242
- const t = (this.origin.x - offset) / this.direction.x;
243
- if (t > 0) {
244
- return null;
245
- }
246
- return new Vector3(offset, this.origin.y + this.direction.y * -t, this.origin.z + this.direction.z * -t);
247
- }
248
- case "z": {
249
- const t = (this.origin.z - offset) / this.direction.z;
250
- if (t > 0) {
251
- return null;
252
- }
253
- return new Vector3(this.origin.x + this.direction.x * -t, this.origin.y + this.direction.y * -t, offset);
254
- }
255
- default:
256
- return null;
257
- }
258
- }
259
- /**
260
- * Checks if ray intersects a mesh. The ray is defined in WORLD space. A mesh triangle can be picked both from its front and back sides,
261
- * irrespective of orientation.
262
- * @param mesh the mesh to check
263
- * @param fastCheck defines if the first intersection will be used (and not the closest)
264
- * @param trianglePredicate defines an optional predicate used to select faces when a mesh intersection is detected
265
- * @param onlyBoundingInfo defines a boolean indicating if picking should only happen using bounding info (false by default)
266
- * @param worldToUse defines the world matrix to use to get the world coordinate of the intersection point
267
- * @param skipBoundingInfo a boolean indicating if we should skip the bounding info check
268
- * @returns picking info of the intersection
269
- */
270
- intersectsMesh(mesh, fastCheck, trianglePredicate, onlyBoundingInfo = false, worldToUse, skipBoundingInfo = false) {
271
- const tm = TmpVectors.Matrix[0];
272
- mesh.getWorldMatrix().invertToRef(tm);
273
- if (this._tmpRay) {
274
- Ray.TransformToRef(this, tm, this._tmpRay);
275
- }
276
- else {
277
- this._tmpRay = Ray.Transform(this, tm);
278
- }
279
- return mesh.intersects(this._tmpRay, fastCheck, trianglePredicate, onlyBoundingInfo, worldToUse, skipBoundingInfo);
280
- }
281
- /**
282
- * Checks if ray intersects a mesh
283
- * @param meshes the meshes to check
284
- * @param fastCheck defines if the first intersection will be used (and not the closest)
285
- * @param results array to store result in
286
- * @returns Array of picking infos
287
- */
288
- intersectsMeshes(meshes, fastCheck, results) {
289
- if (results) {
290
- results.length = 0;
291
- }
292
- else {
293
- results = [];
294
- }
295
- for (let i = 0; i < meshes.length; i++) {
296
- const pickInfo = this.intersectsMesh(meshes[i], fastCheck);
297
- if (pickInfo.hit) {
298
- results.push(pickInfo);
299
- }
300
- }
301
- results.sort(this._comparePickingInfo);
302
- return results;
303
- }
304
- _comparePickingInfo(pickingInfoA, pickingInfoB) {
305
- if (pickingInfoA.distance < pickingInfoB.distance) {
306
- return -1;
307
- }
308
- else if (pickingInfoA.distance > pickingInfoB.distance) {
309
- return 1;
310
- }
311
- else {
312
- return 0;
313
- }
314
- }
315
- /**
316
- * Intersection test between the ray and a given segment within a given tolerance (threshold)
317
- * @param sega the first point of the segment to test the intersection against
318
- * @param segb the second point of the segment to test the intersection against
319
- * @param threshold the tolerance margin, if the ray doesn't intersect the segment but is close to the given threshold, the intersection is successful
320
- * @returns the distance from the ray origin to the intersection point if there's intersection, or -1 if there's no intersection
321
- */
322
- intersectionSegment(sega, segb, threshold) {
323
- const o = this.origin;
324
- const u = TmpVectors.Vector3[0];
325
- const rsegb = TmpVectors.Vector3[1];
326
- const v = TmpVectors.Vector3[2];
327
- const w = TmpVectors.Vector3[3];
328
- segb.subtractToRef(sega, u);
329
- this.direction.scaleToRef(Ray._Rayl, v);
330
- o.addToRef(v, rsegb);
331
- sega.subtractToRef(o, w);
332
- const a = Vector3.Dot(u, u); // always >= 0
333
- const b = Vector3.Dot(u, v);
334
- const c = Vector3.Dot(v, v); // always >= 0
335
- const d = Vector3.Dot(u, w);
336
- const e = Vector3.Dot(v, w);
337
- const D = a * c - b * b; // always >= 0
338
- let sN, sD = D; // sc = sN / sD, default sD = D >= 0
339
- let tN, tD = D; // tc = tN / tD, default tD = D >= 0
340
- // compute the line parameters of the two closest points
341
- if (D < Ray._Smallnum) {
342
- // the lines are almost parallel
343
- sN = 0.0; // force using point P0 on segment S1
344
- sD = 1.0; // to prevent possible division by 0.0 later
345
- tN = e;
346
- tD = c;
347
- }
348
- else {
349
- // get the closest points on the infinite lines
350
- sN = b * e - c * d;
351
- tN = a * e - b * d;
352
- if (sN < 0.0) {
353
- // sc < 0 => the s=0 edge is visible
354
- sN = 0.0;
355
- tN = e;
356
- tD = c;
357
- }
358
- else if (sN > sD) {
359
- // sc > 1 => the s=1 edge is visible
360
- sN = sD;
361
- tN = e + b;
362
- tD = c;
363
- }
364
- }
365
- if (tN < 0.0) {
366
- // tc < 0 => the t=0 edge is visible
367
- tN = 0.0;
368
- // recompute sc for this edge
369
- if (-d < 0.0) {
370
- sN = 0.0;
371
- }
372
- else if (-d > a) {
373
- sN = sD;
374
- }
375
- else {
376
- sN = -d;
377
- sD = a;
378
- }
379
- }
380
- else if (tN > tD) {
381
- // tc > 1 => the t=1 edge is visible
382
- tN = tD;
383
- // recompute sc for this edge
384
- if (-d + b < 0.0) {
385
- sN = 0;
386
- }
387
- else if (-d + b > a) {
388
- sN = sD;
389
- }
390
- else {
391
- sN = -d + b;
392
- sD = a;
393
- }
394
- }
395
- // finally do the division to get sc and tc
396
- const sc = Math.abs(sN) < Ray._Smallnum ? 0.0 : sN / sD;
397
- const tc = Math.abs(tN) < Ray._Smallnum ? 0.0 : tN / tD;
398
- // get the difference of the two closest points
399
- const qtc = TmpVectors.Vector3[4];
400
- v.scaleToRef(tc, qtc);
401
- const qsc = TmpVectors.Vector3[5];
402
- u.scaleToRef(sc, qsc);
403
- qsc.addInPlace(w);
404
- const dP = TmpVectors.Vector3[6];
405
- qsc.subtractToRef(qtc, dP); // = S1(sc) - S2(tc)
406
- const isIntersected = tc > 0 && tc <= this.length && dP.lengthSquared() < threshold * threshold; // return intersection result
407
- if (isIntersected) {
408
- return qsc.length();
409
- }
410
- return -1;
411
- }
412
- /**
413
- * Update the ray from viewport position
414
- * @param x position
415
- * @param y y position
416
- * @param viewportWidth viewport width
417
- * @param viewportHeight viewport height
418
- * @param world world matrix
419
- * @param view view matrix
420
- * @param projection projection matrix
421
- * @param enableDistantPicking defines if picking should handle large values for mesh position/scaling (false by default)
422
- * @returns this ray updated
423
- */
424
- update(x, y, viewportWidth, viewportHeight, world, view, projection, enableDistantPicking = false) {
425
- if (enableDistantPicking) {
426
- // With world matrices having great values (like 8000000000 on 1 or more scaling or position axis),
427
- // multiplying view/projection/world and doing invert will result in loss of float precision in the matrix.
428
- // One way to fix it is to compute the ray with world at identity then transform the ray in object space.
429
- // This is slower (2 matrix inverts instead of 1) but precision is preserved.
430
- // This is hidden behind `EnableDistantPicking` flag (default is false)
431
- if (!Ray._RayDistant) {
432
- Ray._RayDistant = Ray.Zero();
433
- }
434
- Ray._RayDistant.unprojectRayToRef(x, y, viewportWidth, viewportHeight, Matrix.IdentityReadOnly, view, projection);
435
- const tm = TmpVectors.Matrix[0];
436
- world.invertToRef(tm);
437
- Ray.TransformToRef(Ray._RayDistant, tm, this);
438
- }
439
- else {
440
- this.unprojectRayToRef(x, y, viewportWidth, viewportHeight, world, view, projection);
441
- }
442
- return this;
443
- }
444
- // Statics
445
- /**
446
- * Creates a ray with origin and direction of 0,0,0
447
- * @returns the new ray
448
- */
449
- static Zero() {
450
- return new Ray(Vector3.Zero(), Vector3.Zero());
451
- }
452
- /**
453
- * Creates a new ray from screen space and viewport
454
- * @param x position
455
- * @param y y position
456
- * @param viewportWidth viewport width
457
- * @param viewportHeight viewport height
458
- * @param world world matrix
459
- * @param view view matrix
460
- * @param projection projection matrix
461
- * @returns new ray
462
- */
463
- static CreateNew(x, y, viewportWidth, viewportHeight, world, view, projection) {
464
- const result = Ray.Zero();
465
- return result.update(x, y, viewportWidth, viewportHeight, world, view, projection);
466
- }
467
- /**
468
- * Function will create a new transformed ray starting from origin and ending at the end point. Ray's length will be set, and ray will be
469
- * transformed to the given world matrix.
470
- * @param origin The origin point
471
- * @param end The end point
472
- * @param world a matrix to transform the ray to. Default is the identity matrix.
473
- * @returns the new ray
474
- */
475
- static CreateNewFromTo(origin, end, world = Matrix.IdentityReadOnly) {
476
- const result = new Ray(new Vector3(0, 0, 0), new Vector3(0, 0, 0));
477
- return Ray.CreateFromToToRef(origin, end, result, world);
478
- }
479
- /**
480
- * Function will update a transformed ray starting from origin and ending at the end point. Ray's length will be set, and ray will be
481
- * transformed to the given world matrix.
482
- * @param origin The origin point
483
- * @param end The end point
484
- * @param result the object to store the result
485
- * @param world a matrix to transform the ray to. Default is the identity matrix.
486
- * @returns the ref ray
487
- */
488
- static CreateFromToToRef(origin, end, result, world = Matrix.IdentityReadOnly) {
489
- result.origin.copyFrom(origin);
490
- const direction = end.subtractToRef(origin, result.direction);
491
- const length = Math.sqrt(direction.x * direction.x + direction.y * direction.y + direction.z * direction.z);
492
- result.length = length;
493
- result.direction.normalize();
494
- return Ray.TransformToRef(result, world, result);
495
- }
496
- /**
497
- * Transforms a ray by a matrix
498
- * @param ray ray to transform
499
- * @param matrix matrix to apply
500
- * @returns the resulting new ray
501
- */
502
- static Transform(ray, matrix) {
503
- const result = new Ray(new Vector3(0, 0, 0), new Vector3(0, 0, 0));
504
- Ray.TransformToRef(ray, matrix, result);
505
- return result;
506
- }
507
- /**
508
- * Transforms a ray by a matrix
509
- * @param ray ray to transform
510
- * @param matrix matrix to apply
511
- * @param result ray to store result in
512
- * @returns the updated result ray
513
- */
514
- static TransformToRef(ray, matrix, result) {
515
- Vector3.TransformCoordinatesToRef(ray.origin, matrix, result.origin);
516
- Vector3.TransformNormalToRef(ray.direction, matrix, result.direction);
517
- result.length = ray.length;
518
- result.epsilon = ray.epsilon;
519
- const dir = result.direction;
520
- const len = dir.length();
521
- if (!(len === 0 || len === 1)) {
522
- const num = 1.0 / len;
523
- dir.x *= num;
524
- dir.y *= num;
525
- dir.z *= num;
526
- result.length *= len;
527
- }
528
- return result;
529
- }
530
- /**
531
- * Unproject a ray from screen space to object space
532
- * @param sourceX defines the screen space x coordinate to use
533
- * @param sourceY defines the screen space y coordinate to use
534
- * @param viewportWidth defines the current width of the viewport
535
- * @param viewportHeight defines the current height of the viewport
536
- * @param world defines the world matrix to use (can be set to Identity to go to world space)
537
- * @param view defines the view matrix to use
538
- * @param projection defines the projection matrix to use
539
- */
540
- unprojectRayToRef(sourceX, sourceY, viewportWidth, viewportHeight, world, view, projection) {
541
- const matrix = TmpVectors.Matrix[0];
542
- world.multiplyToRef(view, matrix);
543
- matrix.multiplyToRef(projection, matrix);
544
- matrix.invert();
545
- const engine = EngineStore.LastCreatedEngine;
546
- const nearScreenSource = TmpVectors.Vector3[0];
547
- nearScreenSource.x = (sourceX / viewportWidth) * 2 - 1;
548
- nearScreenSource.y = -((sourceY / viewportHeight) * 2 - 1);
549
- nearScreenSource.z = engine?.useReverseDepthBuffer ? 1 : engine?.isNDCHalfZRange ? 0 : -1;
550
- // far Z need to be close but < to 1 or camera projection matrix with maxZ = 0 will NaN
551
- const farScreenSource = TmpVectors.Vector3[1].copyFromFloats(nearScreenSource.x, nearScreenSource.y, 1.0 - 1e-8);
552
- const nearVec3 = TmpVectors.Vector3[2];
553
- const farVec3 = TmpVectors.Vector3[3];
554
- Vector3._UnprojectFromInvertedMatrixToRef(nearScreenSource, matrix, nearVec3);
555
- Vector3._UnprojectFromInvertedMatrixToRef(farScreenSource, matrix, farVec3);
556
- this.origin.copyFrom(nearVec3);
557
- farVec3.subtractToRef(nearVec3, this.direction);
558
- this.direction.normalize();
559
- }
560
- }
561
- Ray._TmpVector3 = BuildArray(6, Vector3.Zero);
562
- Ray._RayDistant = Ray.Zero();
563
- Ray._Smallnum = 0.00000001;
564
- Ray._Rayl = 10e8;
565
- Scene.prototype.createPickingRay = function (x, y, world, camera, cameraViewSpace = false) {
566
- const result = Ray.Zero();
567
- this.createPickingRayToRef(x, y, world, result, camera, cameraViewSpace);
568
- return result;
569
- };
3
+ import { AddRayExtensions, CreatePickingRayInCameraSpace, CreatePickingRayInCameraSpaceToRef, CreatePickingRayToRef, MultiPick, MultiPickWithRay, Pick, PickWithBoundingInfo, PickWithRay, } from "./ray.core.js";
4
+ export * from "./ray.core.js";
5
+ // Picking
6
+ AddRayExtensions(Scene, Camera);
570
7
  Scene.prototype.createPickingRayToRef = function (x, y, world, result, camera, cameraViewSpace = false, enableDistantPicking = false) {
571
- const engine = this.getEngine();
572
- if (!camera && !(camera = this.activeCamera)) {
573
- return this;
574
- }
575
- const cameraViewport = camera.viewport;
576
- const renderHeight = engine.getRenderHeight();
577
- const { x: vx, y: vy, width, height } = cameraViewport.toGlobal(engine.getRenderWidth(), renderHeight);
578
- // Moving coordinates to local viewport world
579
- const levelInv = 1 / engine.getHardwareScalingLevel();
580
- x = x * levelInv - vx;
581
- y = y * levelInv - (renderHeight - vy - height);
582
- result.update(x, y, width, height, world ? world : Matrix.IdentityReadOnly, cameraViewSpace ? Matrix.IdentityReadOnly : camera.getViewMatrix(), camera.getProjectionMatrix(), enableDistantPicking);
583
- return this;
8
+ return CreatePickingRayToRef(this, x, y, world, result, camera, cameraViewSpace, enableDistantPicking);
584
9
  };
585
10
  Scene.prototype.createPickingRayInCameraSpace = function (x, y, camera) {
586
- const result = Ray.Zero();
587
- this.createPickingRayInCameraSpaceToRef(x, y, result, camera);
588
- return result;
11
+ return CreatePickingRayInCameraSpace(this, x, y, camera);
589
12
  };
590
13
  Scene.prototype.createPickingRayInCameraSpaceToRef = function (x, y, result, camera) {
591
- if (!PickingInfo) {
592
- return this;
593
- }
594
- const engine = this.getEngine();
595
- if (!camera && !(camera = this.activeCamera)) {
596
- throw new Error("Active camera not set");
597
- }
598
- const cameraViewport = camera.viewport;
599
- const renderHeight = engine.getRenderHeight();
600
- const { x: vx, y: vy, width, height } = cameraViewport.toGlobal(engine.getRenderWidth(), renderHeight);
601
- const identity = Matrix.Identity();
602
- // Moving coordinates to local viewport world
603
- const levelInv = 1 / engine.getHardwareScalingLevel();
604
- x = x * levelInv - vx;
605
- y = y * levelInv - (renderHeight - vy - height);
606
- result.update(x, y, width, height, identity, identity, camera.getProjectionMatrix());
607
- return this;
608
- };
609
- Scene.prototype._internalPickForMesh = function (pickingInfo, rayFunction, mesh, world, fastCheck, onlyBoundingInfo, trianglePredicate, skipBoundingInfo) {
610
- const ray = rayFunction(world, mesh.enableDistantPicking);
611
- const result = mesh.intersects(ray, fastCheck, trianglePredicate, onlyBoundingInfo, world, skipBoundingInfo);
612
- if (!result || !result.hit) {
613
- return null;
614
- }
615
- if (!fastCheck && pickingInfo != null && result.distance >= pickingInfo.distance) {
616
- return null;
617
- }
618
- return result;
619
- };
620
- Scene.prototype._internalPick = function (rayFunction, predicate, fastCheck, onlyBoundingInfo, trianglePredicate) {
621
- let pickingInfo = null;
622
- const computeWorldMatrixForCamera = !!(this.activeCameras && this.activeCameras.length > 1 && this.cameraToUseForPointers !== this.activeCamera);
623
- const currentCamera = this.cameraToUseForPointers || this.activeCamera;
624
- for (let meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
625
- const mesh = this.meshes[meshIndex];
626
- if (predicate) {
627
- if (!predicate(mesh, -1)) {
628
- continue;
629
- }
630
- }
631
- else if (!mesh.isEnabled() || !mesh.isVisible || !mesh.isPickable) {
632
- continue;
633
- }
634
- const forceCompute = computeWorldMatrixForCamera && mesh.isWorldMatrixCameraDependent();
635
- const world = mesh.computeWorldMatrix(forceCompute, currentCamera);
636
- if (mesh.hasThinInstances && mesh.thinInstanceEnablePicking) {
637
- // first check if the ray intersects the whole bounding box/sphere of the mesh
638
- const result = this._internalPickForMesh(pickingInfo, rayFunction, mesh, world, true, true, trianglePredicate);
639
- if (result) {
640
- if (onlyBoundingInfo) {
641
- // the user only asked for a bounding info check so we can return
642
- return result;
643
- }
644
- const tmpMatrix = TmpVectors.Matrix[1];
645
- const thinMatrices = mesh.thinInstanceGetWorldMatrices();
646
- for (let index = 0; index < thinMatrices.length; index++) {
647
- if (predicate && !predicate(mesh, index)) {
648
- continue;
649
- }
650
- const thinMatrix = thinMatrices[index];
651
- thinMatrix.multiplyToRef(world, tmpMatrix);
652
- const result = this._internalPickForMesh(pickingInfo, rayFunction, mesh, tmpMatrix, fastCheck, onlyBoundingInfo, trianglePredicate, true);
653
- if (result) {
654
- pickingInfo = result;
655
- pickingInfo.thinInstanceIndex = index;
656
- if (fastCheck) {
657
- return pickingInfo;
658
- }
659
- }
660
- }
661
- }
662
- }
663
- else {
664
- const result = this._internalPickForMesh(pickingInfo, rayFunction, mesh, world, fastCheck, onlyBoundingInfo, trianglePredicate);
665
- if (result) {
666
- pickingInfo = result;
667
- if (fastCheck) {
668
- return pickingInfo;
669
- }
670
- }
671
- }
672
- }
673
- return pickingInfo || new PickingInfo();
674
- };
675
- Scene.prototype._internalMultiPick = function (rayFunction, predicate, trianglePredicate) {
676
- if (!PickingInfo) {
677
- return null;
678
- }
679
- const pickingInfos = [];
680
- const computeWorldMatrixForCamera = !!(this.activeCameras && this.activeCameras.length > 1 && this.cameraToUseForPointers !== this.activeCamera);
681
- const currentCamera = this.cameraToUseForPointers || this.activeCamera;
682
- for (let meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
683
- const mesh = this.meshes[meshIndex];
684
- if (predicate) {
685
- if (!predicate(mesh, -1)) {
686
- continue;
687
- }
688
- }
689
- else if (!mesh.isEnabled() || !mesh.isVisible || !mesh.isPickable) {
690
- continue;
691
- }
692
- const forceCompute = computeWorldMatrixForCamera && mesh.isWorldMatrixCameraDependent();
693
- const world = mesh.computeWorldMatrix(forceCompute, currentCamera);
694
- if (mesh.hasThinInstances && mesh.thinInstanceEnablePicking) {
695
- const result = this._internalPickForMesh(null, rayFunction, mesh, world, true, true, trianglePredicate);
696
- if (result) {
697
- const tmpMatrix = TmpVectors.Matrix[1];
698
- const thinMatrices = mesh.thinInstanceGetWorldMatrices();
699
- for (let index = 0; index < thinMatrices.length; index++) {
700
- if (predicate && !predicate(mesh, index)) {
701
- continue;
702
- }
703
- const thinMatrix = thinMatrices[index];
704
- thinMatrix.multiplyToRef(world, tmpMatrix);
705
- const result = this._internalPickForMesh(null, rayFunction, mesh, tmpMatrix, false, false, trianglePredicate, true);
706
- if (result) {
707
- result.thinInstanceIndex = index;
708
- pickingInfos.push(result);
709
- }
710
- }
711
- }
712
- }
713
- else {
714
- const result = this._internalPickForMesh(null, rayFunction, mesh, world, false, false, trianglePredicate);
715
- if (result) {
716
- pickingInfos.push(result);
717
- }
718
- }
719
- }
720
- return pickingInfos;
14
+ return CreatePickingRayInCameraSpaceToRef(this, x, y, result, camera);
721
15
  };
722
16
  Scene.prototype.pickWithBoundingInfo = function (x, y, predicate, fastCheck, camera) {
723
- if (!PickingInfo) {
724
- return null;
725
- }
726
- const result = this._internalPick((world) => {
727
- if (!this._tempPickingRay) {
728
- this._tempPickingRay = Ray.Zero();
729
- }
730
- this.createPickingRayToRef(x, y, world, this._tempPickingRay, camera || null);
731
- return this._tempPickingRay;
732
- }, predicate, fastCheck, true);
733
- if (result) {
734
- result.ray = this.createPickingRay(x, y, Matrix.Identity(), camera || null);
735
- }
736
- return result;
17
+ return PickWithBoundingInfo(this, x, y, predicate, fastCheck, camera);
737
18
  };
738
- Object.defineProperty(Scene.prototype, "_pickingAvailable", {
739
- get: () => true,
740
- enumerable: false,
741
- configurable: false,
742
- });
743
19
  Scene.prototype.pick = function (x, y, predicate, fastCheck, camera, trianglePredicate, _enableDistantPicking = false) {
744
- const result = this._internalPick((world, enableDistantPicking) => {
745
- if (!this._tempPickingRay) {
746
- this._tempPickingRay = Ray.Zero();
747
- }
748
- this.createPickingRayToRef(x, y, world, this._tempPickingRay, camera || null, false, enableDistantPicking);
749
- return this._tempPickingRay;
750
- }, predicate, fastCheck, false, trianglePredicate);
751
- if (result) {
752
- result.ray = this.createPickingRay(x, y, Matrix.Identity(), camera || null);
753
- }
754
- return result;
20
+ return Pick(this, x, y, predicate, fastCheck, camera, trianglePredicate, _enableDistantPicking);
755
21
  };
756
22
  Scene.prototype.pickWithRay = function (ray, predicate, fastCheck, trianglePredicate) {
757
- const result = this._internalPick((world) => {
758
- if (!this._pickWithRayInverseMatrix) {
759
- this._pickWithRayInverseMatrix = Matrix.Identity();
760
- }
761
- world.invertToRef(this._pickWithRayInverseMatrix);
762
- if (!this._cachedRayForTransform) {
763
- this._cachedRayForTransform = Ray.Zero();
764
- }
765
- Ray.TransformToRef(ray, this._pickWithRayInverseMatrix, this._cachedRayForTransform);
766
- return this._cachedRayForTransform;
767
- }, predicate, fastCheck, false, trianglePredicate);
768
- if (result) {
769
- result.ray = ray;
770
- }
771
- return result;
23
+ return PickWithRay(this, ray, predicate, fastCheck, trianglePredicate);
772
24
  };
773
25
  Scene.prototype.multiPick = function (x, y, predicate, camera, trianglePredicate) {
774
- return this._internalMultiPick((world) => this.createPickingRay(x, y, world, camera || null), predicate, trianglePredicate);
26
+ return MultiPick(this, x, y, predicate, camera, trianglePredicate);
775
27
  };
776
28
  Scene.prototype.multiPickWithRay = function (ray, predicate, trianglePredicate) {
777
- return this._internalMultiPick((world) => {
778
- if (!this._pickWithRayInverseMatrix) {
779
- this._pickWithRayInverseMatrix = Matrix.Identity();
780
- }
781
- world.invertToRef(this._pickWithRayInverseMatrix);
782
- if (!this._cachedRayForTransform) {
783
- this._cachedRayForTransform = Ray.Zero();
784
- }
785
- Ray.TransformToRef(ray, this._pickWithRayInverseMatrix, this._cachedRayForTransform);
786
- return this._cachedRayForTransform;
787
- }, predicate, trianglePredicate);
788
- };
789
- Camera.prototype.getForwardRay = function (length = 100, transform, origin) {
790
- return this.getForwardRayToRef(new Ray(Vector3.Zero(), Vector3.Zero(), length), length, transform, origin);
791
- };
792
- Camera.prototype.getForwardRayToRef = function (refRay, length = 100, transform, origin) {
793
- if (!transform) {
794
- transform = this.getWorldMatrix();
795
- }
796
- refRay.length = length;
797
- if (origin) {
798
- refRay.origin.copyFrom(origin);
799
- }
800
- else {
801
- refRay.origin.copyFrom(this.position);
802
- }
803
- const forward = TmpVectors.Vector3[2];
804
- forward.set(0, 0, this._scene.useRightHandedSystem ? -1 : 1);
805
- const worldForward = TmpVectors.Vector3[3];
806
- Vector3.TransformNormalToRef(forward, transform, worldForward);
807
- Vector3.NormalizeToRef(worldForward, refRay.direction);
808
- return refRay;
29
+ return MultiPickWithRay(this, ray, predicate, trianglePredicate);
809
30
  };
810
31
  //# sourceMappingURL=ray.js.map