@onerjs/core 8.28.0 → 8.28.2

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 (109) hide show
  1. package/Behaviors/Meshes/handConstraintBehavior.js.map +1 -1
  2. package/Collisions/gpuPicker.d.ts +40 -16
  3. package/Collisions/gpuPicker.js +216 -95
  4. package/Collisions/gpuPicker.js.map +1 -1
  5. package/Decorators/nodeDecorator.d.ts +5 -1
  6. package/Decorators/nodeDecorator.js +4 -0
  7. package/Decorators/nodeDecorator.js.map +1 -1
  8. package/Engines/abstractEngine.js +2 -2
  9. package/Engines/abstractEngine.js.map +1 -1
  10. package/FrameGraph/Node/Blocks/PostProcesses/colorCorrectionPostProcessBlock.d.ts +30 -0
  11. package/FrameGraph/Node/Blocks/PostProcesses/colorCorrectionPostProcessBlock.js +56 -0
  12. package/FrameGraph/Node/Blocks/PostProcesses/colorCorrectionPostProcessBlock.js.map +1 -0
  13. package/FrameGraph/Node/Blocks/PostProcesses/filterPostProcessBlock.d.ts +32 -0
  14. package/FrameGraph/Node/Blocks/PostProcesses/filterPostProcessBlock.js +62 -0
  15. package/FrameGraph/Node/Blocks/PostProcesses/filterPostProcessBlock.js.map +1 -0
  16. package/FrameGraph/Node/Blocks/PostProcesses/tonemapPostProcessBlock.d.ts +36 -0
  17. package/FrameGraph/Node/Blocks/PostProcesses/tonemapPostProcessBlock.js +88 -0
  18. package/FrameGraph/Node/Blocks/PostProcesses/tonemapPostProcessBlock.js.map +1 -0
  19. package/FrameGraph/Node/Blocks/index.d.ts +3 -0
  20. package/FrameGraph/Node/Blocks/index.js +3 -0
  21. package/FrameGraph/Node/Blocks/index.js.map +1 -1
  22. package/FrameGraph/Tasks/PostProcesses/colorCorrectionTask.d.ts +17 -0
  23. package/FrameGraph/Tasks/PostProcesses/colorCorrectionTask.js +18 -0
  24. package/FrameGraph/Tasks/PostProcesses/colorCorrectionTask.js.map +1 -0
  25. package/FrameGraph/Tasks/PostProcesses/filterTask.d.ts +16 -0
  26. package/FrameGraph/Tasks/PostProcesses/filterTask.js +17 -0
  27. package/FrameGraph/Tasks/PostProcesses/filterTask.js.map +1 -0
  28. package/FrameGraph/Tasks/PostProcesses/tonemapTask.d.ts +16 -0
  29. package/FrameGraph/Tasks/PostProcesses/tonemapTask.js +17 -0
  30. package/FrameGraph/Tasks/PostProcesses/tonemapTask.js.map +1 -0
  31. package/FrameGraph/index.d.ts +3 -0
  32. package/FrameGraph/index.js +3 -0
  33. package/FrameGraph/index.js.map +1 -1
  34. package/Materials/Textures/texture.js +9 -2
  35. package/Materials/Textures/texture.js.map +1 -1
  36. package/Materials/effect.d.ts +1 -0
  37. package/Materials/effect.js +7 -1
  38. package/Materials/effect.js.map +1 -1
  39. package/Particles/gpuParticleSystem.js +2 -1
  40. package/Particles/gpuParticleSystem.js.map +1 -1
  41. package/Particles/thinParticleSystem.js +4 -3
  42. package/Particles/thinParticleSystem.js.map +1 -1
  43. package/Physics/v2/physicsAggregate.js +4 -3
  44. package/Physics/v2/physicsAggregate.js.map +1 -1
  45. package/PostProcesses/colorCorrectionPostProcess.d.ts +3 -3
  46. package/PostProcesses/colorCorrectionPostProcess.js +21 -21
  47. package/PostProcesses/colorCorrectionPostProcess.js.map +1 -1
  48. package/PostProcesses/filterPostProcess.d.ts +4 -2
  49. package/PostProcesses/filterPostProcess.js +22 -15
  50. package/PostProcesses/filterPostProcess.js.map +1 -1
  51. package/PostProcesses/index.d.ts +3 -0
  52. package/PostProcesses/index.js +3 -0
  53. package/PostProcesses/index.js.map +1 -1
  54. package/PostProcesses/thinColorCorrectionPostProcess.d.ts +30 -0
  55. package/PostProcesses/thinColorCorrectionPostProcess.js +52 -0
  56. package/PostProcesses/thinColorCorrectionPostProcess.js.map +1 -0
  57. package/PostProcesses/thinFilterPostProcess.d.ts +29 -0
  58. package/PostProcesses/thinFilterPostProcess.js +51 -0
  59. package/PostProcesses/thinFilterPostProcess.js.map +1 -0
  60. package/PostProcesses/thinTonemapPostProcess.d.ts +52 -0
  61. package/PostProcesses/thinTonemapPostProcess.js +83 -0
  62. package/PostProcesses/thinTonemapPostProcess.js.map +1 -0
  63. package/PostProcesses/tonemapPostProcess.d.ts +23 -21
  64. package/PostProcesses/tonemapPostProcess.js +55 -46
  65. package/PostProcesses/tonemapPostProcess.js.map +1 -1
  66. package/Rendering/geometryBufferRenderer.js +6 -1
  67. package/Rendering/geometryBufferRenderer.js.map +1 -1
  68. package/Shaders/geometry.fragment.js +3 -1
  69. package/Shaders/geometry.fragment.js.map +1 -1
  70. package/Shaders/geometry.vertex.js +10 -2
  71. package/Shaders/geometry.vertex.js.map +1 -1
  72. package/Shaders/picking.fragment.js +20 -6
  73. package/Shaders/picking.fragment.js.map +1 -1
  74. package/Shaders/picking.vertex.js +4 -3
  75. package/Shaders/picking.vertex.js.map +1 -1
  76. package/ShadersWGSL/geometry.fragment.js +3 -1
  77. package/ShadersWGSL/geometry.fragment.js.map +1 -1
  78. package/ShadersWGSL/geometry.vertex.js +10 -2
  79. package/ShadersWGSL/geometry.vertex.js.map +1 -1
  80. package/ShadersWGSL/picking.fragment.js +11 -6
  81. package/ShadersWGSL/picking.fragment.js.map +1 -1
  82. package/ShadersWGSL/picking.vertex.js +4 -3
  83. package/ShadersWGSL/picking.vertex.js.map +1 -1
  84. package/XR/features/WebXRAnchorSystem.d.ts +1 -1
  85. package/XR/features/WebXRBackgroundRemover.d.ts +1 -1
  86. package/XR/features/WebXRControllerMovement.d.ts +1 -1
  87. package/XR/features/WebXRControllerPhysics.d.ts +1 -1
  88. package/XR/features/WebXRControllerPointerSelection.d.ts +1 -1
  89. package/XR/features/WebXRControllerTeleportation.d.ts +1 -1
  90. package/XR/features/WebXRDOMOverlay.d.ts +1 -1
  91. package/XR/features/WebXRDepthSensing.d.ts +1 -1
  92. package/XR/features/WebXREyeTracking.d.ts +1 -1
  93. package/XR/features/WebXRFeaturePointSystem.d.ts +1 -1
  94. package/XR/features/WebXRHandTracking.d.ts +1 -1
  95. package/XR/features/WebXRHitTest.d.ts +1 -1
  96. package/XR/features/WebXRHitTestLegacy.d.ts +1 -1
  97. package/XR/features/WebXRImageTracking.d.ts +1 -1
  98. package/XR/features/WebXRLayers.d.ts +1 -1
  99. package/XR/features/WebXRLightEstimation.d.ts +1 -1
  100. package/XR/features/WebXRMeshDetector.d.ts +1 -1
  101. package/XR/features/WebXRNearInteraction.d.ts +1 -1
  102. package/XR/features/WebXRPlaneDetector.d.ts +1 -1
  103. package/XR/features/WebXRRawCameraAccess.d.ts +1 -1
  104. package/XR/features/WebXRSpaceWarp.d.ts +1 -1
  105. package/XR/webXRDefaultExperience.js +1 -1
  106. package/XR/webXRDefaultExperience.js.map +1 -1
  107. package/XR/webXRFeaturesManager.d.ts +116 -27
  108. package/XR/webXRFeaturesManager.js.map +1 -1
  109. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
 
2
2
  import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture.js";
3
3
  import { ShaderMaterial } from "../Materials/shaderMaterial.js";
4
- import { Color3, Color4 } from "../Maths/math.color.js";
4
+ import { Color4 } from "../Maths/math.color.js";
5
5
  import { VertexBuffer } from "../Meshes/buffer.js";
6
6
  import { Logger } from "../Misc/logger.js";
7
7
  /**
@@ -13,14 +13,20 @@ export class GPUPicker {
13
13
  this._pickingTexture = null;
14
14
  this._idMap = [];
15
15
  this._thinIdMap = [];
16
- this._idColors = [];
16
+ this._meshUniqueIdToPickerId = [];
17
+ this._idWarningIssued = false;
18
+ this._cachedScene = null;
19
+ this._engine = null;
20
+ this._pickingMaterialCache = new Array(9).fill(null);
21
+ this._pickableMeshes = [];
17
22
  this._meshMaterialMap = new Map();
23
+ this._readbuffer = null;
18
24
  this._meshRenderingCount = 0;
19
- this._attributeName = "instanceMeshID";
20
- this._warningIssued = false;
25
+ this._renderWarningIssued = false;
21
26
  this._renderPickingTexture = false;
22
27
  this._sceneBeforeRenderObserver = null;
23
- this._pickingTextureAfterRenderObservable = null;
28
+ this._pickingTextureAfterRenderObserver = null;
29
+ this._nextFreeId = 1;
24
30
  /** Shader language used by the generator */
25
31
  this._shaderLanguage = 0 /* ShaderLanguage.GLSL */;
26
32
  this._pickingInProgress = false;
@@ -38,15 +44,12 @@ export class GPUPicker {
38
44
  return this._pickingInProgress;
39
45
  }
40
46
  /**
41
- * Gets the default render material used by the picker.
47
+ * Gets the default render materials used by the picker.
48
+ *
49
+ * index is Material filling mode
42
50
  */
43
- get defaultRenderMaterial() {
44
- return this._defaultRenderMaterial;
45
- }
46
- static _IdToRgb(id) {
47
- GPUPicker._TempColor.r = (id & 0xff0000) >> 16;
48
- GPUPicker._TempColor.g = (id & 0x00ff00) >> 8;
49
- GPUPicker._TempColor.b = (id & 0x0000ff) >> 0;
51
+ get defaultRenderMaterials() {
52
+ return this._pickingMaterialCache;
50
53
  }
51
54
  _getColorIdFromReadBuffer(offset) {
52
55
  const r = this._readbuffer[offset];
@@ -54,12 +57,6 @@ export class GPUPicker {
54
57
  const b = this._readbuffer[offset + 2];
55
58
  return (r << 16) + (g << 8) + b;
56
59
  }
57
- static _SetColorData(buffer, i, r, g, b) {
58
- buffer[i] = r / 255.0;
59
- buffer[i + 1] = g / 255.0;
60
- buffer[i + 2] = b / 255.0;
61
- buffer[i + 3] = 1.0;
62
- }
63
60
  _createRenderTarget(scene, width, height) {
64
61
  if (this._cachedScene && this._pickingTexture) {
65
62
  const index = this._cachedScene.customRenderTargets.indexOf(this._pickingTexture);
@@ -71,21 +68,36 @@ export class GPUPicker {
71
68
  if (this._pickingTexture) {
72
69
  this._pickingTexture.dispose();
73
70
  }
74
- this._pickingTexture = new RenderTargetTexture("pickingTexure", { width: width, height: height }, scene, false, undefined, 0, false, 1);
71
+ this._pickingTexture = new RenderTargetTexture("pickingTexure", { width: width, height: height }, scene, {
72
+ generateMipMaps: false,
73
+ type: 0,
74
+ samplingMode: 1,
75
+ });
76
+ }
77
+ _clearPickingMaterials() {
78
+ for (let i = 0; i < this._pickingMaterialCache.length; i++) {
79
+ const material = this._pickingMaterialCache[i];
80
+ if (material !== null) {
81
+ material.dispose();
82
+ this._pickingMaterialCache[i] = null;
83
+ }
84
+ }
75
85
  }
76
- // eslint-disable-next-line @typescript-eslint/require-await
77
- async _createColorMaterialAsync(scene) {
78
- if (this._defaultRenderMaterial) {
79
- this._defaultRenderMaterial.dispose();
86
+ _getPickingMaterial(scene, fillMode) {
87
+ if (fillMode < 0 || 8 < fillMode) {
88
+ fillMode = 0;
89
+ }
90
+ const cachedMaterial = this._pickingMaterialCache[fillMode];
91
+ if (cachedMaterial) {
92
+ return cachedMaterial;
80
93
  }
81
- this._defaultRenderMaterial = null;
82
94
  const engine = scene.getEngine();
83
95
  if (engine.isWebGPU) {
84
96
  this._shaderLanguage = 1 /* ShaderLanguage.WGSL */;
85
97
  }
86
98
  const defines = [];
87
99
  const options = {
88
- attributes: [VertexBuffer.PositionKind, this._attributeName, "bakedVertexAnimationSettingsInstanced"],
100
+ attributes: [VertexBuffer.PositionKind, GPUPicker._AttributeName],
89
101
  uniforms: ["world", "viewProjection", "meshID"],
90
102
  needAlphaBlending: false,
91
103
  defines: defines,
@@ -100,8 +112,11 @@ export class GPUPicker {
100
112
  }
101
113
  },
102
114
  };
103
- this._defaultRenderMaterial = new ShaderMaterial("pickingShader", scene, "picking", options, false);
104
- this._defaultRenderMaterial.onBindObservable.add(this._materialBindCallback, undefined, undefined, this);
115
+ const newMaterial = new ShaderMaterial("pickingShader", scene, "picking", options, false);
116
+ newMaterial.fillMode = fillMode;
117
+ newMaterial.onBindObservable.add(this._materialBindCallback, undefined, undefined, this);
118
+ this._pickingMaterialCache[fillMode] = newMaterial;
119
+ return newMaterial;
105
120
  }
106
121
  _materialBindCallback(mesh) {
107
122
  if (!mesh) {
@@ -109,39 +124,18 @@ export class GPUPicker {
109
124
  }
110
125
  const material = this._meshMaterialMap.get(mesh);
111
126
  if (!material) {
112
- if (!this._warningIssued) {
113
- this._warningIssued = true;
127
+ if (!this._renderWarningIssued) {
128
+ this._renderWarningIssued = true;
114
129
  Logger.Warn("GPUPicker issue: Mesh not found in the material map. This may happen when the root mesh of an instance is not in the picking list.");
115
130
  }
116
131
  return;
117
132
  }
118
133
  const effect = material.getEffect();
119
- if (!mesh.hasInstances && !mesh.isAnInstance && !mesh.hasThinInstances && this._idColors[mesh.uniqueId] !== undefined) {
120
- effect.setColor4("meshID", this._idColors[mesh.uniqueId], 1);
134
+ if (!mesh.hasInstances && !mesh.isAnInstance && !mesh.hasThinInstances && this._meshUniqueIdToPickerId[mesh.uniqueId] !== undefined) {
135
+ effect.setFloat("meshID", this._meshUniqueIdToPickerId[mesh.uniqueId]);
121
136
  }
122
137
  this._meshRenderingCount++;
123
138
  }
124
- _generateColorData(instanceCount, id, r, g, b, onInstance) {
125
- const colorData = new Float32Array(4 * (instanceCount + 1));
126
- GPUPicker._SetColorData(colorData, 0, r, g, b);
127
- for (let i = 0; i < instanceCount; i++) {
128
- GPUPicker._IdToRgb(id);
129
- onInstance(i, id);
130
- GPUPicker._SetColorData(colorData, (i + 1) * 4, GPUPicker._TempColor.r, GPUPicker._TempColor.g, GPUPicker._TempColor.b);
131
- id++;
132
- }
133
- return colorData;
134
- }
135
- _generateThinInstanceColorData(instanceCount, id, onInstance) {
136
- const colorData = new Float32Array(4 * instanceCount);
137
- for (let i = 0; i < instanceCount; i++) {
138
- GPUPicker._IdToRgb(id);
139
- onInstance(i, id);
140
- GPUPicker._SetColorData(colorData, i * 4, GPUPicker._TempColor.r, GPUPicker._TempColor.g, GPUPicker._TempColor.b);
141
- id++;
142
- }
143
- return colorData;
144
- }
145
139
  /**
146
140
  * Set the list of meshes to pick from
147
141
  * Set that value to null to clear the list (and avoid leaks)
@@ -149,21 +143,37 @@ export class GPUPicker {
149
143
  * @param list defines the list of meshes to pick from
150
144
  */
151
145
  setPickingList(list) {
146
+ this.clearPickingList();
147
+ if (!list || list.length === 0) {
148
+ return;
149
+ }
150
+ this._pickableMeshes = list;
151
+ // Prepare target
152
+ const scene = ("mesh" in list[0] ? list[0].mesh : list[0]).getScene();
153
+ if (!this._cachedScene || this._cachedScene !== scene) {
154
+ this._clearPickingMaterials();
155
+ }
156
+ this.addPickingList(list);
157
+ }
158
+ /**
159
+ * Clear the current picking list and free resources
160
+ */
161
+ clearPickingList() {
152
162
  if (this._pickableMeshes) {
153
163
  // Cleanup
154
164
  for (let index = 0; index < this._pickableMeshes.length; index++) {
155
165
  const mesh = this._pickableMeshes[index];
156
166
  if (mesh.hasInstances) {
157
- mesh.removeVerticesData(this._attributeName);
167
+ mesh.removeVerticesData(GPUPicker._AttributeName);
158
168
  }
159
169
  if (mesh.hasThinInstances) {
160
- mesh.thinInstanceSetBuffer(this._attributeName, null);
170
+ mesh.thinInstanceSetBuffer(GPUPicker._AttributeName, null);
161
171
  }
162
172
  if (this._pickingTexture) {
163
173
  this._pickingTexture.setMaterialForRendering(mesh, undefined);
164
174
  }
165
175
  const material = this._meshMaterialMap.get(mesh);
166
- if (material !== this._defaultRenderMaterial) {
176
+ if (!this._pickingMaterialCache.includes(material)) {
167
177
  material.onBindObservable.removeCallback(this._materialBindCallback);
168
178
  }
169
179
  }
@@ -171,15 +181,21 @@ export class GPUPicker {
171
181
  this._meshMaterialMap.clear();
172
182
  this._idMap.length = 0;
173
183
  this._thinIdMap.length = 0;
174
- this._idColors.length = 0;
184
+ this._meshUniqueIdToPickerId.length = 0;
175
185
  if (this._pickingTexture) {
176
186
  this._pickingTexture.renderList = [];
177
187
  }
178
188
  }
189
+ this._nextFreeId = 1;
190
+ }
191
+ /**
192
+ * Add array of meshes to the current picking list
193
+ * @param list defines the array of meshes to add to the current picking list
194
+ */
195
+ addPickingList(list) {
179
196
  if (!list || list.length === 0) {
180
197
  return;
181
198
  }
182
- this._pickableMeshes = list;
183
199
  // Prepare target
184
200
  const scene = ("mesh" in list[0] ? list[0].mesh : list[0]).getScene();
185
201
  const engine = scene.getEngine();
@@ -201,29 +217,39 @@ export class GPUPicker {
201
217
  this._cachedScene.activeCamera = null;
202
218
  }
203
219
  });
204
- if (!this._cachedScene || this._cachedScene !== scene) {
205
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
206
- this._createColorMaterialAsync(scene);
220
+ this._cachedScene = scene;
221
+ this._engine = scene.getEngine();
222
+ if (!this._pickingTexture.renderList) {
223
+ this._pickingTexture.renderList = [];
207
224
  }
225
+ const newPickableMeshes = new Array(list.length);
226
+ const pickableMeshOffset = this._pickableMeshes?.length ?? 0;
208
227
  this._cachedScene = scene;
209
228
  this._engine = scene.getEngine();
210
229
  for (let i = 0; i < list.length; i++) {
211
230
  const item = list[i];
212
231
  if ("mesh" in item) {
213
232
  this._meshMaterialMap.set(item.mesh, item.material);
214
- list[i] = item.mesh;
233
+ newPickableMeshes[i] = item.mesh;
215
234
  }
216
235
  else {
217
- this._meshMaterialMap.set(item, this._defaultRenderMaterial);
236
+ const material = this._getPickingMaterial(scene, item.material?.fillMode ?? 0);
237
+ this._meshMaterialMap.set(item, material);
238
+ newPickableMeshes[i] = item;
218
239
  }
219
240
  }
220
- this._pickingTexture.renderList = [];
241
+ if (this._pickableMeshes !== null) {
242
+ this._pickableMeshes = [...this._pickableMeshes, ...newPickableMeshes];
243
+ }
244
+ else {
245
+ this._pickableMeshes = newPickableMeshes;
246
+ }
221
247
  // We will affect colors and create vertex color buffers
222
- let id = 1;
223
- for (let index = 0; index < this._pickableMeshes.length; index++) {
224
- const mesh = this._pickableMeshes[index];
248
+ let nextFreeid = this._nextFreeId;
249
+ for (let index = 0; index < newPickableMeshes.length; index++) {
250
+ const mesh = newPickableMeshes[index];
225
251
  const material = this._meshMaterialMap.get(mesh);
226
- if (material !== this._defaultRenderMaterial) {
252
+ if (!this._pickingMaterialCache.includes(material)) {
227
253
  material.onBindObservable.add(this._materialBindCallback, undefined, undefined, this);
228
254
  }
229
255
  this._pickingTexture.setMaterialForRendering(mesh, material);
@@ -231,33 +257,54 @@ export class GPUPicker {
231
257
  if (mesh.isAnInstance) {
232
258
  continue; // This will be handled by the source mesh
233
259
  }
234
- GPUPicker._IdToRgb(id);
260
+ const globalIndex = index + pickableMeshOffset;
235
261
  if (mesh.hasThinInstances) {
236
- const colorData = this._generateThinInstanceColorData(mesh.thinInstanceCount, id, (i, id) => {
237
- this._thinIdMap[id] = { meshId: index, thinId: i };
238
- });
239
- id += mesh.thinInstanceCount;
240
- mesh.thinInstanceSetBuffer(this._attributeName, colorData, 4);
262
+ const thinInstanceCount = mesh.thinInstanceCount;
263
+ const instanceIdData = new Float32Array(thinInstanceCount);
264
+ for (let i = 0; i < thinInstanceCount; i++) {
265
+ instanceIdData[i] = nextFreeid;
266
+ this._thinIdMap[nextFreeid] = { meshId: globalIndex, thinId: i };
267
+ nextFreeid++;
268
+ }
269
+ mesh.thinInstanceSetBuffer(GPUPicker._AttributeName, instanceIdData, 1);
241
270
  }
242
271
  else {
243
- this._idMap[id] = index;
244
- id++;
272
+ const currentMeshId = nextFreeid;
273
+ this._idMap[currentMeshId] = globalIndex;
274
+ nextFreeid++;
245
275
  if (mesh.hasInstances) {
246
- const instancesForPick = this._pickableMeshes.filter((m) => m.isAnInstance && m.sourceMesh === mesh);
247
- const colorData = this._generateColorData(instancesForPick.length, id, GPUPicker._TempColor.r, GPUPicker._TempColor.g, GPUPicker._TempColor.b, (i, id) => {
248
- const instance = instancesForPick[i];
249
- this._idMap[id] = this._pickableMeshes.indexOf(instance);
250
- });
251
- id += instancesForPick.length;
276
+ // find index of instances of that mesh
277
+ const instancesForPick = [];
278
+ for (let pickableMeshIndex = 0; pickableMeshIndex < newPickableMeshes.length; ++pickableMeshIndex) {
279
+ const m = newPickableMeshes[pickableMeshIndex];
280
+ if (m.isAnInstance && m.sourceMesh === mesh) {
281
+ instancesForPick.push(pickableMeshIndex);
282
+ }
283
+ }
284
+ const instanceIdData = new Float32Array(instancesForPick.length + 1); // +1 for the source mesh
285
+ instanceIdData[0] = currentMeshId;
286
+ for (let i = 0; i < instancesForPick.length; i++) {
287
+ instanceIdData[i + 1] = nextFreeid;
288
+ const globalInstanceIndex = instancesForPick[i] + pickableMeshOffset;
289
+ this._idMap[nextFreeid] = globalInstanceIndex;
290
+ nextFreeid++;
291
+ }
252
292
  const engine = mesh.getEngine();
253
- const buffer = new VertexBuffer(engine, colorData, this._attributeName, false, false, 4, true);
293
+ const buffer = new VertexBuffer(engine, instanceIdData, GPUPicker._AttributeName, false, false, 1, true);
254
294
  mesh.setVerticesBuffer(buffer, true);
255
295
  }
256
296
  else {
257
- this._idColors[mesh.uniqueId] = Color3.FromInts(GPUPicker._TempColor.r, GPUPicker._TempColor.g, GPUPicker._TempColor.b);
297
+ this._meshUniqueIdToPickerId[mesh.uniqueId] = currentMeshId;
258
298
  }
259
299
  }
260
300
  }
301
+ if (GPUPicker._MaxPickingId < nextFreeid - 1) {
302
+ if (!this._idWarningIssued) {
303
+ this._idWarningIssued = true;
304
+ Logger.Warn(`GPUPicker maximum number of pickable meshes and instances is ${GPUPicker._MaxPickingId}. Some meshes or instances won't be pickable.`);
305
+ }
306
+ }
307
+ this._nextFreeId = nextFreeid;
261
308
  }
262
309
  /**
263
310
  * Execute a picking operation
@@ -332,6 +379,40 @@ export class GPUPicker {
332
379
  this._preparePickingBuffer(this._engine, rttSizeW, rttSizeH, minX, partialCutH, w, h);
333
380
  return await this._executeMultiPickingAsync(processedXY, minX, maxY, rttSizeH, w, h, disposeWhenDone);
334
381
  }
382
+ /**
383
+ * Execute a picking operation on box defined by two screen coordinates
384
+ * @param x1 defines the X coordinate of the first corner of the box where to run the pick
385
+ * @param y1 defines the Y coordinate of the first corner of the box where to run the pick
386
+ * @param x2 defines the X coordinate of the opposite corner of the box where to run the pick
387
+ * @param y2 defines the Y coordinate of the opposite corner of the box where to run the pick
388
+ * @param disposeWhenDone defines a boolean indicating we do not want to keep resources alive (false by default)
389
+ * @returns A promise with the picking results. Always returns an array with the same length as the number of coordinates. The mesh or null at the index where no mesh was picked.
390
+ */
391
+ async boxPickAsync(x1, y1, x2, y2, disposeWhenDone = false) {
392
+ if (this._pickingInProgress) {
393
+ return null;
394
+ }
395
+ if (!this._pickableMeshes || this._pickableMeshes.length === 0) {
396
+ return null;
397
+ }
398
+ this._pickingInProgress = true;
399
+ const { rttSizeW, rttSizeH, devicePixelRatio } = this._getRenderInfo();
400
+ const { x: adjustedX1, y: adjustedY1 } = this._prepareForPicking(x1, y1, devicePixelRatio);
401
+ const { x: adjustedX2, y: adjustedY2 } = this._prepareForPicking(x2, y2, devicePixelRatio);
402
+ const minX = Math.max(Math.min(adjustedX1, adjustedX2), 0);
403
+ const maxX = Math.min(Math.max(adjustedX1, adjustedX2), rttSizeW - 1);
404
+ const minY = Math.max(Math.min(adjustedY1, adjustedY2), 0);
405
+ const maxY = Math.min(Math.max(adjustedY1, adjustedY2), rttSizeH - 1);
406
+ if (minX >= rttSizeW || minY >= rttSizeH || maxX < 0 || maxY < 0) {
407
+ this._pickingInProgress = false;
408
+ return null;
409
+ }
410
+ const w = Math.max(maxX - minX, 1);
411
+ const h = Math.max(maxY - minY, 1);
412
+ const partialCutH = rttSizeH - maxY - 1;
413
+ this._preparePickingBuffer(this._engine, rttSizeW, rttSizeH, minX, partialCutH, w, h);
414
+ return await this._executeBoxPickingAsync(minX, partialCutH, w, h, disposeWhenDone);
415
+ }
335
416
  _getRenderInfo() {
336
417
  const engine = this._cachedScene.getEngine();
337
418
  const rttSizeW = engine.getRenderWidth();
@@ -362,8 +443,8 @@ export class GPUPicker {
362
443
  this._pickingTexture.onBeforeRender = () => {
363
444
  this._enableScissor(x, y, w, h);
364
445
  };
365
- this._pickingTextureAfterRenderObservable?.remove();
366
- this._pickingTextureAfterRenderObservable = this._pickingTexture.onAfterRenderObservable.add(() => {
446
+ this._pickingTextureAfterRenderObserver?.remove();
447
+ this._pickingTextureAfterRenderObserver = this._pickingTexture.onAfterRenderObservable.add(() => {
367
448
  this._disableScissor();
368
449
  });
369
450
  this._cachedScene.customRenderTargets.push(this._pickingTexture);
@@ -445,6 +526,50 @@ export class GPUPicker {
445
526
  };
446
527
  });
447
528
  }
529
+ // pick box area
530
+ async _executeBoxPickingAsync(x, y, w, h, disposeWhenDone) {
531
+ return await new Promise((resolve, reject) => {
532
+ if (!this._pickingTexture) {
533
+ this._pickingInProgress = false;
534
+ reject(new Error("Picking texture not created"));
535
+ return;
536
+ }
537
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
538
+ this._pickingTexture.onAfterRender = async () => {
539
+ if (this._checkRenderStatus()) {
540
+ this._pickingTexture.onAfterRender = null;
541
+ const pickedMeshes = [];
542
+ const thinInstanceIndexes = [];
543
+ if (await this._readTexturePixelsAsync(x, y, w, h)) {
544
+ for (let offsetY = 0; offsetY < h; ++offsetY) {
545
+ for (let offsetX = 0; offsetX < w; ++offsetX) {
546
+ const colorId = this._getColorIdFromReadBuffer((offsetY * w + offsetX) * 4);
547
+ if (colorId > 0) {
548
+ // Thin?
549
+ if (this._thinIdMap[colorId]) {
550
+ const pickedMesh = this._pickableMeshes[this._thinIdMap[colorId].meshId];
551
+ const thinInstanceIndex = this._thinIdMap[colorId].thinId;
552
+ pickedMeshes.push(pickedMesh);
553
+ thinInstanceIndexes.push(thinInstanceIndex);
554
+ }
555
+ else {
556
+ const pickedMesh = this._pickableMeshes[this._idMap[colorId]];
557
+ pickedMeshes.push(pickedMesh);
558
+ thinInstanceIndexes.push(0);
559
+ }
560
+ }
561
+ }
562
+ }
563
+ }
564
+ if (disposeWhenDone) {
565
+ this.dispose();
566
+ }
567
+ this._pickingInProgress = false;
568
+ resolve({ meshes: pickedMeshes, thinInstanceIndexes: thinInstanceIndexes });
569
+ }
570
+ };
571
+ });
572
+ }
448
573
  _enableScissor(x, y, w = 1, h = 1) {
449
574
  if (this._engine.enableScissor) {
450
575
  this._engine.enableScissor(x, y, w, h);
@@ -459,8 +584,8 @@ export class GPUPicker {
459
584
  * @returns true if rendering if the picking texture has finished, otherwise false
460
585
  */
461
586
  _checkRenderStatus() {
462
- const wasSuccessfull = this._meshRenderingCount > 0;
463
- if (wasSuccessfull) {
587
+ const wasSuccessful = this._meshRenderingCount > 0;
588
+ if (wasSuccessful) {
464
589
  // Remove from the active RTTs
465
590
  const index = this._cachedScene.customRenderTargets.indexOf(this._pickingTexture);
466
591
  if (index > -1) {
@@ -516,15 +641,11 @@ export class GPUPicker {
516
641
  // Cleaning up
517
642
  this._pickingTexture?.dispose();
518
643
  this._pickingTexture = null;
519
- this._defaultRenderMaterial?.dispose();
520
- this._defaultRenderMaterial = null;
644
+ this._clearPickingMaterials();
521
645
  this._sceneBeforeRenderObserver?.remove();
522
646
  this._sceneBeforeRenderObserver = null;
523
647
  }
524
648
  }
525
- GPUPicker._TempColor = {
526
- r: 0,
527
- g: 0,
528
- b: 0,
529
- };
649
+ GPUPicker._AttributeName = "instanceMeshID";
650
+ GPUPicker._MaxPickingId = 0x00ffffff; // 24 bits unsigned integer max
530
651
  //# sourceMappingURL=gpuPicker.js.map