@woosh/meep-engine 2.43.22 → 2.43.24

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 (47) hide show
  1. package/core/geom/3d/tetrahedra/delaunay/compute_delaunay_tetrahedral_mesh.js +2 -2
  2. package/core/geom/3d/topology/struct/{BinaryElementPool.js → binary/BinaryElementPool.js} +7 -11
  3. package/core/geom/3d/topology/struct/{BinaryElementPool.spec.js → binary/BinaryElementPool.spec.js} +0 -0
  4. package/core/geom/3d/topology/struct/{BinaryTopology.js → binary/BinaryTopology.js} +123 -6
  5. package/core/geom/3d/topology/struct/{BinaryTopology.spec.js → binary/BinaryTopology.spec.js} +0 -0
  6. package/core/geom/3d/topology/struct/binary/io/OrderedEdge.js +66 -0
  7. package/core/geom/3d/topology/struct/binary/io/bt_index_geometry_to_topology.js +188 -0
  8. package/core/geom/3d/topology/struct/binary/io/bt_index_geometry_to_topology.spec.js +84 -0
  9. package/core/geom/3d/topology/struct/binary/io/bt_mesh_calc_edges.js +51 -0
  10. package/core/geom/3d/topology/struct/binary/io/create_edge.js +106 -0
  11. package/core/geom/3d/topology/struct/binary/io/get_or_create_edge_map.js +26 -0
  12. package/core/geom/3d/topology/struct/binary/query/bt_mesh_edge_has_vertex.js +16 -0
  13. package/core/geom/3d/topology/struct/binary/query/bt_mesh_edge_has_vertex.spec.js +15 -0
  14. package/core/geom/3d/topology/struct/binary/query/bt_mesh_edge_other_vertex.js +21 -0
  15. package/core/geom/3d/topology/struct/binary/query/bt_mesh_edge_other_vertex.spec.js +16 -0
  16. package/core/geom/3d/topology/struct/prototypeBinaryTopology.js +14 -14
  17. package/core/path/PATH_SEPARATOR.js +1 -0
  18. package/core/path/computeFileExtension.js +24 -0
  19. package/core/path/computeFileExtension.spec.js +13 -0
  20. package/core/path/computePathBase.js +21 -0
  21. package/core/path/computePathBase.spec.js +13 -0
  22. package/core/path/computePathDirectory.js +25 -0
  23. package/editor/Editor.js +3 -2
  24. package/editor/view/library/MeshLibraryView.js +1 -1
  25. package/engine/EngineHarness.js +25 -1
  26. package/engine/asset/guessAssetType.js +1 -1
  27. package/engine/asset/loaders/image/ImageRGBADataLoader.js +1 -1
  28. package/engine/asset/loaders/texture/TextureAssetLoader.js +1 -1
  29. package/engine/ecs/storage/BinaryBufferSerializer.js +7 -0
  30. package/engine/graphics/camera/camera_compute_distance_to_fit_length.js +5 -1
  31. package/engine/graphics/ecs/mesh-v2/render/adapters/AbstractRenderAdapter.js +33 -0
  32. package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +1 -0
  33. package/engine/graphics/material/composeCompile.js +3 -5
  34. package/engine/graphics/micron/plugin/GLTFAssetTransformer.js +1 -1
  35. package/engine/graphics/sh3/README.md +2 -0
  36. package/engine/graphics/sh3/path_tracer/PathTracer.js +0 -14
  37. package/engine/graphics/sh3/path_tracer/prototypePathTracer.js +11 -7
  38. package/engine/graphics/texture/cubemap/load_environment_map.js +1 -1
  39. package/engine/graphics/util/makeMeshPreviewScene.js +38 -26
  40. package/engine/network/RemoteController.js +138 -0
  41. package/engine/network/remoteEditor.js +36 -0
  42. package/package.json +1 -1
  43. package/view/elements/MeshPreview.js +5 -1
  44. package/core/FilePath.js +0 -73
  45. package/core/FilePath.spec.js +0 -25
  46. package/core/geom/3d/topology/struct/bt_index_geometry_to_topology.js +0 -329
  47. package/core/geom/3d/topology/struct/bt_index_geometry_to_topology.spec.js +0 -26
@@ -0,0 +1,106 @@
1
+ import { NULL_POINTER } from "../BinaryTopology.js";
2
+
3
+ /**
4
+ *
5
+ * @param {BinaryTopology} mesh
6
+ * @param {number} edge_from
7
+ * @param {number} edge_to
8
+ * @param {number} vertex
9
+ */
10
+ function edge_link_disk_forward(mesh, edge_from, edge_to, vertex) {
11
+ const from_v1 = mesh.edge_read_vertex1(edge_from);
12
+
13
+ let displaced_edge;
14
+
15
+ if (from_v1 === vertex) {
16
+ displaced_edge = mesh.edge_read_v1_disk_next(edge_from);
17
+
18
+ mesh.edge_write_v1_disk_next(edge_from, edge_to);
19
+
20
+ } else {
21
+ displaced_edge = mesh.edge_read_v2_disk_next(edge_from);
22
+
23
+ mesh.edge_write_v2_disk_next(edge_from, edge_to);
24
+ }
25
+
26
+ return displaced_edge;
27
+ }
28
+
29
+ function edge_link_disk_back(mesh, edge_from, edge_to, vertex) {
30
+ const from_v1 = mesh.edge_read_vertex1(edge_from);
31
+
32
+ let displaced_edge;
33
+
34
+ if (from_v1 === vertex) {
35
+ displaced_edge = mesh.edge_read_v1_disk_prev(edge_from);
36
+
37
+ mesh.edge_write_v1_disk_prev(edge_from, edge_to);
38
+
39
+ } else {
40
+ displaced_edge = mesh.edge_read_v2_disk_prev(edge_from);
41
+
42
+ mesh.edge_write_v2_disk_prev(edge_from, edge_to);
43
+ }
44
+
45
+ return displaced_edge;
46
+ }
47
+
48
+ /**
49
+ *
50
+ * @param {BinaryTopology} mesh
51
+ * @param {number} edge_source anchor edge, new edge is inserted after this one
52
+ * @param {number} edge_new edge that is being introduced
53
+ * @param {number} vertex
54
+ */
55
+ function edge_link_disk(mesh, edge_source, edge_new, vertex) {
56
+ const forward_link = edge_link_disk_forward(mesh, edge_source, edge_new, vertex);
57
+ edge_link_disk_forward(mesh, edge_new, forward_link, vertex);
58
+
59
+ edge_link_disk_back(mesh, forward_link, edge_new, vertex);
60
+ edge_link_disk_back(mesh, edge_new, edge_source, vertex);
61
+ }
62
+
63
+ /**
64
+ *
65
+ * @param {BinaryTopology} mesh
66
+ * @param {number} v0
67
+ * @param {number} v1
68
+ * @return {number}
69
+ */
70
+ export function create_edge(mesh, v0, v1) {
71
+ const edge_id = mesh.edges.allocate();
72
+
73
+ mesh.edge_write_vertex1(edge_id, v0);
74
+ mesh.edge_write_vertex2(edge_id, v1);
75
+
76
+ // initialize rest of the edge
77
+ mesh.edge_write_loop(edge_id, NULL_POINTER);
78
+
79
+ // process disk links
80
+ const first_v0_edge = mesh.vertex_read_edge(v0);
81
+
82
+ if (first_v0_edge !== NULL_POINTER) {
83
+ edge_link_disk(mesh, first_v0_edge, edge_id, v0);
84
+ } else {
85
+ // no edges attached yet, attach this one as the first
86
+ mesh.vertex_write_edge(v0, edge_id);
87
+ // link to self
88
+ mesh.edge_write_v1_disk_next(edge_id, edge_id);
89
+ mesh.edge_write_v1_disk_prev(edge_id, edge_id);
90
+ }
91
+
92
+ const first_v1_edge = mesh.vertex_read_edge(v1);
93
+
94
+ if (first_v1_edge !== NULL_POINTER) {
95
+
96
+ edge_link_disk(mesh, first_v1_edge, edge_id, v1);
97
+
98
+ } else {
99
+ // no edges attached yet, attach this one as the first
100
+ mesh.vertex_write_edge(v1, edge_id);
101
+ // link to self
102
+ mesh.edge_write_v2_disk_next(edge_id, edge_id);
103
+ mesh.edge_write_v2_disk_prev(edge_id, edge_id);
104
+ }
105
+ return edge_id;
106
+ }
@@ -0,0 +1,26 @@
1
+ import { OrderedEdge } from "./OrderedEdge.js";
2
+ import { create_edge } from "./create_edge.js";
3
+
4
+ /**
5
+ *
6
+ * @param {number} v0
7
+ * @param {number} v1
8
+ * @param {HashMap<OrderedEdge,number>} map
9
+ * @param {BinaryTopology} mesh
10
+ */
11
+ function get_or_create_edge_map(v0, v1, map, mesh) {
12
+ const scratch_ordered_edge = new OrderedEdge(v0, v1);
13
+
14
+ const existing = map.get(scratch_ordered_edge);
15
+
16
+ if (existing !== undefined) {
17
+ return existing;
18
+ }
19
+
20
+ // doesn't exist - create
21
+ const edge_id = create_edge(mesh, v0, v1);
22
+
23
+ map.set(scratch_ordered_edge, edge_id);
24
+
25
+ return edge_id;
26
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ *
3
+ * @param {BinaryTopology} mesh
4
+ * @param {number} edge_id
5
+ * @param {number} vertex_id
6
+ * @returns {boolean}
7
+ */
8
+ export function bt_mesh_edge_has_vertex(mesh, edge_id, vertex_id) {
9
+ const v1 = mesh.edge_read_vertex1(edge_id);
10
+
11
+ if (v1 === vertex_id) {
12
+ return true;
13
+ }
14
+
15
+ return mesh.edge_read_vertex2(edge_id) === vertex_id;
16
+ }
@@ -0,0 +1,15 @@
1
+ import { BinaryTopology } from "../BinaryTopology.js";
2
+ import { bt_mesh_edge_has_vertex } from "./bt_mesh_edge_has_vertex.js";
3
+
4
+ test('main', () => {
5
+ const mesh = new BinaryTopology();
6
+
7
+ const edge = mesh.edges.allocate();
8
+
9
+ mesh.edge_write_vertex1(edge, 7);
10
+ mesh.edge_write_vertex2(edge, 3);
11
+
12
+ expect(bt_mesh_edge_has_vertex(mesh, edge, 7)).toBe(true);
13
+ expect(bt_mesh_edge_has_vertex(mesh, edge, 3)).toBe(true);
14
+ expect(bt_mesh_edge_has_vertex(mesh, edge, 1)).toBe(false);
15
+ });
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Returns other vertex ID
3
+ * Assumes that given vertex belongs to this edge
4
+ * Assumes that given edge exists
5
+ * @param {BinaryTopology} mesh
6
+ * @param {number} edge_id edge ID
7
+ * @param {number} vertex_id
8
+ * @returns {number}
9
+ */
10
+ export function bt_mesh_edge_other_vertex(mesh, edge_id, vertex_id) {
11
+
12
+ const v1 = mesh.edge_read_vertex1(edge_id);
13
+ const v2 = mesh.edge_read_vertex2(edge_id);
14
+
15
+ if (v1 === vertex_id) {
16
+ return v2;
17
+ } else {
18
+ return v1;
19
+ }
20
+
21
+ }
@@ -0,0 +1,16 @@
1
+ import { BinaryTopology } from "../BinaryTopology.js";
2
+ import { bt_mesh_edge_other_vertex } from "./bt_mesh_edge_other_vertex.js";
3
+
4
+ test('main', () => {
5
+
6
+ const mesh = new BinaryTopology();
7
+
8
+ const edge = mesh.edges.allocate();
9
+
10
+ mesh.edge_write_vertex1(edge, 7);
11
+ mesh.edge_write_vertex2(edge, 3);
12
+
13
+ expect(bt_mesh_edge_other_vertex(mesh, edge, 7)).toBe(3);
14
+ expect(bt_mesh_edge_other_vertex(mesh, edge, 3)).toBe(7);
15
+
16
+ });
@@ -1,7 +1,7 @@
1
1
  import { PLYLoader } from "three/examples/jsm/loaders/PLYLoader.js";
2
2
  import { noop } from "../../../../function/Functions.js";
3
- import { bt_index_geometry_to_topology } from "./bt_index_geometry_to_topology.js";
4
- import { BinaryTopology } from "./BinaryTopology.js";
3
+ import { bt_index_geometry_to_topology } from "./binary/io/bt_index_geometry_to_topology.js";
4
+ import { BinaryTopology } from "./binary/BinaryTopology.js";
5
5
  import {
6
6
  compute_buffer_geometry_byte_size
7
7
  } from "../../../../../engine/graphics/geometry/buffered/compute_buffer_geometry_byte_size.js";
@@ -18,27 +18,27 @@ function promise_ply(url) {
18
18
 
19
19
  async function main() {
20
20
 
21
- // const url = "data/models/stanford/Lucy100k.ply";
22
- const url = "data/models/stanford/dragon_recon/dragon_vrip.ply";
21
+ const url = "data/models/stanford/Lucy100k.ply";
22
+ // const url = "data/models/stanford/dragon_recon/dragon_vrip.ply";
23
23
  const lucy_geom = await promise_ply(url);
24
24
 
25
25
  const mesh = new BinaryTopology();
26
+ const topoMesh = new TopoMesh();
26
27
 
27
28
  const positions_array = lucy_geom.getAttribute('position').array;
28
29
  const index_array = lucy_geom.getIndex().array;
29
30
 
30
31
 
31
- const topoMesh = new TopoMesh();
32
-
33
- console.time('topo build - obj');
34
- topoMesh.build(positions_array, index_array);
35
- console.timeEnd('topo build - obj');
36
-
37
- // console.time('topo build - bin');
38
- console.profile('topo build - bin');
32
+ console.time('topo build - bin');
33
+ // console.profile('topo build - bin');
39
34
  bt_index_geometry_to_topology(mesh, index_array, positions_array);
40
- console.profileEnd('topo build - bin');
41
- // console.timeEnd('topo build - bin');
35
+ // console.profileEnd('topo build - bin');
36
+ console.timeEnd('topo build - bin');
37
+
38
+ //
39
+ // console.time('topo build - obj');
40
+ // topoMesh.build(positions_array, index_array);
41
+ // console.timeEnd('topo build - obj');
42
42
 
43
43
  mesh.trim();
44
44
 
@@ -0,0 +1 @@
1
+ export const PATH_SEPARATOR = '/';
@@ -0,0 +1,24 @@
1
+ import { computePathBase } from "./computePathBase.js";
2
+
3
+ /**
4
+ *
5
+ * @param {string} path
6
+ * @returns {String|null}
7
+ */
8
+ export function computeFileExtension(path) {
9
+ if (typeof path !== "string") {
10
+ throw new Error('path is not a string');
11
+ }
12
+
13
+ //get base
14
+ const pathBase = computePathBase(path);
15
+
16
+ const lastDotIndex = pathBase.lastIndexOf('.');
17
+
18
+ if (lastDotIndex !== -1) {
19
+ return pathBase.substring(lastDotIndex + 1);
20
+ } else {
21
+ //no extension
22
+ return null;
23
+ }
24
+ }
@@ -0,0 +1,13 @@
1
+ import { computeFileExtension } from "./computeFileExtension.js";
2
+
3
+ test('extract extension of cat.txt', () => {
4
+ expect(computeFileExtension('cat.txt')).toEqual('txt');
5
+ });
6
+
7
+ test('extract extension of ../hmm/cat.txt', () => {
8
+ expect(computeFileExtension('../hmm/cat.txt')).toEqual('txt');
9
+ });
10
+
11
+ test('extract extension of empty string', () => {
12
+ expect(computeFileExtension('')).toBeNull();
13
+ });
@@ -0,0 +1,21 @@
1
+ import { PATH_SEPARATOR } from "./PATH_SEPARATOR.js";
2
+
3
+ /**
4
+ * Strips all directories from the path.
5
+ * @example 'a/b/c' -> 'c'
6
+ * @param {string} path
7
+ * @returns {string}
8
+ */
9
+ export function computePathBase(path) {
10
+ if (typeof path !== "string") {
11
+ throw new Error('path is not a string');
12
+ }
13
+
14
+ const lastSlashIndex = path.lastIndexOf(PATH_SEPARATOR);
15
+
16
+ if (lastSlashIndex !== -1) {
17
+ return path.substring(lastSlashIndex + 1);
18
+ } else {
19
+ return path;
20
+ }
21
+ }
@@ -0,0 +1,13 @@
1
+ import { computePathBase } from "./computePathBase.js";
2
+
3
+ test('extract base path of empty string', () => {
4
+ expect(computePathBase('')).toBe('');
5
+ });
6
+
7
+ test('extract base path of hello', () => {
8
+ expect(computePathBase('hello')).toBe('hello');
9
+ });
10
+
11
+ test('extract base path of hello/there/world', () => {
12
+ expect(computePathBase('hello/there/world')).toBe('world');
13
+ });
@@ -0,0 +1,25 @@
1
+ import { PATH_SEPARATOR } from "./PATH_SEPARATOR.js";
2
+
3
+ /**
4
+ * Returns the directory name of a path, similar to the Unix dirname command.
5
+ * @param {string} path
6
+ * @return {string}
7
+ */
8
+ export function computePathDirectory(path) {
9
+ if (typeof path !== "string") {
10
+ throw new Error('path is not a string');
11
+ }
12
+
13
+ let lastSlashIndex = path.lastIndexOf(PATH_SEPARATOR);
14
+
15
+ //rewind in case of trailing slashes
16
+ while (lastSlashIndex > 0 && path.charAt(lastSlashIndex - 1) === PATH_SEPARATOR) {
17
+ lastSlashIndex--;
18
+ }
19
+
20
+ if (lastSlashIndex !== -1) {
21
+ return path.substring(0, lastSlashIndex);
22
+ } else {
23
+ return path;
24
+ }
25
+ }
package/editor/Editor.js CHANGED
@@ -71,8 +71,8 @@ import { ObservedIntegerEditor } from "./ecs/component/editors/ObservedIntegerEd
71
71
 
72
72
  import '../../../../css/editor/EntityEditorView.scss';
73
73
  import '../../../../css/editor/EditorView.scss';
74
- import {ParameterTrackSet} from "../engine/graphics/particles/particular/engine/parameter/ParameterTrackSet.js";
75
- import {ParameterTrackSetEditor} from "./ecs/component/editors/ecs/ParameterTrackSetEditor.js";
74
+ import { ParameterTrackSet } from "../engine/graphics/particles/particular/engine/parameter/ParameterTrackSet.js";
75
+ import { ParameterTrackSetEditor } from "./ecs/component/editors/ecs/ParameterTrackSetEditor.js";
76
76
 
77
77
  /**
78
78
  * @template T
@@ -485,6 +485,7 @@ function Editor() {
485
485
  resetSoundEmitterTracks(dataset);
486
486
 
487
487
  const serializer = new BinaryBufferSerializer();
488
+ serializer.engine = self.engine;
488
489
  serializer.registry = engine.binarySerializationRegistry;
489
490
 
490
491
  const state = new EncodingBinaryBuffer();
@@ -2,13 +2,13 @@ import View from "../../../view/View.js";
2
2
  import { makeModelView } from "../../../view/renderModel.js";
3
3
  import Vector2 from "../../../core/geom/Vector2.js";
4
4
  import domify from "../../../view/DOM.js";
5
- import { computePathBase } from "../../../core/FilePath.js";
6
5
  import LabelView from "../../../view/common/LabelView.js";
7
6
  import List from "../../../core/collection/list/List.js";
8
7
  import AABB2 from "../../../core/geom/AABB2.js";
9
8
  import { DragEvents } from "../../../engine/input/devices/events/DragEvents.js";
10
9
  import { MouseEvents } from "../../../engine/input/devices/events/MouseEvents.js";
11
10
  import { TouchEvents } from "../../../engine/input/devices/events/TouchEvents.js";
11
+ import { computePathBase } from "../../../core/path/computePathBase.js";
12
12
 
13
13
 
14
14
  const ICON_SIZE = 50;
@@ -29,6 +29,8 @@ import { noop } from "../core/function/Functions.js";
29
29
  import SoundListenerSystem from "./sound/ecs/SoundListenerSystem.js";
30
30
  import SoundListener from "./sound/ecs/SoundListener.js";
31
31
  import { getURLHash } from "./platform/GetURLHash.js";
32
+ import Stats from "three/examples/jsm/libs/stats.module.js";
33
+ import EmptyView from "../view/elements/EmptyView.js";
32
34
 
33
35
  /**
34
36
  *
@@ -68,6 +70,22 @@ export class EngineHarness {
68
70
  this.p = null;
69
71
  }
70
72
 
73
+ /**
74
+ *
75
+ * @param {Engine} engine
76
+ */
77
+ static addFpsCounter(engine) {
78
+ const stats = new Stats();
79
+
80
+ engine.graphics.on.postRender.add(stats.update, stats);
81
+
82
+ const view = new EmptyView({
83
+ el: stats.domElement
84
+ });
85
+
86
+ engine.viewStack.addChild(view);
87
+ }
88
+
71
89
  /**
72
90
  * @param {(config:EngineConfiguration,engine:Engine)=>*} configuration
73
91
  * @param {boolean} [enable_localization] Whether or not to load localization data
@@ -228,6 +246,7 @@ export class EngineHarness {
228
246
  * @param {boolean} [cameraController=true]
229
247
  * @param {boolean} [cameraAutoClip]
230
248
  * @param shadowmapResolution
249
+ * @param showFps
231
250
  */
232
251
  static async buildBasics({
233
252
  engine,
@@ -246,9 +265,14 @@ export class EngineHarness {
246
265
  cameraFarDistance,
247
266
  cameraController = true,
248
267
  cameraAutoClip = false,
249
- shadowmapResolution
268
+ shadowmapResolution,
269
+ showFps = true
250
270
  }) {
251
271
 
272
+ if (showFps) {
273
+ EngineHarness.addFpsCounter(engine);
274
+ }
275
+
252
276
  if (enableLights) {
253
277
  await EngineHarness.buildLights({ engine: engine, shadowmapResolution });
254
278
  }
@@ -1,4 +1,4 @@
1
- import { computeFileExtension } from "../../core/FilePath.js";
1
+ import { computeFileExtension } from "../../core/path/computeFileExtension.js";
2
2
 
3
3
  /**
4
4
  *
@@ -1,5 +1,4 @@
1
1
  import { AssetLoader } from "../AssetLoader.js";
2
- import { computeFileExtension } from "../../../../core/FilePath.js";
3
2
  import { GameAssetType } from "../../GameAssetType.js";
4
3
  import { convertTexture2Sampler2D } from "../../../graphics/texture/sampler/convertTexture2Sampler2D.js";
5
4
  import { ImageRGBADataAsset } from "./ImageRGBADataAsset.js";
@@ -7,6 +6,7 @@ import { ArrayBufferLoader } from "../ArrayBufferLoader.js";
7
6
  import { CodecWithFallback } from "./codec/CodecWithFallback.js";
8
7
  import { ThreadedImageDecoder } from "./codec/ThreadedImageDecoder.js";
9
8
  import { NativeImageDecoder } from "./codec/NativeImageDecoder.js";
9
+ import { computeFileExtension } from "../../../../core/path/computeFileExtension.js";
10
10
 
11
11
  const ASSET_TYPE_ARRAY_BUFFER = "arraybuffer";
12
12
 
@@ -1,7 +1,7 @@
1
1
  import { AssetLoader } from "../AssetLoader.js";
2
- import { computeFileExtension } from "../../../../core/FilePath.js";
3
2
  import { loadDDSTexture } from "./loadDDSTexture.js";
4
3
  import { loadStandardImageTexture } from "./loadStandardImageTexture.js";
4
+ import { computeFileExtension } from "../../../../core/path/computeFileExtension.js";
5
5
 
6
6
  export class TextureAssetLoader extends AssetLoader {
7
7
  load(path, success, failure, progress) {
@@ -55,6 +55,11 @@ class BinaryBufferSerializer {
55
55
  * @type {BinarySerializationRegistry}
56
56
  */
57
57
  this.registry = null;
58
+ /**
59
+ *
60
+ * @type {Engine|null}
61
+ */
62
+ this.engine = null;
58
63
  }
59
64
 
60
65
  /**
@@ -92,6 +97,8 @@ class BinaryBufferSerializer {
92
97
 
93
98
  let i;
94
99
 
100
+ const engine = this.engine;
101
+
95
102
  for (i = 0; i < numSerializableTypes; i++) {
96
103
 
97
104
  const componentType = serializableComponentTypes[i];
@@ -8,9 +8,13 @@ import { assert } from "../../../core/assert.js";
8
8
  */
9
9
  export function camera_compute_distance_to_fit_length(length, fov) {
10
10
  assert.isNumber(length, 'length');
11
+ assert.greaterThanOrEqual(length, 0, 'length < 0');
12
+
11
13
  assert.isNumber(fov, 'fov');
12
14
  assert.greaterThan(fov, 0, 'fov <= 0');
13
15
  assert.lessThan(fov, Math.PI, 'fov >= pi');
14
16
 
15
- return Math.abs((length / 2) / Math.sin(fov / 2));
17
+ const signed_distance = (length * 0.5) / Math.tan(fov * 0.5);
18
+
19
+ return Math.abs(signed_distance);
16
20
  }
@@ -1,3 +1,29 @@
1
+ import { array_quick_sort_by_comparator } from "../../../../../../core/collection/array/arrayQuickSort.js";
2
+
3
+ /**
4
+ *
5
+ * @param {THREE.Object3D} a
6
+ * @param {THREE.Object3D} b
7
+ * @returns {number}
8
+ */
9
+ function compare_by_material(a, b) {
10
+
11
+ const a_mat = a.material;
12
+ const b_mat = b.material;
13
+
14
+ if (a_mat === b_mat) {
15
+ return 0;
16
+ }
17
+
18
+ if (a_mat === undefined) {
19
+ return 1;
20
+ } else if (b_mat === undefined) {
21
+ return -1;
22
+ }
23
+
24
+ return a_mat.id - b_mat.id;
25
+ }
26
+
1
27
  export class AbstractRenderAdapter {
2
28
  constructor() {
3
29
 
@@ -16,6 +42,13 @@ export class AbstractRenderAdapter {
16
42
  this.__objects = [];
17
43
  }
18
44
 
45
+ /**
46
+ * Sorting objects by material will help reduce context switching and number of graphics API calls
47
+ */
48
+ sort_by_material() {
49
+ array_quick_sort_by_comparator(this.__objects, compare_by_material, null, 0, this.__object_count - 1);
50
+ }
51
+
19
52
  /**
20
53
  *
21
54
  * @param {THREE.BufferGeometry} geometry
@@ -110,6 +110,7 @@ async function main(engine) {
110
110
  // sg.draw_method = 2;
111
111
  // sg.draw_method = DRAW_METHOD_INSTANCED;
112
112
  // sg.draw_method = random() > 0.5 ? DRAW_METHOD_INSTANCED : 2;
113
+ sg.setFlag(ShadedGeometryFlags.DrawMethodLocked);
113
114
  sg.clearFlag(ShadedGeometryFlags.CastShadow | ShadedGeometryFlags.ReceiveShadow);
114
115
 
115
116
  new EntityBuilder()
@@ -13,6 +13,7 @@ export function composeCompile(previous, next) {
13
13
  let t1_cache = cache.get(previous);
14
14
 
15
15
  if (t1_cache === undefined) {
16
+ // no caches starting from previous
16
17
  t1_cache = new WeakMap();
17
18
 
18
19
  cache.set(previous, t1_cache);
@@ -21,14 +22,11 @@ export function composeCompile(previous, next) {
21
22
  let result_function = t1_cache.get(next);
22
23
 
23
24
  if (result_function === undefined) {
25
+ // no matching function found for pair, let's create it
26
+
24
27
  // we create a custom function just to be able to name our function, this is because of how three.js caches onBeforeCompile by just turning it into the string, so changing the function name will result in altered cache key
25
28
  const f = new Function('previous, next', `return function f${id_counter++}(a,b,c,d){ previous(a,b,c,d); next(a,b,c,d); };`);
26
29
 
27
- // result_function = function (a, b, c, d) {
28
- // previous(a, b, c, d);
29
- // next(a, b, c, d);
30
- // };
31
- //
32
30
 
33
31
  result_function = f(previous, next);
34
32
 
@@ -1,5 +1,4 @@
1
1
  import { AssetTransformer } from "../../../asset/AssetTransformer.js";
2
- import { computePathDirectory } from "../../../../core/FilePath.js";
3
2
  import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
4
3
  import { MicronGeometry } from "../format/MicronGeometry.js";
5
4
  import { MICRON_GEOMETRY_FIELD } from "../MICRON_GEOMETRY_FIELD.js";
@@ -12,6 +11,7 @@ import {
12
11
  deserialize_geometry_collection
13
12
  } from "../format/serialization/collection/geometry_collection_serialization.js";
14
13
  import { GLTF_MICRON_ID_FIELD } from "./GLTF_MICRON_ID_FIELD.js";
14
+ import { computePathDirectory } from "../../../../core/path/computePathDirectory.js";
15
15
 
16
16
  export const ASSET_TYPE_ARRAY_BUFFER = "arraybuffer";
17
17
 
@@ -3,3 +3,5 @@ Path tracing ideas:
3
3
  * [smallpt](https://www.kevinbeason.com/smallpt/) (100 line c implementation of path tracer)
4
4
  * [three path tracer](https://github.com/gkjohnson/three-gpu-pathtracer)
5
5
  * http://blog.hvidtfeldts.net/index.php/2015/01/path-tracing-3d-fractals/
6
+ * [Global Illumination and Path Tracing](https://www.scratchapixel.com/lessons/3d-basic-rendering/global-illumination-path-tracing/global-illumination-path-tracing-practical-implementation)
7
+ * [Path Tracing, by Steve Rotenberg](https://cseweb.ucsd.edu/classes/sp17/cse168-a/CSE168_08_PathTracing.pdf)
@@ -20,7 +20,6 @@ import {
20
20
  UnsignedByteType
21
21
  } from "three";
22
22
  import { linear_to_sRGB } from "../../../../core/color/linear_to_sRGB.js";
23
- import { random_in_hemisphere } from "./random_in_hemisphere.js";
24
23
  import { sample_triangle_attribute } from "./sample_triangle_attribute.js";
25
24
  import { vec3_uint8_to_float } from "./vec3_uint8_to_float.js";
26
25
  import { apply_texture_clamping_to_coordinate } from "./apply_texture_clamping_to_coordinate.js";
@@ -527,10 +526,6 @@ export class PathTracer {
527
526
  break;
528
527
  }
529
528
 
530
-
531
- // irradiance[0] += m;
532
- // irradiance[1] += m;
533
- // irradiance[2] += m;
534
529
  this.sample_material(tmp_0, trace_result);
535
530
 
536
531
  // adjust normal on the hit
@@ -541,7 +536,6 @@ export class PathTracer {
541
536
  array_copy(trace_result, 0, _ray_0, 0, 3);
542
537
 
543
538
  getBiasedNormalSample(_ray_0, 3, tmp_0, 3, 1, random);
544
- // random_in_hemisphere(random, _ray_0, 3, tmp_0, 3);
545
539
 
546
540
  // accumulate
547
541
  vec3.multiply(irradiance, irradiance, tmp_0);
@@ -556,14 +550,6 @@ export class PathTracer {
556
550
  vec3.multiply(irradiance, irradiance, tmp_1);
557
551
  }
558
552
 
559
- //
560
- // if (got_emission === false) {
561
- // // no light source was hit, propagate shadow(darkness) along the ray
562
- // irradiance[0] = 0;
563
- // irradiance[1] = 0;
564
- // irradiance[2] = 0;
565
- // }
566
-
567
553
  array_copy(irradiance, 0, out, 0, 3);
568
554
  }
569
555
  }