@woosh/meep-engine 2.35.10 → 2.35.12
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.
- package/core/binary/BinaryBuffer.js +65 -18
- package/engine/graphics/ecs/camera/Camera.js +1 -1
- package/engine/graphics/ecs/camera/CameraSystem.js +2 -2
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +8 -2
- package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +19 -4
- package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +1 -1
- package/engine/graphics/micron/plugin/shaded_geometry/MicronShadedGeometryRenderAdapter.js +45 -3
- package/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +1 -1
- package/engine/graphics/micron/render/v1/MaterialContext.js +1 -11
- package/engine/graphics/micron/render/v1/MaterialVertexSpec.js +55 -2
- package/engine/graphics/micron/render/v1/MicronRenderContext.js +25 -13
- package/engine/graphics/micron/render/v1/VGThreeRenderer.js +13 -1
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* @enum {boolean}
|
|
4
4
|
*/
|
|
5
5
|
import { assert } from "../assert.js";
|
|
6
|
+
import { array_copy } from "../collection/array/copyArray.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
*
|
|
@@ -30,17 +31,50 @@ function BinaryBuffer() {
|
|
|
30
31
|
*/
|
|
31
32
|
this.endianness = EndianType.BigEndian;
|
|
32
33
|
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @type {number}
|
|
37
|
+
*/
|
|
33
38
|
this.position = 0;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
*
|
|
42
|
+
* @type {number}
|
|
43
|
+
*/
|
|
34
44
|
this.length = 0;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
*
|
|
48
|
+
* @type {number}
|
|
49
|
+
*/
|
|
35
50
|
this.capacity = 0;
|
|
36
51
|
|
|
37
52
|
/**
|
|
38
53
|
*
|
|
39
54
|
* @type {ArrayBuffer}
|
|
55
|
+
* @private
|
|
40
56
|
*/
|
|
41
57
|
this.data = new ArrayBuffer(0);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
*
|
|
61
|
+
* @type {DataView}
|
|
62
|
+
* @private
|
|
63
|
+
*/
|
|
42
64
|
this.dataView = new DataView(this.data);
|
|
43
65
|
|
|
66
|
+
/**
|
|
67
|
+
*
|
|
68
|
+
* @type {Uint8Array}
|
|
69
|
+
* @private
|
|
70
|
+
*/
|
|
71
|
+
this.__data_uint8 = new Uint8Array(0);
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
*
|
|
75
|
+
* @type {number}
|
|
76
|
+
* @private
|
|
77
|
+
*/
|
|
44
78
|
this.__growFactor = 1.1;
|
|
45
79
|
}
|
|
46
80
|
|
|
@@ -50,6 +84,7 @@ function BinaryBuffer() {
|
|
|
50
84
|
BinaryBuffer.prototype.fromArrayBuffer = function (arrayBuffer) {
|
|
51
85
|
this.data = arrayBuffer;
|
|
52
86
|
this.dataView = new DataView(arrayBuffer);
|
|
87
|
+
this.__data_uint8 = new Uint8Array(arrayBuffer);
|
|
53
88
|
|
|
54
89
|
this.capacity = arrayBuffer.byteLength;
|
|
55
90
|
//assume that all the data is useful
|
|
@@ -85,7 +120,7 @@ BinaryBuffer.prototype.trim = function () {
|
|
|
85
120
|
* @param {number} capacity
|
|
86
121
|
*/
|
|
87
122
|
BinaryBuffer.prototype.setCapacity = function (capacity) {
|
|
88
|
-
const oldData =
|
|
123
|
+
const oldData = this.__data_uint8;
|
|
89
124
|
const newData = new Uint8Array(capacity);
|
|
90
125
|
|
|
91
126
|
//copy old data
|
|
@@ -93,7 +128,7 @@ BinaryBuffer.prototype.setCapacity = function (capacity) {
|
|
|
93
128
|
newData.set(oldData.subarray(0, copyLength), 0);
|
|
94
129
|
|
|
95
130
|
this.data = newData.buffer;
|
|
96
|
-
|
|
131
|
+
this.__data_uint8 = newData;
|
|
97
132
|
this.dataView = new DataView(this.data);
|
|
98
133
|
|
|
99
134
|
this.capacity = capacity;
|
|
@@ -680,11 +715,11 @@ BinaryBuffer.prototype.writeUint32LE = function (value) {
|
|
|
680
715
|
/**
|
|
681
716
|
*
|
|
682
717
|
* @param {Uint8Array|Uint8ClampedArray} array
|
|
683
|
-
* @param {number}
|
|
718
|
+
* @param {number} source_offset
|
|
684
719
|
* @param {number} length
|
|
685
720
|
*/
|
|
686
|
-
BinaryBuffer.prototype.writeBytes = function (array,
|
|
687
|
-
const source_end =
|
|
721
|
+
BinaryBuffer.prototype.writeBytes = function (array, source_offset, length) {
|
|
722
|
+
const source_end = source_offset + length;
|
|
688
723
|
assert.greaterThanOrEqual(array.length, source_end, 'source array underflow');
|
|
689
724
|
|
|
690
725
|
const targetAddress = this.position;
|
|
@@ -693,18 +728,21 @@ BinaryBuffer.prototype.writeBytes = function (array, sourceOffset, length) {
|
|
|
693
728
|
|
|
694
729
|
this.ensureCapacity(end);
|
|
695
730
|
|
|
696
|
-
|
|
731
|
+
if (source_offset === 0 && array.length === length) {
|
|
732
|
+
// copying entire source array
|
|
697
733
|
|
|
698
|
-
|
|
734
|
+
this.__data_uint8.set(array, targetAddress);
|
|
735
|
+
|
|
736
|
+
} else if (typeof array.subarray === "function") {
|
|
699
737
|
// typed array, use "subarray" method
|
|
700
738
|
|
|
701
|
-
|
|
739
|
+
this.__data_uint8.set(array.subarray(source_offset, source_end), targetAddress);
|
|
702
740
|
|
|
703
741
|
} else {
|
|
704
742
|
// not a typed array, copy byte by byte manually
|
|
705
743
|
|
|
706
744
|
for (let i = 0; i < length; i++) {
|
|
707
|
-
|
|
745
|
+
this.__data_uint8[targetAddress + i] = array[source_offset + i];
|
|
708
746
|
}
|
|
709
747
|
|
|
710
748
|
}
|
|
@@ -714,14 +752,23 @@ BinaryBuffer.prototype.writeBytes = function (array, sourceOffset, length) {
|
|
|
714
752
|
|
|
715
753
|
/**
|
|
716
754
|
*
|
|
717
|
-
* @param {Uint8Array}
|
|
718
|
-
* @param {number}
|
|
755
|
+
* @param {Uint8Array} destination
|
|
756
|
+
* @param {number} destination_offset
|
|
719
757
|
* @param {number} length
|
|
720
758
|
*/
|
|
721
|
-
BinaryBuffer.prototype.readBytes = function (
|
|
722
|
-
const
|
|
723
|
-
|
|
724
|
-
|
|
759
|
+
BinaryBuffer.prototype.readBytes = function (destination, destination_offset, length) {
|
|
760
|
+
const source_position = this.position;
|
|
761
|
+
|
|
762
|
+
const end = source_position + length;
|
|
763
|
+
|
|
764
|
+
const uint8 = this.__data_uint8;
|
|
765
|
+
|
|
766
|
+
if (length < 128) {
|
|
767
|
+
// small copy
|
|
768
|
+
array_copy(uint8, source_position, destination, destination_offset, length);
|
|
769
|
+
} else {
|
|
770
|
+
destination.set(uint8.subarray(source_position, end), destination_offset);
|
|
771
|
+
}
|
|
725
772
|
|
|
726
773
|
this.position = end;
|
|
727
774
|
};
|
|
@@ -764,7 +811,7 @@ BinaryBuffer.prototype.writeUTF8String = function (string) {
|
|
|
764
811
|
|
|
765
812
|
this.ensureCapacity(tlen + at);
|
|
766
813
|
|
|
767
|
-
let target =
|
|
814
|
+
let target = this.__data_uint8; // ... but at 8 byte offset
|
|
768
815
|
|
|
769
816
|
|
|
770
817
|
while (pos < len) {
|
|
@@ -791,7 +838,7 @@ BinaryBuffer.prototype.writeUTF8String = function (string) {
|
|
|
791
838
|
|
|
792
839
|
this.ensureCapacity(tlen + startPosition);
|
|
793
840
|
|
|
794
|
-
target =
|
|
841
|
+
target = this.__data_uint8;
|
|
795
842
|
}
|
|
796
843
|
|
|
797
844
|
if ((value & 0xffffff80) === 0) { // 1-byte
|
|
@@ -851,7 +898,7 @@ BinaryBuffer.prototype.readUTF8String = function () {
|
|
|
851
898
|
return undefined;
|
|
852
899
|
}
|
|
853
900
|
|
|
854
|
-
const bytes =
|
|
901
|
+
const bytes = this.__data_uint8;
|
|
855
902
|
|
|
856
903
|
|
|
857
904
|
let result = "";
|
|
@@ -297,7 +297,7 @@ export class CameraSystem extends System {
|
|
|
297
297
|
* @param {Camera} c
|
|
298
298
|
*/
|
|
299
299
|
function visitCameraEntity(c) {
|
|
300
|
-
if (c.object
|
|
300
|
+
if (c.object === null) {
|
|
301
301
|
return;
|
|
302
302
|
}
|
|
303
303
|
|
|
@@ -305,7 +305,7 @@ export class CameraSystem extends System {
|
|
|
305
305
|
return;
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
-
if (c.autoClip) {
|
|
308
|
+
if (c.autoClip === true) {
|
|
309
309
|
autoSetClippingPlanes(c, layers);
|
|
310
310
|
} else {
|
|
311
311
|
c.object.far = c.clip_far;
|
|
@@ -313,13 +313,19 @@ export class ShadedGeometrySystem extends System {
|
|
|
313
313
|
const local_direction_x = scratch_m4[0] * direction_x + scratch_m4[4] * direction_y + scratch_m4[8] * direction_z;
|
|
314
314
|
const local_direction_y = scratch_m4[1] * direction_x + scratch_m4[5] * direction_y + scratch_m4[9] * direction_z;
|
|
315
315
|
const local_direction_z = scratch_m4[2] * direction_x + scratch_m4[6] * direction_y + scratch_m4[10] * direction_z;
|
|
316
|
-
|
|
316
|
+
|
|
317
|
+
const local_direction_magnitude = Math.hypot(local_direction_x, local_direction_y, local_direction_z);
|
|
318
|
+
const local_direction_magnitude_inverse = 1 / local_direction_magnitude;
|
|
319
|
+
|
|
320
|
+
const local_direction_normalized_x = local_direction_x * local_direction_magnitude_inverse;
|
|
321
|
+
const local_direction_normalized_y = local_direction_y * local_direction_magnitude_inverse;
|
|
322
|
+
const local_direction_normalized_z = local_direction_z * local_direction_magnitude_inverse;
|
|
317
323
|
|
|
318
324
|
const geometry_hit_found = GeometrySpatialQueryAccelerator.INSTANCE.queryRaycastNearest_primitive(
|
|
319
325
|
scratch_point,
|
|
320
326
|
sg.geometry,
|
|
321
327
|
local_origin_x, local_origin_y, local_origin_z,
|
|
322
|
-
|
|
328
|
+
local_direction_normalized_x, local_direction_normalized_y, local_direction_normalized_z
|
|
323
329
|
);
|
|
324
330
|
|
|
325
331
|
if (!geometry_hit_found) {
|
|
@@ -20,6 +20,9 @@ import { randomFromArray } from "../../../../../core/math/random/randomFromArray
|
|
|
20
20
|
import { BehaviorComponent } from "../../../../intelligence/behavior/ecs/BehaviorComponent.js";
|
|
21
21
|
import { OrbitingBehavior } from "../../../../../../model/game/util/behavior/OrbitingBehavior.js";
|
|
22
22
|
import { BehaviorSystem } from "../../../../intelligence/behavior/ecs/BehaviorSystem.js";
|
|
23
|
+
import { MicronShadedGeometryRenderAdapter } from "../../../micron/plugin/shaded_geometry/MicronShadedGeometryRenderAdapter.js";
|
|
24
|
+
import { MicronRenderContext } from "../../../micron/render/v1/MicronRenderContext.js";
|
|
25
|
+
import { randomIntegerBetween } from "../../../../../core/math/random/randomIntegerBetween.js";
|
|
23
26
|
|
|
24
27
|
const eh = new EngineHarness();
|
|
25
28
|
|
|
@@ -50,7 +53,17 @@ async function main(engine) {
|
|
|
50
53
|
|
|
51
54
|
const em = engine.entityManager;
|
|
52
55
|
|
|
53
|
-
|
|
56
|
+
const sgs = new ShadedGeometrySystem(engine);
|
|
57
|
+
|
|
58
|
+
const mrc = new MicronRenderContext();
|
|
59
|
+
sgs.register_render_adapter(2, () => {
|
|
60
|
+
const adapter = new MicronShadedGeometryRenderAdapter();
|
|
61
|
+
adapter.ctx = mrc;
|
|
62
|
+
|
|
63
|
+
return adapter;
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
await em.addSystem(sgs);
|
|
54
67
|
await em.addSystem(new BehaviorSystem(engine));
|
|
55
68
|
|
|
56
69
|
EngineHarness.buildBasics({
|
|
@@ -74,7 +87,7 @@ async function main(engine) {
|
|
|
74
87
|
|
|
75
88
|
const random = seededRandom(0);
|
|
76
89
|
|
|
77
|
-
const INSTANCE_COUNT =
|
|
90
|
+
const INSTANCE_COUNT = 10000;
|
|
78
91
|
|
|
79
92
|
const geometries = [];
|
|
80
93
|
|
|
@@ -87,7 +100,9 @@ async function main(engine) {
|
|
|
87
100
|
const sg = ShadedGeometry.from(geometry, material);
|
|
88
101
|
|
|
89
102
|
// sg.draw_method = DRAW_METHOD_PLAIN;
|
|
90
|
-
sg.draw_method = DRAW_METHOD_INSTANCED;
|
|
103
|
+
// sg.draw_method = DRAW_METHOD_INSTANCED;
|
|
104
|
+
// sg.draw_method = 2;
|
|
105
|
+
sg.draw_method = randomIntegerBetween(random, 0, 2);
|
|
91
106
|
// sg.draw_method = random() > 0.01 ? DRAW_METHOD_INSTANCED : DRAW_METHOD_PLAIN;
|
|
92
107
|
sg.clearFlag(ShadedGeometryFlags.CastShadow | ShadedGeometryFlags.ReceiveShadow);
|
|
93
108
|
|
|
@@ -105,7 +120,7 @@ async function main(engine) {
|
|
|
105
120
|
.build(ecd);
|
|
106
121
|
}
|
|
107
122
|
|
|
108
|
-
makeMovingShadedGeometry().build(ecd);
|
|
123
|
+
// makeMovingShadedGeometry().build(ecd);
|
|
109
124
|
|
|
110
125
|
debug_button(engine, () => {
|
|
111
126
|
const dot = convert_bvh_to_dot_format_string(engine.graphics.layers.getLayerByName('shaded-geometry').bvh);
|
|
@@ -121,7 +121,7 @@ const PRINT_VERBOSE_STATS = false;
|
|
|
121
121
|
/**
|
|
122
122
|
*
|
|
123
123
|
* @param {THREE.BufferGeometry} input
|
|
124
|
-
* @returns {MicronGeometry}
|
|
124
|
+
* @returns {Promise<MicronGeometry>}
|
|
125
125
|
*/
|
|
126
126
|
export async function buildMicronGeometryFromBufferGeometry(input) {
|
|
127
127
|
const source_geometry = deinterleaveBufferGeometry(input);
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { AbstractRenderAdapter } from "../../../ecs/mesh-v2/render/adapters/AbstractRenderAdapter.js";
|
|
2
2
|
import Vector2 from "../../../../../core/geom/Vector2.js";
|
|
3
|
+
import { buildMicronGeometryFromBufferGeometry } from "../../build/buildMicronGeometryFromBufferGeometry.js";
|
|
4
|
+
import { ShadedGeometryFlags } from "../../../ecs/mesh-v2/ShadedGeometryFlags.js";
|
|
5
|
+
import { MaterialVertexSpec, MaterialVertexSpecFlags } from "../../render/v1/MaterialVertexSpec.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @type {MaterialVertexSpec}
|
|
10
|
+
*/
|
|
11
|
+
const scratch_mvc = new MaterialVertexSpec();
|
|
3
12
|
|
|
4
13
|
export class MicronShadedGeometryRenderAdapter extends AbstractRenderAdapter {
|
|
5
14
|
|
|
@@ -21,19 +30,42 @@ export class MicronShadedGeometryRenderAdapter extends AbstractRenderAdapter {
|
|
|
21
30
|
|
|
22
31
|
/**
|
|
23
32
|
*
|
|
24
|
-
* @type {
|
|
33
|
+
* @type {Map<number, Promise>}
|
|
25
34
|
* @private
|
|
26
35
|
*/
|
|
27
|
-
this.
|
|
36
|
+
this.__geometry_building_promises = new Map();
|
|
28
37
|
}
|
|
29
38
|
|
|
30
39
|
add(sg) {
|
|
31
40
|
|
|
32
|
-
const
|
|
41
|
+
const geometry_id = sg.geometry.id;
|
|
42
|
+
|
|
43
|
+
const micron_geometry = this.__geometry_map.get(geometry_id);
|
|
44
|
+
|
|
45
|
+
if (micron_geometry === undefined) {
|
|
46
|
+
// no micron geometry
|
|
47
|
+
if (!this.__geometry_building_promises.has(geometry_id)) {
|
|
48
|
+
const p = buildMicronGeometryFromBufferGeometry(sg.geometry);
|
|
49
|
+
|
|
50
|
+
this.__geometry_building_promises.set(geometry_id, p);
|
|
51
|
+
|
|
52
|
+
p.then(mg => this.__geometry_map.set(geometry_id, mg));
|
|
53
|
+
}
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
33
56
|
|
|
34
57
|
// populate virtual geometry for this instance
|
|
35
58
|
this.ctx.builder.buildForMesh(sg.entity, micron_geometry, sg.transform);
|
|
36
59
|
|
|
60
|
+
scratch_mvc.material = sg.material;
|
|
61
|
+
scratch_mvc.spec = micron_geometry.vertex_spec;
|
|
62
|
+
scratch_mvc.writeFlag(MaterialVertexSpecFlags.CastShadow, sg.getFlag(ShadedGeometryFlags.CastShadow));
|
|
63
|
+
scratch_mvc.writeFlag(MaterialVertexSpecFlags.ReceiveShadow, sg.getFlag(ShadedGeometryFlags.ReceiveShadow));
|
|
64
|
+
|
|
65
|
+
const material_context = this.ctx.obtain_material(scratch_mvc);
|
|
66
|
+
|
|
67
|
+
material_context.instances.add(sg.entity);
|
|
68
|
+
|
|
37
69
|
}
|
|
38
70
|
|
|
39
71
|
/**
|
|
@@ -69,6 +101,16 @@ export class MicronShadedGeometryRenderAdapter extends AbstractRenderAdapter {
|
|
|
69
101
|
|
|
70
102
|
build_end() {
|
|
71
103
|
this.ctx.render();
|
|
104
|
+
|
|
105
|
+
const material_contexts = this.ctx.contexts_array;
|
|
106
|
+
const contexts_count = material_contexts.length;
|
|
107
|
+
for (let i = 0; i < contexts_count; i++) {
|
|
108
|
+
const mc = material_contexts[i];
|
|
109
|
+
|
|
110
|
+
if (mc.instances.size > 0) {
|
|
111
|
+
this.__objects[this.__object_count++] = mc.mesh;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
72
114
|
}
|
|
73
115
|
|
|
74
116
|
dispose() {
|
|
@@ -52,7 +52,7 @@ export class MaterialContext {
|
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
*
|
|
55
|
-
* @type {
|
|
55
|
+
* @type {Uint32Array|number[]}
|
|
56
56
|
*/
|
|
57
57
|
this.__patches = [];
|
|
58
58
|
|
|
@@ -63,16 +63,6 @@ export class MaterialContext {
|
|
|
63
63
|
this.__patch_count = 0;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
*
|
|
69
|
-
* @param {MicronGeometryPatchOccurrence} occurrence
|
|
70
|
-
* @returns {boolean}
|
|
71
|
-
*/
|
|
72
|
-
filter(occurrence) {
|
|
73
|
-
return this.instances.has(occurrence.instance_id);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
66
|
init() {
|
|
77
67
|
|
|
78
68
|
const material = this.material.clone();
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export const MaterialVertexSpecFlags = {
|
|
2
|
+
CastShadow: 1,
|
|
3
|
+
ReceiveShadow: 2
|
|
4
|
+
};
|
|
5
|
+
|
|
1
6
|
export class MaterialVertexSpec {
|
|
2
7
|
constructor() {
|
|
3
8
|
/**
|
|
@@ -10,6 +15,52 @@ export class MaterialVertexSpec {
|
|
|
10
15
|
* @type {THREE.Material|null}
|
|
11
16
|
*/
|
|
12
17
|
this.material = null;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @type {number}
|
|
22
|
+
*/
|
|
23
|
+
this.flags = 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
*
|
|
28
|
+
* @param {number|MaterialVertexSpecFlags} flag
|
|
29
|
+
* @returns {void}
|
|
30
|
+
*/
|
|
31
|
+
setFlag(flag) {
|
|
32
|
+
this.flags |= flag;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
*
|
|
37
|
+
* @param {number|MaterialVertexSpecFlags} flag
|
|
38
|
+
* @returns {void}
|
|
39
|
+
*/
|
|
40
|
+
clearFlag(flag) {
|
|
41
|
+
this.flags &= ~flag;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
* @param {number|MaterialVertexSpecFlags} flag
|
|
47
|
+
* @param {boolean} value
|
|
48
|
+
*/
|
|
49
|
+
writeFlag(flag, value) {
|
|
50
|
+
if (value) {
|
|
51
|
+
this.setFlag(flag);
|
|
52
|
+
} else {
|
|
53
|
+
this.clearFlag(flag);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
*
|
|
59
|
+
* @param {number|MaterialVertexSpecFlags} flag
|
|
60
|
+
* @returns {boolean}
|
|
61
|
+
*/
|
|
62
|
+
getFlag(flag) {
|
|
63
|
+
return (this.flags & flag) === flag;
|
|
13
64
|
}
|
|
14
65
|
|
|
15
66
|
/**
|
|
@@ -19,6 +70,7 @@ export class MaterialVertexSpec {
|
|
|
19
70
|
copy(other) {
|
|
20
71
|
this.spec = other.spec;
|
|
21
72
|
this.material = other.material;
|
|
73
|
+
this.flags = other.flags;
|
|
22
74
|
}
|
|
23
75
|
|
|
24
76
|
/**
|
|
@@ -47,7 +99,7 @@ export class MaterialVertexSpec {
|
|
|
47
99
|
}
|
|
48
100
|
|
|
49
101
|
hash() {
|
|
50
|
-
return this.spec.hash() ^ this.material.id;
|
|
102
|
+
return this.spec.hash() ^ this.material.id ^ this.flags;
|
|
51
103
|
}
|
|
52
104
|
|
|
53
105
|
equals(other) {
|
|
@@ -55,8 +107,9 @@ export class MaterialVertexSpec {
|
|
|
55
107
|
return true;
|
|
56
108
|
}
|
|
57
109
|
|
|
58
|
-
return this.
|
|
110
|
+
return this.flags === other.flags
|
|
59
111
|
&& this.material === other.material
|
|
112
|
+
&& this.spec.equals(other.spec)
|
|
60
113
|
;
|
|
61
114
|
}
|
|
62
115
|
}
|
|
@@ -3,7 +3,7 @@ import { VirtualGeometryBuilder } from "../VirtualGeometryBuilder.js";
|
|
|
3
3
|
import { HashMap } from "../../../../../core/collection/HashMap.js";
|
|
4
4
|
import Signal from "../../../../../core/events/signal/Signal.js";
|
|
5
5
|
import { MaterialContext } from "./MaterialContext.js";
|
|
6
|
-
import { MaterialVertexSpec } from "./MaterialVertexSpec.js";
|
|
6
|
+
import { MaterialVertexSpec, MaterialVertexSpecFlags } from "./MaterialVertexSpec.js";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
*
|
|
@@ -39,6 +39,14 @@ export class MicronRenderContext {
|
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
* @returns {MaterialContext[]}
|
|
45
|
+
*/
|
|
46
|
+
get contexts_array() {
|
|
47
|
+
return this.__contexts_array;
|
|
48
|
+
}
|
|
49
|
+
|
|
42
50
|
/**
|
|
43
51
|
* Enable/disable wireframe rendering
|
|
44
52
|
* @param {boolean} x
|
|
@@ -55,27 +63,27 @@ export class MicronRenderContext {
|
|
|
55
63
|
|
|
56
64
|
/**
|
|
57
65
|
*
|
|
58
|
-
* @param {
|
|
59
|
-
* @param {Material} m
|
|
66
|
+
* @param {MaterialVertexSpec} descriptor
|
|
60
67
|
* @returns {MaterialContext}
|
|
61
68
|
*/
|
|
62
|
-
obtain_material(
|
|
63
|
-
scratch_mvc.material = m;
|
|
64
|
-
scratch_mvc.spec = spec;
|
|
69
|
+
obtain_material(descriptor) {
|
|
65
70
|
|
|
66
|
-
const existing = this.material_contexts.get(
|
|
71
|
+
const existing = this.material_contexts.get(descriptor);
|
|
67
72
|
|
|
68
73
|
if (existing !== undefined) {
|
|
69
74
|
return existing;
|
|
70
75
|
}
|
|
71
76
|
|
|
72
77
|
// create a separate instance to be stored alongside the context
|
|
73
|
-
const key =
|
|
78
|
+
const key = descriptor.clone();
|
|
74
79
|
|
|
75
|
-
const ctx = new MaterialContext(spec,
|
|
80
|
+
const ctx = new MaterialContext(descriptor.spec, descriptor.material);
|
|
76
81
|
|
|
77
82
|
ctx.init();
|
|
78
83
|
|
|
84
|
+
ctx.mesh.castShadow = descriptor.getFlag(MaterialVertexSpecFlags.CastShadow);
|
|
85
|
+
ctx.mesh.receiveShadow = descriptor.getFlag(MaterialVertexSpecFlags.ReceiveShadow);
|
|
86
|
+
|
|
79
87
|
this.material_contexts.set(key, ctx);
|
|
80
88
|
this.__contexts_array.push(ctx);
|
|
81
89
|
|
|
@@ -95,7 +103,9 @@ export class MicronRenderContext {
|
|
|
95
103
|
*/
|
|
96
104
|
const instance_to_ctx = new Map();
|
|
97
105
|
|
|
98
|
-
|
|
106
|
+
let i = 0;
|
|
107
|
+
|
|
108
|
+
for (i = 0; i < context_count; i++) {
|
|
99
109
|
const ctx = contexts[i];
|
|
100
110
|
ctx.__patch_count = 0;
|
|
101
111
|
|
|
@@ -109,7 +119,7 @@ export class MicronRenderContext {
|
|
|
109
119
|
const patch_count = geometry.patch_count;
|
|
110
120
|
const patches = geometry.patches;
|
|
111
121
|
|
|
112
|
-
for (
|
|
122
|
+
for (i = 0; i < patch_count; i++) {
|
|
113
123
|
const i3 = i * 3;
|
|
114
124
|
|
|
115
125
|
const instance_id = patches[i3];
|
|
@@ -118,7 +128,9 @@ export class MicronRenderContext {
|
|
|
118
128
|
|
|
119
129
|
const ctx = instance_to_ctx.get(instance_id);
|
|
120
130
|
|
|
121
|
-
const
|
|
131
|
+
const target_index = ctx.__patch_count;
|
|
132
|
+
const target_address = target_index * 3;
|
|
133
|
+
|
|
122
134
|
ctx.__patch_count++;
|
|
123
135
|
|
|
124
136
|
const ctx_patches = ctx.__patches;
|
|
@@ -129,7 +141,7 @@ export class MicronRenderContext {
|
|
|
129
141
|
}
|
|
130
142
|
|
|
131
143
|
// build each context
|
|
132
|
-
for (
|
|
144
|
+
for (i = 0; i < context_count; i++) {
|
|
133
145
|
const ctx = contexts[i];
|
|
134
146
|
|
|
135
147
|
ctx.build(geometry);
|
|
@@ -2,6 +2,13 @@ import Vector2 from "../../../../../core/geom/Vector2.js";
|
|
|
2
2
|
import { MaterialContext } from "./MaterialContext.js";
|
|
3
3
|
import { array_copy } from "../../../../../core/collection/array/copyArray.js";
|
|
4
4
|
import { MicronRenderContext } from "./MicronRenderContext.js";
|
|
5
|
+
import { MaterialVertexSpec, MaterialVertexSpecFlags } from "./MaterialVertexSpec.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @type {MaterialVertexSpec}
|
|
10
|
+
*/
|
|
11
|
+
const scratch_mvc = new MaterialVertexSpec();
|
|
5
12
|
|
|
6
13
|
export class VGThreeRenderer {
|
|
7
14
|
constructor() {
|
|
@@ -73,7 +80,12 @@ export class VGThreeRenderer {
|
|
|
73
80
|
*/
|
|
74
81
|
const m = o;
|
|
75
82
|
|
|
76
|
-
|
|
83
|
+
scratch_mvc.material = m.material;
|
|
84
|
+
scratch_mvc.spec = m.geometry.vertex_spec;
|
|
85
|
+
scratch_mvc.writeFlag(MaterialVertexSpecFlags.CastShadow, m.castShadow);
|
|
86
|
+
scratch_mvc.writeFlag(MaterialVertexSpecFlags.ReceiveShadow, m.receiveShadow);
|
|
87
|
+
|
|
88
|
+
const ctx = render_context.obtain_material(scratch_mvc);
|
|
77
89
|
|
|
78
90
|
ctx.instances.add(o.instance_id);
|
|
79
91
|
}
|
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.
|
|
8
|
+
"version": "2.35.12",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|