@woosh/meep-engine 2.34.44 → 2.34.45

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.
@@ -31,14 +31,6 @@ export class TopoMesh {
31
31
  this.__faces = new Set();
32
32
  }
33
33
 
34
- get edges() {
35
- throw new Error('Deprecated accessor, use getEdges instead');
36
- }
37
-
38
- get faces() {
39
- throw new Error('Deprecated accessor, use getEdges instead');
40
- }
41
-
42
34
  /**
43
35
  *
44
36
  * @returns {Set<TopoEdge>}
@@ -241,24 +241,25 @@ export class TopoVertex {
241
241
  const faces = victim.faces;
242
242
  const face_count = faces.length;
243
243
 
244
- for (let i = 0; i < face_count; i++) {
244
+ let i = 0;
245
+
246
+ for (; i < face_count; i++) {
245
247
  // take over the victim's faces
246
248
  const face = faces[i];
247
249
 
248
- // DEBUG
249
- face.computeNormal();
250
+
251
+ // face.computeNormal(); // DEBUG
250
252
  face.replaceVertex(victim, this);
251
253
 
252
254
  this.addUniqueFace(face);
253
255
 
254
- // DEBUG
255
- face.computeNormal();
256
+ // face.computeNormal(); // DEBUG
256
257
  }
257
258
 
258
259
  const edges = victim.edges;
259
260
  const edge_count = edges.length;
260
261
 
261
- for (let i = 0; i < edge_count; i++) {
262
+ for (i = 0; i < edge_count; i++) {
262
263
  // take over the victim's edges
263
264
  const edge = edges[i];
264
265
 
@@ -1,4 +1,7 @@
1
1
  import { v3_dot } from "../../../../v3_dot.js";
2
+ import { fabsf } from "../../../../../math/fabsf.js";
3
+ import { EPSILON } from "../../../../../math/MathUtils.js";
4
+ import { vec3 } from "gl-matrix";
2
5
 
3
6
  export class Quadratic3 {
4
7
  constructor() {
@@ -21,6 +24,74 @@ export class Quadratic3 {
21
24
  this.d2 = 0;
22
25
  }
23
26
 
27
+ /**
28
+ *
29
+ * @param {ArrayLike<number>|number[]|Float32Array} result
30
+ */
31
+ toVector3(result) {
32
+ result[0] = this.ad;
33
+ result[1] = this.bd;
34
+ result[2] = this.cd;
35
+ }
36
+
37
+ /**
38
+ *
39
+ * @param {ArrayLike<number>|number[]|Float32Array} m3
40
+ */
41
+ toTensorM3(m3) {
42
+ m3[0] = this.a2;
43
+ m3[1] = this.ab;
44
+ m3[2] = this.ac;
45
+
46
+ m3[3] = this.ab;
47
+ m3[4] = this.b2;
48
+ m3[5] = this.bc;
49
+
50
+ m3[6] = this.ac;
51
+ m3[7] = this.bc;
52
+ m3[8] = this.c2;
53
+ }
54
+
55
+ /**
56
+ * Equivalent to taking a tensor followed by matrix inversion
57
+ * @param {ArrayLike<number>|number[]|Float32Array} m3
58
+ * @param {number} epsilon
59
+ * @returns {boolean} whether operation was successful or not
60
+ */
61
+ toTensorM3Inverse(m3, epsilon) {
62
+ const a2 = this.a2;
63
+ const b2 = this.b2;
64
+ const c2 = this.c2;
65
+ const bc = this.bc;
66
+ const ab = this.ab;
67
+ const ac = this.ac;
68
+
69
+ const det = a2 * (b2 * c2 - bc * bc) -
70
+ ab * (ab * c2 - ac * bc) +
71
+ ac * (ab * bc - ac * b2);
72
+
73
+ if (fabsf(det) > epsilon) {
74
+
75
+ const invdet = 1.0 / det;
76
+
77
+ m3[0] = (b2 * c2 - bc * bc) * invdet;
78
+ m3[3] = (bc * ac - ab * c2) * invdet;
79
+ m3[6] = (ab * bc - b2 * ac) * invdet;
80
+
81
+ m3[1] = (ac * bc - ab * c2) * invdet;
82
+ m3[4] = (a2 * c2 - ac * ac) * invdet;
83
+ m3[7] = (ab * ac - a2 * bc) * invdet;
84
+
85
+ m3[2] = (ab * bc - ac * b2) * invdet;
86
+ m3[5] = (ac * ab - a2 * bc) * invdet;
87
+ m3[8] = (a2 * b2 - ab * ab) * invdet;
88
+
89
+ return true;
90
+ }
91
+
92
+ return false;
93
+ }
94
+
24
95
  /**
25
96
  * Set from plane expressed as a 4 component vector
26
97
  * @param {number} x plane normal
@@ -78,18 +149,35 @@ export class Quadratic3 {
78
149
  evaluate(x, y, z) {
79
150
  // Evaluate vAv + 2bv + c
80
151
 
81
- return x * x * this.a2 + 2 * x * y * this.ab + 2 * x * z * this.ac + 2 * x * this.ad
82
- + y * y * this.b2 + 2 * y * z * this.bc + 2 * y * this.bd
83
- + z * z * this.c2 + 2 * z * this.cd
84
- + this.d2;
152
+ return (x * x * this.a2) + (2 * x * y * this.ab) + (2 * x * z * this.ac) + (2 * x * this.ad) // A
153
+ + (y * y * this.b2) + (2 * y * z * this.bc) + (2 * y * this.bd) // B
154
+ + (z * z * this.c2) + (2 * z * this.cd) // C
155
+ + this.d2; // D
85
156
  }
86
157
 
87
158
  /**
159
+ * Find optimal vertex position based on the quadratic
160
+ *
161
+ * Based on Bleder's implementation: https://github.com/blender/blender/blob/594f47ecd2d5367ca936cf6fc6ec8168c2b360d0/source/blender/blenlib/intern/quadric.c
88
162
  *
89
163
  * @param {number[]} out
164
+ * @returns {boolean}
90
165
  */
91
166
  optimize(out) {
92
- throw new Error('Not Implemented');
167
+ const m = new Float32Array(9);
168
+
169
+ if (this.toTensorM3Inverse(m, EPSILON)) {
170
+
171
+ this.toVector3(out);
172
+
173
+ vec3.transformMat3(out, out, m);
174
+ vec3.negate(out, out);
175
+
176
+ return true;
177
+ }
178
+
179
+ return false;
180
+
93
181
  }
94
182
 
95
183
  /**
@@ -31,7 +31,10 @@ export function build_vertex_quadratics(mesh, quadratics) {
31
31
  const mesh_vertices = mesh.vertices;
32
32
  const mesh_vertex_count = mesh_vertices.length;
33
33
 
34
- for (let i = 0; i < mesh_vertex_count; i++) {
34
+
35
+ let i, face;
36
+
37
+ for (i = 0; i < mesh_vertex_count; i++) {
35
38
  const mesh_vertex = mesh_vertices[i];
36
39
 
37
40
  const vertex_quadratic = new Quadratic3();
@@ -44,15 +47,15 @@ export function build_vertex_quadratics(mesh, quadratics) {
44
47
 
45
48
  const faces = mesh.getFaces();
46
49
 
47
- for (let face of faces) {
50
+ for (face of faces) {
48
51
 
49
52
  q.setFromFace(face);
50
53
 
51
54
  const face_vertices = face.vertices;
52
55
  const face_vertex_count = face_vertices.length;
53
56
 
54
- for (let j = 0; j < face_vertex_count; j++) {
55
- const face_vertex = face_vertices[j];
57
+ for (i = 0; i < face_vertex_count; i++) {
58
+ const face_vertex = face_vertices[i];
56
59
 
57
60
  // accumulate to adjacent vertex
58
61
  const face_vertex_quadratic = quadratics.get(face_vertex.index);
@@ -18,5 +18,11 @@ export function compute_edge_collapse_cost_quadratic(
18
18
  const q_v0 = q0.evaluate(target.x, target.y, target.z);
19
19
  const q_v1 = q1.evaluate(target.x, target.y, target.z);
20
20
 
21
- return q_v0 + q_v1;
21
+ /**
22
+ * 'cost' shouldn't be negative but happens sometimes with small values.
23
+ * @type {number}
24
+ */
25
+ const cost = Math.abs(q_v0 + q_v1);
26
+
27
+ return cost;
22
28
  }
@@ -23,7 +23,6 @@ export function extract_edge_cost(edge) {
23
23
  /**
24
24
  * @param {number} number_faces_to_remove minimum number of faces to removed
25
25
  * @param {BinaryHeap<EdgeCollapseCandidate>} heap
26
- * @param {EdgeCollapseCandidate[]} removed_edges
27
26
  * @param {TopoMesh} mesh
28
27
  * @param {Map<TopoEdge, EdgeCollapseCandidate>} edge_to_collapse_map
29
28
  * @param {Map<number, Quadratic3>} vertex_quadratics
@@ -32,7 +31,6 @@ export function extract_edge_cost(edge) {
32
31
  export function collapse_edges(
33
32
  number_faces_to_remove,
34
33
  heap,
35
- removed_edges,
36
34
  mesh,
37
35
  edge_to_collapse_map,
38
36
  vertex_quadratics,
@@ -64,8 +62,6 @@ export function collapse_edges(
64
62
  // continue;
65
63
  // }
66
64
 
67
- removed_edges.push(collapse_candidate);
68
-
69
65
  // find edges that need to be updated
70
66
  const victim_vertex = collapse_candidate.victim_vertex;
71
67
 
@@ -208,21 +204,15 @@ export function collapse_edges(
208
204
  * @param {TopoMesh} mesh
209
205
  * @param {number} num_faces_to_remove desired number of faces to remove
210
206
  * @param {Set<number>} [restricted_vertices] vertices that are not allowed to be removed
211
- * @returns {EdgeCollapseCandidate[]} collapsed edges
212
207
  */
213
208
  export function simplifyTopoMesh(mesh, num_faces_to_remove, restricted_vertices = new Set()) {
214
- /**
215
- *
216
- * @type {EdgeCollapseCandidate[]}
217
- */
218
- const removed_edges = [];
219
209
 
220
210
  const faces = mesh.getFaces();
221
211
  const face_count = faces.size;
222
212
 
223
213
  if (num_faces_to_remove <= 0 || face_count <= 0) {
224
214
  // we're already at the target
225
- return removed_edges;
215
+ return ;
226
216
  }
227
217
 
228
218
 
@@ -258,7 +248,6 @@ export function simplifyTopoMesh(mesh, num_faces_to_remove, restricted_vertices
258
248
  collapse_edges(
259
249
  num_faces_to_remove,
260
250
  open_set,
261
- removed_edges,
262
251
  mesh,
263
252
  edge_to_collapse_map,
264
253
  vertex_quadratics,
@@ -270,6 +259,4 @@ export function simplifyTopoMesh(mesh, num_faces_to_remove, restricted_vertices
270
259
  collapse_all_degenerate_edges(mesh.getEdges(), mesh);
271
260
 
272
261
  // debugValidateMesh(mesh);
273
-
274
- return removed_edges;
275
262
  }
@@ -15,6 +15,7 @@ import { compute_buffer_geometry_byte_size } from "../../geometry/buffered/compu
15
15
  import { deinterleaveBufferGeometry } from "../../geometry/buffered/deinterleaveBufferGeometry.js";
16
16
  import { AABB3 } from "../../../../core/bvh2/aabb3/AABB3.js";
17
17
  import { aabb3_from_v3_array } from "../../../../core/bvh2/aabb3/aabb3_from_v3_array.js";
18
+ import { update_topo_face_normals } from "../../../../core/geom/3d/topology/update_topo_face_normals.js";
18
19
 
19
20
  /**
20
21
  * Returns current time in milliseconds
@@ -142,6 +143,9 @@ export async function buildMicronGeometryFromBufferGeometry(input) {
142
143
 
143
144
  expandConnectivityByLocality(topoMesh, geometry_aabb);
144
145
 
146
+ // ensure faces have normals for mesh simplification
147
+ update_topo_face_normals(Array.from(topoMesh.getFaces()), topoMesh.getFaces().size);
148
+
145
149
  /**
146
150
  * Used to generate neighbourhood assignment
147
151
  * @type {Map<number, PatchRepresentation>}
@@ -399,7 +399,6 @@ async function many_to_many_merge(
399
399
  collapse_edges(
400
400
  num_desired_faces_to_remove,
401
401
  open_set,
402
- [],
403
402
  merged_mesh,
404
403
  edge_to_collapse_map,
405
404
  vertex_quadratics,
@@ -462,6 +461,7 @@ async function many_to_many_merge(
462
461
  // );
463
462
 
464
463
  const group_per_pixel_error = group_inverse_polycount;
464
+ // const group_per_pixel_error = Math.sqrt(largest_squared_error);
465
465
 
466
466
  // split topology into desired number of pieces
467
467
  const pieces = recursive_split_mesh_partition(merged_mesh, actual_up_count, MICRON_PATCH_SIZE_MAX);
@@ -76,6 +76,8 @@ export async function convert_three_object_to_micron(object, micron_cache = defa
76
76
 
77
77
  await micron_cache.set(g, micron_geometry);
78
78
 
79
+ // console.log(micron_geometry);
80
+
79
81
  return micron_geometry;
80
82
  }
81
83
 
@@ -48,7 +48,6 @@ import { CanvasView } from "../../../view/elements/CanvasView.js";
48
48
  import { Sampler2D } from "../texture/sampler/Sampler2D.js";
49
49
  import { downsampleSampler2D } from "../texture/sampler/downsampleSampler2D.js";
50
50
  import { ShadowMapRenderer } from "../shadows/ShadowMapRenderer.js";
51
- import { MouseEvents } from "../../input/devices/events/MouseEvents.js";
52
51
  import { mat4 } from "gl-matrix";
53
52
 
54
53
  const background = new TextureLoader().load('data/textures/utility/checkers_white_grey_256x256.png');
@@ -461,13 +460,14 @@ function init() {
461
460
  // sample_gltf_sponza();
462
461
  // gltf_sample('data/models/RTS_Buildings_Humans/18/Building_R_18_out/Building_R_18.gltf');
463
462
  sample_lucy();
463
+ // sample_dragon();
464
464
  // sample_gltf_hapro_2();
465
465
  // sample_gltf_hapro_1();
466
466
  // sample_gltf_broken_isiflow();
467
467
  // gltf_grid('data/models/moicon/Kople/EVCharger1.gltf');
468
468
  // gltf_grid('data/models/RTS_Buildings_Humans/18/Building_R_18_out/Building_R_18.gltf');
469
- // gltf_sample('data/models/moicon/08-clickable-assets/model.gltf');
470
- // gltf_sample('data/models/moicon/05-ground-floor/model.gltf');
469
+ // gltf_sample('moicon/08-clickable-assets/model.gltf');
470
+ // gltf_sample('moicon/05-ground-floor/model.gltf');
471
471
  // gltf_sample('data/models/moicon/isiflow_Oct_15_21/0/model.gltf');
472
472
  // gltf_sample('moicon/29_Dec_2021_Nammo/1/model.gltf');
473
473
  // gltf_sample('moicon/29_Dec_2021_Nammo/1-onematerial/model.gltf');
@@ -546,6 +546,7 @@ function onWindowResize() {
546
546
  * @param {number} scale
547
547
  */
548
548
  function createScene(geometry, m1, scale) {
549
+
549
550
  geometry.computeVertexNormals();
550
551
 
551
552
 
@@ -798,7 +799,7 @@ function render() {
798
799
  // console.log(`patches:${active_patches.length}, polycount:${polycount}`);
799
800
  }
800
801
 
801
- window.document.body.addEventListener(MouseEvents.Move, ({ clientX, clientY }) => {
802
+ const raycast_handler = ({ clientX, clientY }) => {
802
803
  const direction = new Vector3();
803
804
 
804
805
  const viewport_size = new Vector2();
@@ -858,5 +859,7 @@ window.document.body.addEventListener(MouseEvents.Move, ({ clientX, clientY }) =
858
859
  if (hits.length > 0) {
859
860
  console.log(`HITS: ${hits.map(JSON.stringify).join(',')}`);
860
861
  }
861
- });
862
+ };
863
+
864
+ // window.document.body.addEventListener(MouseEvents.Move, raycast_handler);
862
865
 
@@ -125,7 +125,6 @@ export class VirtualGeometryBuilder {
125
125
  // get acl
126
126
  const acl = this.__acl;
127
127
 
128
- acl.initializeFromGeometry(micron_geometry);
129
128
 
130
129
  this.buildForMesh(
131
130
  object.instance_id,
@@ -159,6 +158,7 @@ export class VirtualGeometryBuilder {
159
158
  transform,
160
159
  apl
161
160
  ) {
161
+ apl.initializeFromGeometry(geometry);
162
162
 
163
163
  refinement_spec.build(transform, this.view_projection_matrix);
164
164
 
@@ -239,7 +239,6 @@ export class VirtualGeometryBuilder {
239
239
  // clear output
240
240
  this.output.clear();
241
241
 
242
- this.__info_enforced_node_splits = 0;
243
242
 
244
243
  const n = this.input_scene_length;
245
244
  const input_objects = this.input_scene;
@@ -194,8 +194,6 @@ export class ActivePatchList {
194
194
 
195
195
  const node = record.patch;
196
196
 
197
- // check if record needs to be split
198
- const prev_is_visible = record.getFlag(ActivePatchFlags.Visible);
199
197
 
200
198
  /*
201
199
  check if node is in view frustum
@@ -205,16 +203,11 @@ export class ActivePatchList {
205
203
 
206
204
  if (!in_view_frustum) {
207
205
  // outside of view frustum, cull
208
- if (prev_is_visible) {
209
- record.clearFlag(ActivePatchFlags.Visible);
210
- }
211
206
  record = record.link_next;
212
207
  continue;
213
208
  }
214
209
 
215
- if (!prev_is_visible) {
216
- record.setFlag(ActivePatchFlags.Visible);
217
- }
210
+ record.setFlag(ActivePatchFlags.Visible);
218
211
 
219
212
  /*
220
213
  scale error to projection space:
@@ -224,6 +217,7 @@ export class ActivePatchList {
224
217
  */
225
218
 
226
219
 
220
+ // check if record needs to be split
227
221
  if (node.lod > 0) {
228
222
 
229
223
  // not the lowest level of LOD, see if subdivision might be necessary
@@ -303,8 +303,8 @@ async function sample_scene_0(engine) {
303
303
  }
304
304
 
305
305
  // load_model('moicon/06_04_hapro/00-environment/model.gltf', -0.1);
306
- load_model_s('moicon/06_04_hapro/05-ground-floor/model.gltf');
307
- load_model_s('C:/git/moh/app/moicon/06_04_hapro/08-clickable-assets-new/model.gltf');
306
+ // load_model_s('moicon/06_04_hapro/05-ground-floor/model.gltf');
307
+ // load_model_s('C:/git/moh/app/moicon/06_04_hapro/08-clickable-assets-new/model.gltf');
308
308
  // load_model('moicon/06_04_hapro/02-bearers/model.gltf');
309
309
  // load_model('moicon/06_04_hapro/04-1st-floor/model.gltf');
310
310
 
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.34.44",
8
+ "version": "2.34.45",
9
9
  "dependencies": {
10
10
  "gl-matrix": "3.4.3",
11
11
  "fast-levenshtein": "2.0.6",