@woosh/meep-engine 2.33.24 → 2.33.25

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 (74) hide show
  1. package/core/bvh2/binary/IndexedBinaryBVH.js +1 -1
  2. package/core/bvh2/traversal/ThreeClippingPlaneComputingBVHVisitor.js +5 -1
  3. package/core/bvh2/traversal/__detailed_box_volume_intersection.js +22 -5
  4. package/core/collection/array/binarySearchHighIndex.js +1 -1
  5. package/core/collection/array/copyArray.js +2 -2
  6. package/core/geom/3d/normal/hemioct/unit_hemioct.spec.js +1 -1
  7. package/core/geom/3d/shape/AbstractShape3D.js +9 -0
  8. package/core/geom/3d/shape/CompositeShape.js +188 -8
  9. package/core/geom/3d/shape/TransformedShape3D.js +58 -2
  10. package/core/geom/3d/shape/UnitCubeShape3D.js +11 -0
  11. package/core/geom/3d/shape/UnitSphereShape3D.js +8 -0
  12. package/core/geom/3d/shape/util/shape_to_visual_entity.js +159 -0
  13. package/core/geom/random/randomPointInSphere.js +3 -2
  14. package/core/json/resolvePathByArray.js +2 -2
  15. package/{engine/graphics/render/forward_plus/materials → core/primitives/strings}/insert_after.js +3 -0
  16. package/core/primitives/strings/insert_after_or_replace.js +27 -0
  17. package/editor/process/symbolic/makeHelperBoxGeometry.js +44 -0
  18. package/editor/view/ecs/EntityEditor.js +2 -2
  19. package/editor/view/ecs/components/particles/ParticleEmitterController.js +2 -2
  20. package/engine/EngineHarness.js +1 -0
  21. package/engine/animation/AnimationUtils.js +5 -5
  22. package/engine/ecs/EntityBuilder.js +25 -5
  23. package/engine/ecs/attachment/AttachmentBinding.js +8 -0
  24. package/engine/ecs/attachment/AttachmentSystem.js +4 -0
  25. package/engine/ecs/attachment/TransformAttachmentBinding.js +14 -44
  26. package/engine/ecs/components/Tag.js +27 -6
  27. package/engine/ecs/fow/FogOfWar.js +4 -0
  28. package/engine/ecs/fow/FogOfWarSystem.js +2 -0
  29. package/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +2 -0
  30. package/engine/ecs/system/AbstractContextSystem.js +1 -1
  31. package/engine/ecs/systems/TagSystem.js +17 -0
  32. package/engine/ecs/transform/Transform.js +19 -6
  33. package/engine/graphics/GraphicsEngine.js +11 -6
  34. package/engine/graphics/composit/CompositLayer.js +17 -4
  35. package/engine/graphics/composit/CompositingStages.js +8 -0
  36. package/engine/graphics/composit/LayerCompositer.js +35 -6
  37. package/engine/graphics/ecs/highlight/plugin/OutlineRenderPlugin.js +11 -7
  38. package/engine/graphics/ecs/light/Light.js +2 -0
  39. package/engine/graphics/ecs/light/binding/three/ThreeLightBinding.js +5 -1
  40. package/engine/graphics/ecs/mesh-v2/DrawMode.js +5 -0
  41. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +32 -18
  42. package/engine/graphics/particles/ParticleEmitterLibrary.js +3 -0
  43. package/engine/graphics/particles/ecs/{ParticleEmitterSystem2.js → ParticleEmitterSystem.js} +17 -9
  44. package/engine/graphics/particles/particular/engine/ParticularEngine.js +8 -2
  45. package/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +14 -25
  46. package/engine/graphics/particles/particular/engine/emitter/ParticleEmitterFlag.js +5 -0
  47. package/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +90 -2
  48. package/engine/graphics/particles/particular/engine/emitter/ParticlePool.spec.js +7 -7
  49. package/engine/graphics/particles/particular/engine/renderers/billboard/BILLBOARD_PARTICLE_SPECIFICATION.js +15 -12
  50. package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +262 -51
  51. package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +80 -46
  52. package/engine/graphics/particles/particular/engine/shader/debugAtlas.js +14 -0
  53. package/engine/graphics/particles/particular/engine/utils/volume/AttributeValue.js +141 -0
  54. package/engine/graphics/particles/particular/engine/utils/volume/ParticleVolume.js +148 -54
  55. package/engine/graphics/particles/particular/engine/utils/volume/lut_to_sampler.js +27 -0
  56. package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +542 -165
  57. package/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +12 -6
  58. package/engine/graphics/render/forward_plus/materials/FP_INJECTION_POINT_ACCUMULATION.js +1 -0
  59. package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +32 -0
  60. package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_DECODE_PARS.js +51 -0
  61. package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_PREAMBLE.js +25 -0
  62. package/engine/graphics/render/forward_plus/materials/fp_build_fragment_shader.js +31 -120
  63. package/engine/graphics/render/forward_plus/materials/fp_build_vertex_lighting_shared.js +35 -0
  64. package/engine/graphics/render/forward_plus/materials/fp_build_vertex_shader.js +4 -5
  65. package/engine/graphics/render/forward_plus/plugin/MaterialTransformer.js +10 -3
  66. package/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +588 -53
  67. package/engine/graphics/render/forward_plus/prototypeLightManager.js +29 -4
  68. package/engine/graphics/shaders/TerrainShader.js +4 -5
  69. package/engine/graphics/util/composeMatrix4.js +33 -23
  70. package/engine/graphics/util/decompose_matrix_4_array.js +61 -0
  71. package/engine/intelligence/behavior/ecs/BehaviorComponent.js +30 -14
  72. package/engine/knowledge/database/StaticKnowledgeDataTable.js +6 -1
  73. package/engine/navigation/ecs/components/Path.js +0 -5
  74. package/package.json +1 -1
@@ -344,7 +344,7 @@ function writeBox(array, address, x0, y0, z0, x1, y1, z1) {
344
344
  * @param {Float32Array} array
345
345
  */
346
346
  function copyBox(from, to, array) {
347
- array_copy(data, from, scratch_aabb_0, to, 6);
347
+ array_copy(array, from, array, to, 6);
348
348
  }
349
349
 
350
350
  /**
@@ -40,7 +40,11 @@ export class ThreeClippingPlaneComputingBVHVisitor extends BVHVisitor {
40
40
  */
41
41
  this.__nearPlaneConstant = 0;
42
42
 
43
-
43
+ /**
44
+ *
45
+ * @type {Float32Array}
46
+ * @private
47
+ */
44
48
  this.__planes_f32 = new Float32Array(24);
45
49
 
46
50
  this.near = 0;
@@ -7,37 +7,54 @@ import { __process_point_if_within_planes } from "./__process_point_if_within_pl
7
7
  import { plane_computeConvex3PlaneIntersection } from "../../geom/3d/plane/plane_computeConvex3PlaneIntersection.js";
8
8
  import { EPSILON } from "../../math/MathUtils.js";
9
9
 
10
+ /**
11
+ * Common piece of continuous memory for better cache coherence
12
+ * @type {ArrayBuffer}
13
+ * @private
14
+ */
15
+ const __scratch_buffer = new ArrayBuffer(
16
+ 24 * 4
17
+ + 24 * 4
18
+ + 8 * 4
19
+ + 3 * 4
20
+ );
21
+
10
22
  /**
11
23
  *
12
24
  * @type {number[]}
13
25
  */
14
- const scratch_aabb_corners = new Float32Array(24);
26
+ const scratch_aabb_corners = new Float32Array(__scratch_buffer, 0, 24);
15
27
 
16
28
  /**
17
29
  *
18
30
  * @type {number[]}
19
31
  */
20
- const scratch_aabb_planes = new Float32Array(24);
32
+ const scratch_aabb_planes = new Float32Array(__scratch_buffer, 96, 24);
21
33
 
22
34
  /**
23
35
  *
24
36
  * @type {number[]}
25
37
  */
26
- const scratch_corner_out_bitfields = new Uint32Array(8);
38
+ const scratch_corner_out_bitfields = new Uint32Array(__scratch_buffer, 192, 8);
27
39
 
28
40
  /**
29
41
  *
30
42
  * @type {number[]}
31
43
  */
32
- const scratch_v3_array = new Float32Array(3);
44
+ const scratch_v3_array = new Float32Array(__scratch_buffer, 224, 3);
33
45
 
34
46
  /**
47
+ * Figures out intersection volume between an AABB and a frustum for much tighter bounds
48
+ *
49
+ * Especially beneficial when trying to intersect a large AABB against a small frustum,
50
+ * where where traditionally only AABB corners would be considered,
51
+ * we're instead able to compute minimum bounds of the overlap of the two
35
52
  *
36
53
  * @param {AABB3} box
37
54
  * @param {number[]} planes
38
55
  * @param {number} plane_count
39
56
  * @param {number} plane_mask
40
- * @param {function} callback
57
+ * @param {function(x:number,y:number,z:number)} callback
41
58
  * @param {*} [thisArg]
42
59
  * @private
43
60
  */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @template T,V
3
- * @param {T[]} array
3
+ * @param {T[]|ArrayLike<T>|Float32Array} array
4
4
  * @param {V} el
5
5
  * @param {function(V,T):number} compareFunction
6
6
  * @param {number} [minIndex]
@@ -25,9 +25,9 @@ export function copyArray(source, target) {
25
25
  * Follows Java System.arraycopy interface
26
26
  * Copy data from one array to another
27
27
  * @template T
28
- * @param {T[]|ArrayLike<T>|TypedArray|Uint8ClampedArray|Uint8Array} source The source array
28
+ * @param {T[]|ArrayLike<T>|TypedArray|Uint8ClampedArray|Uint8Array|Float32Array|Float64Array} source The source array
29
29
  * @param {number} source_position Starting position where to copy from inside the source array
30
- * @param {T[]|ArrayLike<T>|TypedArray|Uint8ClampedArray|Uint8Array} destination The destination array
30
+ * @param {T[]|ArrayLike<T>|TypedArray|Uint8ClampedArray|Uint8Array|Float32Array|Float64Array} destination The destination array
31
31
  * @param {number} destination_position Starting position where to copy to inside the destination array
32
32
  * @param {number} length How many elements should be copied
33
33
  */
@@ -1,5 +1,5 @@
1
1
  import { decode_hemioct_to_unit, encode_unit_to_hemioct } from "./encode_unit3_hemioct.js";
2
- import { v3_length } from "../../../Vector3.d.ts";
2
+ import { v3_length } from "../../../v3_length.js";
3
3
 
4
4
  test('encode-decode', () => {
5
5
  const v0 = [];
@@ -12,6 +12,15 @@ export class AbstractShape3D {
12
12
  throw new Error('Not Implemented');
13
13
  }
14
14
 
15
+ /**
16
+ * Whether or not given point is inside the shape
17
+ * @param {number[]} point
18
+ * @returns {boolean}
19
+ */
20
+ contains_point(point) {
21
+ throw new Error('Not Implemented');
22
+ }
23
+
15
24
  /**
16
25
  * Total volume of the shape
17
26
  * @returns {number}
@@ -1,6 +1,20 @@
1
1
  import { AbstractShape3D } from "./AbstractShape3D.js";
2
- import { weightedRandomFromArray } from "../../../collection/array/weightedRandomFromArray.js";
2
+ import { seededRandom } from "../../../math/random/seededRandom.js";
3
+ import { binarySearchHighIndex } from "../../../collection/array/binarySearchHighIndex.js";
4
+ import { compareNumbers } from "../../../primitives/numbers/compareNumbers.js";
3
5
 
6
+ /**
7
+ * To avoid severe performance overhead, we limit number of possible rejections
8
+ * @type {number}
9
+ */
10
+ const SAMPLE_REJECTION_ATTEMPT_MAX = 4;
11
+
12
+ /**
13
+ * Number of samples taken to estimate overlap level
14
+ * @type {number}
15
+ */
16
+ const VOLUME_OVERLAP_ESTIMATION_TAPS = 1024;
17
+ const VOLUME_OVERLAP_ESTIMATION_SUB_TAPS = 4;
4
18
 
5
19
  const scratch_array = [];
6
20
 
@@ -13,7 +27,7 @@ function getVolume(shape) {
13
27
  return shape.volume;
14
28
  }
15
29
 
16
- export class CompositeShape extends AbstractShape3D {
30
+ export class CompositeShape3D extends AbstractShape3D {
17
31
  constructor() {
18
32
  super();
19
33
 
@@ -22,23 +36,126 @@ export class CompositeShape extends AbstractShape3D {
22
36
  * @type {AbstractShape3D[]}
23
37
  */
24
38
  this.children = [];
39
+
40
+ /**
41
+ * Estimator of how much volume is in overlap,
42
+ * expressed as fraction of volume occupied by overlapping region of 2 shapes over the sum of volume occupied by each child
43
+ * @type {number}
44
+ * @private
45
+ */
46
+ this.__volume_overlap_fraction = -1;
47
+
48
+ this.__volume_sum = -1;
49
+ this.__volume_sums = [];
50
+ this.__child_volumes = [];
51
+ }
52
+
53
+ __compute_volume_variables() {
54
+ this.__volume_sum = 0;
55
+
56
+ const children = this.children;
57
+ const child_count = children.length;
58
+
59
+ const child_volumes = this.__child_volumes = new Float32Array(child_count);
60
+ const child_volume_sums = this.__volume_sums = new Float32Array(child_count);
61
+
62
+ for (let i = 0; i < child_count; i++) {
63
+ const child_volume = children[i].volume;
64
+
65
+ child_volumes[i] = child_volume;
66
+ this.__volume_sum += child_volume;
67
+
68
+ child_volume_sums[i] = this.__volume_sum;
69
+ }
70
+
71
+ }
72
+
73
+ /**
74
+ * Monte-carlo-style volume overlap estimation
75
+ * @private
76
+ */
77
+ __estimate_volume_overlap_fraction() {
78
+
79
+ if (this.__volume_sum === -1) {
80
+ this.__compute_volume_variables();
81
+ }
82
+
83
+ const children = this.children;
84
+ const child_count = children.length;
85
+
86
+ const random = seededRandom(1);
87
+
88
+ const child_volume_sums = this.__volume_sums;
89
+ const child_volume_sum = this.__volume_sum;
90
+
91
+ let i = 0, j = 0, k = 0, tap_overlaps = 0;
92
+
93
+ for (i = 0; i < VOLUME_OVERLAP_ESTIMATION_TAPS; i++) {
94
+
95
+ const target_weight = random() * child_volume_sum;
96
+
97
+ // weighted search for a sample candidate, preferring larger volumes, resulting in more uniform sample distribution
98
+ const target_child_index = binarySearchHighIndex(child_volume_sums, target_weight, compareNumbers, 0, child_count - 1);
99
+
100
+ const child_0 = children[target_child_index];
101
+
102
+ for (j = 0; j < VOLUME_OVERLAP_ESTIMATION_SUB_TAPS; j++, i++) {
103
+
104
+ child_0.sample_random_point_in_volume(scratch_array, 0, random);
105
+
106
+ for (k = 0; k < child_count; k++) {
107
+ if (target_child_index === k) {
108
+ // skip self
109
+ continue;
110
+ }
111
+
112
+ const child_1 = children[k];
113
+
114
+ if (child_1.contains_point(scratch_array)) {
115
+ tap_overlaps++;
116
+ }
117
+ }
118
+
119
+ }
120
+ }
121
+
122
+ this.__volume_overlap_fraction = tap_overlaps / (VOLUME_OVERLAP_ESTIMATION_TAPS);
123
+ }
124
+
125
+ static from(children) {
126
+ const r = new CompositeShape3D();
127
+
128
+ r.children = children;
129
+
130
+ return r;
25
131
  }
26
132
 
27
133
  get volume() {
28
- let r = 0;
134
+ if (this.__volume_overlap_fraction < 0) {
135
+ this.__estimate_volume_overlap_fraction();
136
+ }
137
+
138
+ let volume_sum = 0;
29
139
 
30
140
  const children = this.children;
31
141
  const child_count = children.length;
142
+
32
143
  for (let i = 0; i < child_count; i++) {
33
144
  const child = children[i];
34
145
 
35
- r += child.volume;
146
+ volume_sum += child.volume;
36
147
  }
37
148
 
38
- return r;
149
+ /**
150
+ * Unbias the volume by taking overlap into account
151
+ * @type {number}
152
+ */
153
+ const unbiased_volume = volume_sum / (this.__volume_overlap_fraction + 1);
154
+
155
+ return unbiased_volume;
39
156
  }
40
157
 
41
- get surface_area(){
158
+ get surface_area() {
42
159
  let r = 0;
43
160
 
44
161
  const children = this.children;
@@ -52,9 +169,72 @@ export class CompositeShape extends AbstractShape3D {
52
169
  return r;
53
170
  }
54
171
 
172
+ contains_point(point) {
173
+ const children = this.children;
174
+ const n = children.length;
175
+ for (let i = 0; i < n; i++) {
176
+ const child = children[i];
177
+
178
+ if (child.contains_point(point)) {
179
+ return true;
180
+ }
181
+ }
182
+
183
+ return false;
184
+ }
185
+
186
+
55
187
  sample_random_point_in_volume(result, result_offset, random) {
56
- const child = weightedRandomFromArray(this.children, random, getVolume);
188
+ const children = this.children;
189
+ const child_count = children.length;
190
+
191
+
192
+ const target_weight = random() * this.__volume_sum;
193
+
194
+ // weighted search for a sample candidate, preferring larger volumes, resulting in more uniform sample distribution
195
+ const target_child_index = binarySearchHighIndex(this.__volume_sums, target_weight, compareNumbers, 0, child_count - 1);
196
+
197
+ const child = children[target_child_index];
198
+
199
+ let collision_count, i, j;
57
200
 
58
- return child.sample_random_point_in_volume(result, result_offset, random);
201
+ for (i = 0; i < SAMPLE_REJECTION_ATTEMPT_MAX; i++) {
202
+
203
+ // sample shape
204
+ child.sample_random_point_in_volume(result, result_offset, random);
205
+
206
+ /*
207
+ because underlying shapes can overlap and we wish to offer a union, just returning the sample would result in over-sampling in areas where shapes overlap
208
+ to avoid this oversampling, we reject samples in such areas with probability proportional to number of overlapping shapes at the sampled point
209
+ */
210
+ collision_count = 0;
211
+
212
+ for (j = 0; j < child_count; j++) {
213
+ const child_1 = children[j];
214
+
215
+ if (child_1 === child) {
216
+ // exclude sampled child itself
217
+ continue;
218
+ }
219
+
220
+ if (child_1.contains_point(result)) {
221
+ collision_count++;
222
+ }
223
+ }
224
+
225
+ if (collision_count > 0) {
226
+ const rejection_chance = collision_count / (collision_count + 1);
227
+
228
+ const rejection_roll = random();
229
+
230
+ if (rejection_roll < rejection_chance) {
231
+ //reject
232
+ continue;
233
+ }
234
+ }
235
+
236
+ // no collisions, or survived rejection
237
+ break;
238
+ }
59
239
  }
60
240
  }
@@ -17,6 +17,14 @@ export class TransformedShape3D extends AbstractShape3D {
17
17
  * @private
18
18
  */
19
19
  this.__matrix = new Float32Array(16);
20
+
21
+ /**
22
+ *
23
+ * @type {Float32Array|mat4}
24
+ * @private
25
+ */
26
+ this.__inverse_matrix = new Float32Array(16);
27
+
20
28
  /**
21
29
  *
22
30
  * @type {AbstractShape3D|null}
@@ -27,7 +35,15 @@ export class TransformedShape3D extends AbstractShape3D {
27
35
 
28
36
  /**
29
37
  *
30
- * @param {number[]|Float32Array} m4
38
+ * @returns {AbstractShape3D|null}
39
+ */
40
+ get subject() {
41
+ return this.__subject;
42
+ }
43
+
44
+ /**
45
+ *
46
+ * @param {number[]|Float32Array|mat4} m4
31
47
  * @param {AbstractShape3D} subject
32
48
  * @returns {TransformedShape3D}
33
49
  */
@@ -35,17 +51,50 @@ export class TransformedShape3D extends AbstractShape3D {
35
51
  const r = new TransformedShape3D();
36
52
 
37
53
  r.__subject = subject;
38
- r.__matrix = m4;
54
+ r.transform = m4;
39
55
 
40
56
  return r;
41
57
  }
42
58
 
59
+ /**
60
+ *
61
+ * @param {AbstractShape3D} subject
62
+ * @param {number[]} translation
63
+ * @param {number[]} scale
64
+ */
65
+ static from_translation_scale(subject, translation, scale) {
66
+
67
+ const mat = mat4.create();
68
+ mat4.fromRotationTranslationScale(mat, [0, 0, 0, 1], translation, scale);
69
+
70
+ return TransformedShape3D.from_m4(subject, mat);
71
+ }
72
+
73
+ /**
74
+ *
75
+ * @returns {TransformedShape3D}
76
+ * @param {AbstractShape3D} subject
77
+ * @param {number[]|Float32Array|vec3} scale
78
+ */
79
+ static from_scale(subject, scale) {
80
+ const mat = mat4.create();
81
+ mat4.fromScaling(mat, scale);
82
+
83
+ return TransformedShape3D.from_m4(subject, mat);
84
+ }
85
+
43
86
  /**
44
87
  *
45
88
  * @param {number[]|Float32Array} m
46
89
  */
47
90
  set transform(m) {
48
91
  this.__matrix.set(m);
92
+
93
+ mat4.invert(this.__inverse_matrix, this.__matrix);
94
+ }
95
+
96
+ get transform() {
97
+ return this.__matrix;
49
98
  }
50
99
 
51
100
  get volume() {
@@ -56,6 +105,13 @@ export class TransformedShape3D extends AbstractShape3D {
56
105
  return this.__subject.volume * scale_modifier;
57
106
  }
58
107
 
108
+ contains_point(point) {
109
+ // transform point to subject's local space
110
+ vec3.transformMat4(scratch_v3, point, this.__inverse_matrix);
111
+
112
+ return this.__subject.contains_point(scratch_v3);
113
+ }
114
+
59
115
  sample_random_point_in_volume(result, result_offset, random) {
60
116
  this.__subject.sample_random_point_in_volume(scratch_v3, 0, random);
61
117
 
@@ -7,6 +7,17 @@ export class UnitCubeShape3D extends AbstractShape3D {
7
7
  return 1;
8
8
  }
9
9
 
10
+ contains_point(point) {
11
+ const x = point[0];
12
+ const y = point[1];
13
+ const z = point[2];
14
+
15
+ return x > -0.5 && x < 0.5
16
+ && y > -0.5 && y < 0.5
17
+ && z > -0.5 && z < 0.5
18
+ ;
19
+ }
20
+
10
21
  sample_random_point_in_volume(result, result_offset, random) {
11
22
  randomPointInBox(random, result, result_offset);
12
23
  }
@@ -10,6 +10,14 @@ export class UnitSphereShape3D extends AbstractShape3D {
10
10
  return 3.14159265;
11
11
  }
12
12
 
13
+ contains_point(point) {
14
+ const x = point[0];
15
+ const y = point[1];
16
+ const z = point[2];
17
+
18
+ return (x * x + y * y + z * z) < 1;
19
+ }
20
+
13
21
  sample_random_point_in_volume(result, result_offset, random) {
14
22
  randomPointInSphere(random, result, result_offset);
15
23
  }
@@ -0,0 +1,159 @@
1
+ import { CompositeShape3D } from "../CompositeShape.js";
2
+ import { UnitCubeShape3D } from "../UnitCubeShape3D.js";
3
+ import { UnitSphereShape3D } from "../UnitSphereShape3D.js";
4
+ import { TransformedShape3D } from "../TransformedShape3D.js";
5
+ import EntityBuilder from "../../../../../engine/ecs/EntityBuilder.js";
6
+ import { Transform } from "../../../../../engine/ecs/transform/Transform.js";
7
+ import { AttachmentSockets } from "../../../../../engine/ecs/sockets/AttachmentSockets.js";
8
+ import { Attachment } from "../../../../../engine/ecs/attachment/Attachment.js";
9
+ import { ShadedGeometry } from "../../../../../engine/graphics/ecs/mesh-v2/ShadedGeometry.js";
10
+ import { LineBasicMaterial } from "three";
11
+ import { makeHelperSphereGeometry } from "../../../../../editor/process/symbolic/makeHelperSphereGeometry.js";
12
+ import { DrawMode } from "../../../../../engine/graphics/ecs/mesh-v2/DrawMode.js";
13
+ import { makeHelperBoxGeometry } from "../../../../../editor/process/symbolic/makeHelperBoxGeometry.js";
14
+ import Tag from "../../../../../engine/ecs/components/Tag.js";
15
+
16
+ const g_unit_sphere = makeHelperSphereGeometry(0.5, 32);
17
+ const g_unit_cube = makeHelperBoxGeometry(1, 1, 1);
18
+
19
+ const lineMaterial = new LineBasicMaterial({
20
+ depthTest: true,
21
+ depthWrite: false,
22
+ transparent: true,
23
+ linewidth: 1,
24
+ fog: false,
25
+ color: '#FFFFFF',
26
+ opacity: 1
27
+ });
28
+
29
+ export const SHAPE_VISUAL_ENTITY_TAG = 'util/vis/Shape3D';
30
+
31
+ /**
32
+ *
33
+ * @param {CompositeShape3D} shape
34
+ * @param {EntityComponentDataset} ecd
35
+ * @returns {EntityBuilder}
36
+ */
37
+ function composite_shape_to_entity(shape, ecd) {
38
+
39
+ const parent = new EntityBuilder();
40
+ parent
41
+ .add(new Transform())
42
+ .add(AttachmentSockets.fromJSON({
43
+ elements: [
44
+ {
45
+ type: 0,
46
+ id: 0
47
+ }
48
+ ]
49
+ }))
50
+ .build(ecd);
51
+
52
+ shape.children.forEach(c => {
53
+
54
+ const child_entity = shape_to_visual_entity(c, ecd);
55
+
56
+ child_entity.add(Attachment.fromJSON({
57
+ socket: 0,
58
+ parent: parent.entity,
59
+ immediate: true
60
+ }));
61
+
62
+ })
63
+
64
+ return parent;
65
+ }
66
+
67
+
68
+ /**
69
+ *
70
+ * @param {UnitCubeShape3D} shape
71
+ * @param {EntityComponentDataset} ecd
72
+ * @returns {EntityBuilder}
73
+ */
74
+ function cube_shape_to_entity(shape, ecd) {
75
+ const eb = new EntityBuilder();
76
+
77
+ eb.add(new Transform());
78
+ eb.add(Tag.fromOne(SHAPE_VISUAL_ENTITY_TAG));
79
+ eb.add(ShadedGeometry.from(g_unit_cube, lineMaterial, DrawMode.LineSegments));
80
+
81
+ eb.build(ecd);
82
+
83
+ return eb;
84
+ }
85
+
86
+
87
+ /**
88
+ *
89
+ * @param {UnitSphereShape3D} shape
90
+ * @param {EntityComponentDataset} ecd
91
+ * @returns {EntityBuilder}
92
+ */
93
+ function sphere_shape_to_entity(shape, ecd) {
94
+ const eb = new EntityBuilder();
95
+
96
+ eb.add(new Transform());
97
+ eb.add(Tag.fromOne(SHAPE_VISUAL_ENTITY_TAG));
98
+ eb.add(ShadedGeometry.from(g_unit_sphere, lineMaterial, DrawMode.Lines));
99
+
100
+ eb.build(ecd);
101
+
102
+ return eb;
103
+
104
+ }
105
+
106
+ /**
107
+ *
108
+ * @param {TransformedShape3D} shape
109
+ * @param {EntityComponentDataset} ecd
110
+ * @returns {EntityBuilder}
111
+ */
112
+ function transformed_shape_to_entity(shape, ecd) {
113
+ const subject = shape_to_visual_entity(shape.subject, ecd);
114
+
115
+ const parent = new EntityBuilder();
116
+ parent
117
+ .add(new Transform())
118
+ .add(AttachmentSockets.fromJSON({
119
+ elements: [
120
+ {
121
+ type: 0,
122
+ id: 0
123
+ }
124
+ ]
125
+ }))
126
+ .build(ecd);
127
+
128
+ const attachment = Attachment.fromJSON({
129
+ socket: 0,
130
+ parent: parent.entity,
131
+ immediate: true
132
+ });
133
+
134
+ attachment.transform.fromMatrix4(shape.transform);
135
+
136
+ subject.add(attachment);
137
+
138
+ return parent;
139
+ }
140
+
141
+ /**
142
+ *
143
+ * @param {AbstractShape3D} shape
144
+ * @param {EntityComponentDataset} ecd
145
+ * @returns {EntityBuilder}
146
+ */
147
+ export function shape_to_visual_entity(shape, ecd) {
148
+ if (shape instanceof CompositeShape3D) {
149
+ return composite_shape_to_entity(shape, ecd);
150
+ } else if (shape instanceof UnitCubeShape3D) {
151
+ return cube_shape_to_entity(shape, ecd);
152
+ } else if (shape instanceof UnitSphereShape3D) {
153
+ return sphere_shape_to_entity(shape, ecd);
154
+ } else if (shape instanceof TransformedShape3D) {
155
+ return transformed_shape_to_entity(shape, ecd);
156
+ } else {
157
+ throw new Error('Unsupported shape type');
158
+ }
159
+ }
@@ -12,11 +12,12 @@ export function randomPointInSphere(random, result, result_offset) {
12
12
 
13
13
  const cosTheta = random() * 2 - 1;
14
14
 
15
- const u = random() * 0.5;
15
+ const u = random();
16
16
 
17
17
  const theta = Math.acos(cosTheta);
18
18
 
19
- const r = Math.cbrt(u);
19
+ // compute radius
20
+ const r = Math.cbrt(u) * 0.5;
20
21
 
21
22
  const sinTheta = Math.sin(theta);
22
23
 
@@ -44,10 +44,10 @@ export function resolvePathByArray(object, parts, missingPropertyHandler) {
44
44
  } else {
45
45
  const options = buildErrorSuggestions(current);
46
46
 
47
- throw new Error(`failed to resolve path '${path}' at part ${i} [${part}]. Existing keys: ${options.join(", ")}`);
47
+ throw new Error(`failed to resolve path [${parts.join(',')}] at part ${i} [${part}]. Existing keys: ${options.join(", ")}`);
48
48
  }
49
49
  }
50
50
  current = current[part];
51
51
  }
52
52
  return current;
53
- }
53
+ }