@woosh/meep-engine 2.35.4 → 2.35.7

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.
@@ -12,9 +12,9 @@ export class SurfacePoint3 {
12
12
 
13
13
  /**
14
14
  *
15
- * @param {number[]|mat4|Float32Array} m4
15
+ * @param {number[]|mat4|Float32Array} m
16
16
  */
17
- applyMatrix4(m4) {
17
+ applyMatrix4(m) {
18
18
  // transform position
19
19
  const p = this.position;
20
20
 
@@ -23,13 +23,13 @@ export class SurfacePoint3 {
23
23
  const p_z = p.z;
24
24
 
25
25
  // compute perspective projection
26
- const w = 1 / (m4[3] * p_x + m4[7] * p_y + m4[11] * p_z + m4[15]);
26
+ const w = 1 / (m[3] * p_x + m[7] * p_y + m[11] * p_z + m[15]);
27
27
 
28
- const result_p_x = (m4[0] * p_x + m4[4] * p_y + m4[8] * p_z + m4[12]) * w;
29
- const result_p_y = (m4[1] * p_x + m4[5] * p_y + m4[9] * p_z + m4[13]) * w;
30
- const result_p_z = (m4[2] * p_x + m4[6] * p_y + m4[10] * p_z + m4[14]) * w;
28
+ const result_p_x = (m[0] * p_x + m[4] * p_y + m[8] * p_z + m[12]) * w;
29
+ const result_p_y = (m[1] * p_x + m[5] * p_y + m[9] * p_z + m[13]) * w;
30
+ const result_p_z = (m[2] * p_x + m[6] * p_y + m[10] * p_z + m[14]) * w;
31
31
 
32
- this.position.set(
32
+ p.set(
33
33
  result_p_x,
34
34
  result_p_y,
35
35
  result_p_z
@@ -42,13 +42,13 @@ export class SurfacePoint3 {
42
42
  const n_y = n.y;
43
43
  const n_z = n.z;
44
44
 
45
- const result_n_x = m4[0] * n_x + m4[4] * n_y + m4[8] * n_z;
46
- const result_n_y = m4[1] * n_x + m4[5] * n_y + m4[9] * n_z;
47
- const result_n_z = m4[2] * n_x + m4[6] * n_y + m4[10] * n_z;
45
+ const result_n_x = m[0] * n_x + m[4] * n_y + m[8] * n_z;
46
+ const result_n_y = m[1] * n_x + m[5] * n_y + m[9] * n_z;
47
+ const result_n_z = m[2] * n_x + m[6] * n_y + m[10] * n_z;
48
48
 
49
49
  const normal_multiplier = 1 / v3_length(result_n_x, result_n_y, result_n_z);
50
50
 
51
- this.normal.set(
51
+ n.set(
52
52
  result_n_x * normal_multiplier,
53
53
  result_n_y * normal_multiplier,
54
54
  result_n_z * normal_multiplier,
@@ -166,7 +166,7 @@ export class ShadedGeometrySystem extends System {
166
166
  this.__render_layer.buildVisibleSet = ((destination, destination_offset, view) => {
167
167
  const ctx = this.__view_contexts.get(view);
168
168
 
169
- return ctx.collect(destination, destination_offset, view, this.__bvh);
169
+ return ctx.collect(destination, destination_offset,graphics.renderer, view, this.__bvh);
170
170
  });
171
171
 
172
172
  readyCallback();
@@ -76,7 +76,7 @@ export class ShadedGeometryRendererContext {
76
76
  for (; i < adapter_count; i++) {
77
77
  const adapter = adapters[i];
78
78
 
79
- adapter.build_start(renderer);
79
+ adapter.build_start(renderer, view);
80
80
  }
81
81
 
82
82
 
@@ -3,7 +3,7 @@ import { ShadedGeometrySystem } from "../ShadedGeometrySystem.js";
3
3
  import EntityBuilder from "../../../../ecs/EntityBuilder.js";
4
4
  import { Transform } from "../../../../ecs/transform/Transform.js";
5
5
  import { ShadedGeometry } from "../ShadedGeometry.js";
6
- import { BoxBufferGeometry, MeshStandardMaterial } from "three";
6
+ import { BoxBufferGeometry, MeshStandardMaterial, OctahedronGeometry } from "three";
7
7
  import { randomFloatBetween } from "../../../../../core/math/random/randomFloatBetween.js";
8
8
  import { seededRandom } from "../../../../../core/math/random/seededRandom.js";
9
9
  import ViewportPosition from "../../../../ecs/gui/position/ViewportPosition.js";
@@ -17,12 +17,31 @@ import Vector3 from "../../../../../core/geom/Vector3.js";
17
17
  import Quaternion from "../../../../../core/geom/Quaternion.js";
18
18
  import { ShadedGeometryFlags } from "../ShadedGeometryFlags.js";
19
19
  import { randomFromArray } from "../../../../../core/math/random/randomFromArray.js";
20
+ import { BehaviorComponent } from "../../../../intelligence/behavior/ecs/BehaviorComponent.js";
21
+ import { OrbitingBehavior } from "../../../../../../model/game/util/behavior/OrbitingBehavior.js";
22
+ import { BehaviorSystem } from "../../../../intelligence/behavior/ecs/BehaviorSystem.js";
20
23
 
21
24
  const eh = new EngineHarness();
22
25
 
23
26
  const DRAW_METHOD_PLAIN = 0;
24
27
  const DRAW_METHOD_INSTANCED = 1;
25
28
 
29
+ function makeMovingShadedGeometry() {
30
+ const b = new OrbitingBehavior();
31
+ b.offset.set(4, 1, 4);
32
+ b.radius = 2;
33
+ b.rate = 1;
34
+
35
+ const sg = ShadedGeometry.from(new OctahedronGeometry(0.5, 5), new MeshStandardMaterial({ color: 0xFF0000 }));
36
+
37
+ sg.draw_method = DRAW_METHOD_INSTANCED;
38
+
39
+ return new EntityBuilder()
40
+ .add(new Transform())
41
+ .add(sg)
42
+ .add(BehaviorComponent.fromOne(b));
43
+ }
44
+
26
45
  /**
27
46
  *
28
47
  * @param {Engine} engine
@@ -32,6 +51,7 @@ async function main(engine) {
32
51
  const em = engine.entityManager;
33
52
 
34
53
  await em.addSystem(new ShadedGeometrySystem(engine));
54
+ await em.addSystem(new BehaviorSystem(engine));
35
55
 
36
56
  EngineHarness.buildBasics({
37
57
  engine,
@@ -54,11 +74,11 @@ async function main(engine) {
54
74
 
55
75
  const random = seededRandom(0);
56
76
 
57
- const INSTANCE_COUNT = 20000;
77
+ const INSTANCE_COUNT = 0;
58
78
 
59
79
  const geometries = [];
60
80
 
61
- for (let i = 0; i < 1000; i++) {
81
+ for (let i = 0; i < 1; i++) {
62
82
  geometries.push(new BoxBufferGeometry());
63
83
  }
64
84
 
@@ -85,6 +105,8 @@ async function main(engine) {
85
105
  .build(ecd);
86
106
  }
87
107
 
108
+ makeMovingShadedGeometry().build(ecd);
109
+
88
110
  debug_button(engine, () => {
89
111
  const dot = convert_bvh_to_dot_format_string(engine.graphics.layers.getLayerByName('shaded-geometry').bvh);
90
112
  downloadAsFile(dot, 'bvh.dot', 'text');
@@ -323,7 +323,8 @@ function main(engine) {
323
323
  EngineHarness.buildBasics({ engine });
324
324
 
325
325
  const _p = new Path();
326
- _p.interpolation = InterpolationType.CatmullRom;
326
+ // _p.interpolation = InterpolationType.CatmullRom;
327
+ _p.interpolation = InterpolationType.Linear;
327
328
 
328
329
  // _p.setPositionsFromVectorArray(Path.smoothPath([
329
330
  // new Vector3(3, 1, 1),
@@ -351,14 +352,14 @@ function main(engine) {
351
352
 
352
353
  const pathDisplay = new PathDisplay();
353
354
  pathDisplay.specs.push(
354
- PathDisplaySpec.from(
355
- PathDisplayType.Ribbon,
356
- trailPathStyle
357
- ),
358
- PathDisplaySpec.from(
359
- PathDisplayType.Entity,
360
- sample_style_entity()
361
- ),
355
+ // PathDisplaySpec.from(
356
+ // PathDisplayType.Ribbon,
357
+ // trailPathStyle
358
+ // ),
359
+ // PathDisplaySpec.from(
360
+ // PathDisplayType.Entity,
361
+ // sample_style_entity()
362
+ // ),
362
363
  PathDisplaySpec.from(
363
364
  PathDisplayType.Tube,
364
365
  sample_style_tube()
@@ -1,4 +1,12 @@
1
- import { CatmullRomCurve3, MeshMatcapMaterial, MeshStandardMaterial, TubeGeometry, Vector3 } from "three";
1
+ import {
2
+ BufferGeometry,
3
+ CatmullRomCurve3,
4
+ Float32BufferAttribute,
5
+ MeshMatcapMaterial,
6
+ MeshStandardMaterial,
7
+ TubeGeometry,
8
+ Vector3
9
+ } from "three";
2
10
  import { InterpolationType } from "../../../../navigation/ecs/components/InterpolationType.js";
3
11
  import EntityBuilder from "../../../../ecs/EntityBuilder.js";
4
12
  import { Transform } from "../../../../ecs/transform/Transform.js";
@@ -6,6 +14,10 @@ import Renderable from "../../../../ecs/components/Renderable.js";
6
14
  import ThreeFactory from "../../../three/ThreeFactory.js";
7
15
  import { TubeMaterialType } from "./TubeMaterialType.js";
8
16
  import { GameAssetType } from "../../../../asset/GameAssetType.js";
17
+ import { Matrix4 } from "three/src/math/Matrix4.js";
18
+ import * as MathUtils from "three/src/math/MathUtils.js";
19
+ import { max2 } from "../../../../../core/math/max2.js";
20
+ import { min2 } from "../../../../../core/math/min2.js";
9
21
 
10
22
  /**
11
23
  * some useful references:
@@ -43,6 +55,306 @@ function estimatePathViaIterativeIntegral(path, epsilon) {
43
55
  return sum;
44
56
  }
45
57
 
58
+ /**
59
+ * @see https://github.com/mrdoob/three.js/blob/c12c9a166a1369cdd58622fff2aff7e3a84305d7/src/extras/core/Curve.js#L260
60
+ * @param {Vector3[]} points
61
+ * @param {boolean} [closed]
62
+ */
63
+ function computeFrenetFrames(points, closed = false) {
64
+ // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
65
+
66
+ const normal = new Vector3();
67
+
68
+ const tangents = [];
69
+ const normals = [];
70
+ const binormals = [];
71
+
72
+ const vec = new Vector3();
73
+ const mat = new Matrix4();
74
+
75
+ const segments = points.length - 1;
76
+
77
+ const v3_0 = new Vector3();
78
+ const v3_1 = new Vector3();
79
+
80
+ /**
81
+ *
82
+ * @param {number} i
83
+ * @param {Vector3} destination
84
+ */
85
+ function getTangent(i, destination) {
86
+ // get points on either side
87
+ const i0 = max2(i - 1, 0);
88
+ const i1 = min2(i + 1, segments);
89
+
90
+ const p0 = points[i0];
91
+ const pR = points[i];
92
+ const p1 = points[i1];
93
+
94
+ // get points along the lines close to the reference
95
+ v3_0.subVectors(p0, pR);
96
+ v3_0.normalize();
97
+
98
+ v3_1.subVectors(p1, pR);
99
+ v3_1.normalize();
100
+
101
+ destination.subVectors(v3_1, v3_0);
102
+ destination.normalize();
103
+ }
104
+
105
+ // compute the tangent vectors for each segment on the curve
106
+
107
+ for (let i = 0; i <= segments; i++) {
108
+
109
+ const tangent = new Vector3();
110
+ getTangent(i, tangent);
111
+
112
+ tangents[i] = tangent;
113
+
114
+ }
115
+
116
+ // select an initial normal vector perpendicular to the first tangent vector,
117
+ // and in the direction of the minimum tangent xyz component
118
+
119
+ normals[0] = new Vector3();
120
+ binormals[0] = new Vector3();
121
+ let min = Number.MAX_VALUE;
122
+ const tx = Math.abs(tangents[0].x);
123
+ const ty = Math.abs(tangents[0].y);
124
+ const tz = Math.abs(tangents[0].z);
125
+
126
+ if (tx <= min) {
127
+
128
+ min = tx;
129
+ normal.set(1, 0, 0);
130
+
131
+ }
132
+
133
+ if (ty <= min) {
134
+
135
+ min = ty;
136
+ normal.set(0, 1, 0);
137
+
138
+ }
139
+
140
+ if (tz <= min) {
141
+
142
+ normal.set(0, 0, 1);
143
+
144
+ }
145
+
146
+ vec.crossVectors(tangents[0], normal).normalize();
147
+
148
+ normals[0].crossVectors(tangents[0], vec);
149
+ binormals[0].crossVectors(tangents[0], normals[0]);
150
+
151
+
152
+ // compute the slowly-varying normal and binormal vectors for each segment on the curve
153
+
154
+ for (let i = 1; i <= segments; i++) {
155
+
156
+ normals[i] = normals[i - 1].clone();
157
+
158
+ binormals[i] = binormals[i - 1].clone();
159
+
160
+ vec.crossVectors(tangents[i - 1], tangents[i]);
161
+
162
+ if (vec.length() > Number.EPSILON) {
163
+
164
+ vec.normalize();
165
+
166
+ const theta = Math.acos(MathUtils.clamp(tangents[i - 1].dot(tangents[i]), -1, 1)); // clamp for floating pt errors
167
+
168
+ normals[i].applyMatrix4(mat.makeRotationAxis(vec, theta));
169
+
170
+ }
171
+
172
+ binormals[i].crossVectors(tangents[i], normals[i]);
173
+
174
+ }
175
+
176
+ // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
177
+
178
+ if (closed === true) {
179
+
180
+ let theta = Math.acos(MathUtils.clamp(normals[0].dot(normals[segments]), -1, 1));
181
+ theta /= segments;
182
+
183
+ if (tangents[0].dot(vec.crossVectors(normals[0], normals[segments])) > 0) {
184
+
185
+ theta = -theta;
186
+
187
+ }
188
+
189
+ for (let i = 1; i <= segments; i++) {
190
+
191
+ // twist a little...
192
+ normals[i].applyMatrix4(mat.makeRotationAxis(tangents[i], theta * i));
193
+ binormals[i].crossVectors(tangents[i], normals[i]);
194
+
195
+ }
196
+
197
+ }
198
+
199
+ return {
200
+ tangents: tangents,
201
+ normals: normals,
202
+ binormals: binormals
203
+ };
204
+ }
205
+
206
+ /**
207
+ * @see https://github.com/mrdoob/three.js/blob/master/src/geometries/TubeGeometry.js
208
+ * @param {Vector3[]} points
209
+ * @param {Vector3[]} _normals
210
+ * @param {Vector3[]} binormals
211
+ * @param {number} radius
212
+ * @param {number} radialSegments
213
+ * @param {boolean} [closed]
214
+ * @returns {BufferGeometry}
215
+ */
216
+ function makeTubeGeometry(points, _normals, binormals, radius, radialSegments, closed = false) {
217
+ const geometry = new BufferGeometry();
218
+ // helper variables
219
+
220
+ const vertex = new Vector3();
221
+ const normal = new Vector3();
222
+
223
+ // buffer
224
+
225
+ const vertices = [];
226
+ const normals = [];
227
+ const uvs = [];
228
+ const indices = [];
229
+
230
+ const tubularSegments = points.length - 1;
231
+
232
+ // create buffer data
233
+
234
+ generateBufferData();
235
+
236
+ // build geometry
237
+
238
+ geometry.setIndex(indices);
239
+ geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3));
240
+ geometry.setAttribute('normal', new Float32BufferAttribute(normals, 3));
241
+ geometry.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
242
+
243
+ // functions
244
+
245
+ function generateBufferData() {
246
+
247
+ for (let i = 0; i < tubularSegments; i++) {
248
+
249
+ generateSegment(i);
250
+
251
+ }
252
+
253
+ // if the geometry is not closed, generate the last row of vertices and normals
254
+ // at the regular position on the given path
255
+ //
256
+ // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
257
+
258
+ generateSegment((closed === false) ? tubularSegments : 0);
259
+
260
+ // uvs are generated in a separate function.
261
+ // this makes it easy compute correct values for closed geometries
262
+
263
+ generateUVs();
264
+
265
+ // finally create faces
266
+
267
+ generateIndices();
268
+
269
+ }
270
+
271
+ function generateSegment(i) {
272
+
273
+ // we use getPointAt to sample evenly distributed points from the given path
274
+
275
+ const P = points[i];
276
+
277
+ // retrieve corresponding normal and binormal
278
+
279
+ const N = _normals[i];
280
+ const B = binormals[i];
281
+
282
+ // generate normals and vertices for the current segment
283
+
284
+ for (let j = 0; j <= radialSegments; j++) {
285
+
286
+ const v = j / radialSegments * Math.PI * 2;
287
+
288
+ const sin = Math.sin(v);
289
+ const cos = -Math.cos(v);
290
+
291
+ // normal
292
+
293
+ normal.x = (cos * N.x + sin * B.x);
294
+ normal.y = (cos * N.y + sin * B.y);
295
+ normal.z = (cos * N.z + sin * B.z);
296
+ normal.normalize();
297
+
298
+ normals.push(normal.x, normal.y, normal.z);
299
+
300
+ // vertex
301
+
302
+ vertex.x = P.x + radius * normal.x;
303
+ vertex.y = P.y + radius * normal.y;
304
+ vertex.z = P.z + radius * normal.z;
305
+
306
+ vertices.push(vertex.x, vertex.y, vertex.z);
307
+
308
+ }
309
+
310
+ }
311
+
312
+ function generateIndices() {
313
+ let i = 0, j = 0;
314
+
315
+ for (j = 1; j <= tubularSegments; j++) {
316
+
317
+ for (i = 1; i <= radialSegments; i++) {
318
+
319
+ const a = (radialSegments + 1) * (j - 1) + (i - 1);
320
+ const b = (radialSegments + 1) * j + (i - 1);
321
+ const c = (radialSegments + 1) * j + i;
322
+ const d = (radialSegments + 1) * (j - 1) + i;
323
+
324
+ // faces
325
+
326
+ indices.push(a, b, d);
327
+ indices.push(b, c, d);
328
+
329
+ }
330
+
331
+ }
332
+
333
+ }
334
+
335
+ function generateUVs() {
336
+ let i = 0, j = 0;
337
+
338
+ for (i = 0; i <= tubularSegments; i++) {
339
+
340
+ const u = i / tubularSegments;
341
+
342
+ for (j = 0; j <= radialSegments; j++) {
343
+
344
+ const v = j / radialSegments;
345
+
346
+ uvs.push(u, v);
347
+
348
+ }
349
+
350
+ }
351
+
352
+ }
353
+
354
+
355
+ return geometry;
356
+ }
357
+
46
358
  /**
47
359
  *
48
360
  * @param {Path} path
@@ -58,6 +370,35 @@ function estimatePathLength(path) {
58
370
 
59
371
  }
60
372
 
373
+ /**
374
+ *
375
+ * @param {THREE.Vector3[]} points
376
+ * @param {number} point_count
377
+ * @param {TubePathStyle} style
378
+ * @return {BufferGeometry}
379
+ */
380
+ function build_geometry_linear(points, point_count, style) {
381
+
382
+ const frames = computeFrenetFrames(points, false);
383
+
384
+ return makeTubeGeometry(points, frames.normals, frames.binormals, style.width, style.radial_resolution, false);
385
+ }
386
+
387
+ /**
388
+ *
389
+ * @param {THREE.Vector3[]} points
390
+ * @param {number} point_count
391
+ * @param {TubePathStyle} style
392
+ * @return {BufferGeometry}
393
+ */
394
+ function build_geometry_catmullrom(points, point_count, style) {
395
+
396
+ const path = new CatmullRomCurve3(points, false, "centripetal");
397
+
398
+ return new TubeGeometry(path, style.resolution * point_count, style.width, style.radial_resolution, false);
399
+
400
+ }
401
+
61
402
  export class TubePathBuilder {
62
403
  constructor() {
63
404
  /**
@@ -129,26 +470,27 @@ export class TubePathBuilder {
129
470
  }
130
471
 
131
472
 
132
- let path;
473
+ /**
474
+ * @type {THREE.BufferGeometry}
475
+ */
476
+ let geometry;
133
477
 
134
478
  if (path_component.interpolation === InterpolationType.Linear) {
135
- path = new CatmullRomCurve3(three_points, false, "catmullrom", 0);
479
+ geometry = build_geometry_linear(three_points, pointCount, style);
136
480
  } else if (path_component.interpolation === InterpolationType.CatmullRom) {
137
- path = new CatmullRomCurve3(three_points, false, "centripetal");
481
+ geometry = build_geometry_catmullrom(three_points, pointCount, style);
138
482
  } else {
139
483
  throw new Error(`Unsupported interpolation type '${path_component.interpolation}'`);
140
484
  }
141
485
 
142
486
 
143
- const geometry = new TubeGeometry(path, style.resolution * pointCount, style.width, style.radial_resolution, false);
144
-
145
487
  let material_def;
146
488
 
147
489
  if (style.material_type === TubeMaterialType.Standard) {
148
490
  material_def = new MeshStandardMaterial({
149
- metalness: style.material.metalness,
150
- roughness: style.material.roughness
151
- });
491
+ metalness: style.material.metalness,
492
+ roughness: style.material.roughness
493
+ });
152
494
  } else if (style.material_type === TubeMaterialType.Matcap) {
153
495
 
154
496
  material_def = new MeshMatcapMaterial();
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "productName": "Meep",
6
6
  "description": "production-ready JavaScript game engine based on Entity Component System Architecture",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.35.4",
8
+ "version": "2.35.7",
9
9
  "dependencies": {
10
10
  "gl-matrix": "3.4.3",
11
11
  "fast-levenshtein": "2.0.6",