@xeokit/xeokit-sdk 2.6.92 → 2.6.93
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/dist/xeokit-sdk.cjs.js +13074 -44661
- package/dist/xeokit-sdk.es.js +13075 -44660
- package/dist/xeokit-sdk.es5.js +1403 -3501
- package/dist/xeokit-sdk.min.cjs.js +8 -8
- package/dist/xeokit-sdk.min.es.js +8 -8
- package/dist/xeokit-sdk.min.es5.js +7 -7
- package/package.json +1 -1
- package/src/viewer/Viewer.js +55 -103
- package/src/viewer/scene/canvas/Canvas.js +3 -43
- package/src/viewer/scene/geometry/ReadableGeometry.js +0 -25
- package/src/viewer/scene/lights/CubeTexture.js +0 -13
- package/src/viewer/scene/lights/DirLight.js +2 -1
- package/src/viewer/scene/lights/PointLight.js +2 -1
- package/src/viewer/scene/materials/Texture.js +0 -9
- package/src/viewer/scene/math/rtcCoords.js +1 -38
- package/src/viewer/scene/mesh/Mesh.js +454 -212
- package/src/viewer/scene/mesh/draw/DrawShaderSource.js +305 -1504
- package/src/viewer/scene/mesh/draw/LambertShaderSource.js +35 -0
- package/src/viewer/scene/mesh/emphasis/EmphasisShaderSource.js +34 -0
- package/src/viewer/scene/mesh/occlusion/OcclusionShaderSource.js +9 -158
- package/src/viewer/scene/mesh/pick/PickMeshShaderSource.js +21 -151
- package/src/viewer/scene/mesh/pick/PickTriangleShaderSource.js +12 -124
- package/src/viewer/scene/mesh/shadow/ShadowShaderSource.js +22 -97
- package/src/viewer/scene/model/SceneModel.js +248 -852
- package/src/viewer/scene/model/SceneModelEntity.js +4 -4
- package/src/viewer/scene/model/SceneModelMesh.js +3 -3
- package/src/viewer/scene/model/layer/DTXLayer.js +940 -0
- package/src/viewer/scene/model/layer/Layer.js +788 -0
- package/src/viewer/scene/model/layer/VBOLayer.js +1019 -0
- package/src/viewer/scene/model/layer/programs/ColorProgram.js +35 -0
- package/src/viewer/scene/model/layer/programs/ColorTextureProgram.js +46 -0
- package/src/viewer/scene/model/layer/programs/DepthProgram.js +11 -0
- package/src/viewer/scene/model/layer/programs/EdgesProgram.js +12 -0
- package/src/viewer/scene/model/layer/programs/FlatColorProgram.js +24 -0
- package/src/viewer/scene/model/layer/programs/OcclusionProgram.js +12 -0
- package/src/viewer/scene/model/layer/programs/PBRProgram.js +180 -0
- package/src/viewer/scene/model/layer/programs/PickDepthProgram.js +30 -0
- package/src/viewer/scene/model/layer/programs/PickMeshProgram.js +12 -0
- package/src/viewer/scene/model/layer/programs/PickNormalsProgram.js +18 -0
- package/src/viewer/scene/model/layer/programs/ShadowProgram.js +23 -0
- package/src/viewer/scene/model/layer/programs/SilhouetteProgram.js +15 -0
- package/src/viewer/scene/model/layer/programs/SnapProgram.js +29 -0
- package/src/viewer/scene/scene/Scene.js +21 -38
- package/src/viewer/scene/webgl/ArrayBuf.js +5 -20
- package/src/viewer/scene/webgl/FrameContext.js +14 -86
- package/src/viewer/scene/webgl/RenderBuffer.js +62 -262
- package/src/viewer/scene/webgl/Renderer.js +880 -843
- package/src/viewer/scene/webgl/WebGLRenderer.js +612 -0
- package/src/viewer/scene/webgl/occlusion/OcclusionLayer.js +60 -132
- package/src/viewer/scene/webgl/occlusion/OcclusionTester.js +167 -328
- package/src/viewer/scene/mesh/draw/DrawRenderer.js +0 -998
- package/src/viewer/scene/mesh/emphasis/EmphasisEdgesRenderer.js +0 -259
- package/src/viewer/scene/mesh/emphasis/EmphasisEdgesShaderSource.js +0 -160
- package/src/viewer/scene/mesh/emphasis/EmphasisFillRenderer.js +0 -286
- package/src/viewer/scene/mesh/emphasis/EmphasisFillShaderSource.js +0 -263
- package/src/viewer/scene/mesh/occlusion/OcclusionRenderer.js +0 -221
- package/src/viewer/scene/mesh/pick/PickMeshRenderer.js +0 -223
- package/src/viewer/scene/mesh/pick/PickTriangleRenderer.js +0 -200
- package/src/viewer/scene/mesh/shadow/ShadowRenderer.js +0 -214
- package/src/viewer/scene/model/RENDER_PASSES.js +0 -34
- package/src/viewer/scene/model/dtx/BindableDataTexture.js +0 -31
- package/src/viewer/scene/model/dtx/lines/DTXLinesBuffer.js +0 -27
- package/src/viewer/scene/model/dtx/lines/DTXLinesLayer.js +0 -897
- package/src/viewer/scene/model/dtx/lines/DTXLinesState.js +0 -46
- package/src/viewer/scene/model/dtx/lines/DTXLinesTextureFactory.js +0 -411
- package/src/viewer/scene/model/dtx/lines/dataTextureRamStats.js +0 -49
- package/src/viewer/scene/model/dtx/lines/rebucketPositions.js +0 -208
- package/src/viewer/scene/model/dtx/lines/renderers/DTXLinesColorRenderer.js +0 -389
- package/src/viewer/scene/model/dtx/lines/renderers/DTXLinesRenderers.js +0 -65
- package/src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js +0 -1399
- package/src/viewer/scene/model/dtx/triangles/lib/DTXTrianglesBuffer.js +0 -46
- package/src/viewer/scene/model/dtx/triangles/lib/DTXTrianglesState.js +0 -250
- package/src/viewer/scene/model/dtx/triangles/lib/DTXTrianglesTextureFactory.js +0 -518
- package/src/viewer/scene/model/dtx/triangles/lib/dataTextureRamStats.js +0 -54
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesColorRenderer.js +0 -639
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesDepthRenderer.js +0 -464
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesEdgesColorRenderer.js +0 -423
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesEdgesRenderer.js +0 -431
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesNormalsRenderer.js +0 -345
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesOcclusionRenderer.js +0 -436
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickDepthRenderer.js +0 -466
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickMeshRenderer.js +0 -437
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickNormalsFlatRenderer.js +0 -460
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesPickNormalsRenderer.js +0 -437
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesRenderers.js +0 -307
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSilhouetteRenderer.js +0 -472
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSnapInitRenderer.js +0 -474
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSnapRenderer.js +0 -435
- package/src/viewer/scene/model/vbo/ScratchMemory.js +0 -63
- package/src/viewer/scene/model/vbo/VBORenderer.js +0 -664
- package/src/viewer/scene/model/vbo/batching/lines/VBOBatchingLinesLayer.js +0 -704
- package/src/viewer/scene/model/vbo/batching/lines/lib/VBOBatchingLinesBuffer.js +0 -19
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLineSnapInitRenderer.js +0 -318
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesColorRenderer.js +0 -114
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesRenderers.js +0 -99
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSilhouetteRenderer.js +0 -124
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapInitRenderer.js +0 -313
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapRenderer.js +0 -311
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOSceneModelLineBatchingRenderer.js +0 -24
- package/src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsLayer.js +0 -688
- package/src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsRenderer.js +0 -24
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsColorRenderer.js +0 -168
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsOcclusionRenderer.js +0 -136
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsPickDepthRenderer.js +0 -156
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsPickMeshRenderer.js +0 -148
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsRenderers.js +0 -144
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsShadowRenderer.js +0 -107
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsSilhouetteRenderer.js +0 -146
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsSnapInitRenderer.js +0 -315
- package/src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsSnapRenderer.js +0 -305
- package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesBuffer.js +0 -24
- package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesLayer.js +0 -1346
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesColorRenderer.js +0 -131
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesEmphasisRenderer.js +0 -135
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesRenderer.js +0 -12
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/Renderers.js +0 -403
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesBatchingRenderer.js +0 -35
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorRenderer.js +0 -252
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorTextureRenderer.js +0 -294
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesDepthRenderer.js +0 -115
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesFlatColorRenderer.js +0 -246
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesNormalsRenderer.js +0 -139
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesOcclusionRenderer.js +0 -125
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPBRRenderer.js +0 -561
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickDepthRenderer.js +0 -144
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickMeshRenderer.js +0 -130
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickNormalsFlatRenderer.js +0 -121
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickNormalsRenderer.js +0 -131
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesShadowRenderer.js +0 -107
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSilhouetteRenderer.js +0 -144
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapInitRenderer.js +0 -313
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapRenderer.js +0 -312
- package/src/viewer/scene/model/vbo/float16.js +0 -760
- package/src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js +0 -711
- package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesColorRenderer.js +0 -148
- package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesRenderer.js +0 -26
- package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesRenderers.js +0 -139
- package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSilhouetteRenderer.js +0 -127
- package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSnapInitRenderer.js +0 -308
- package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSnapRenderer.js +0 -299
- package/src/viewer/scene/model/vbo/instancing/points/VBOInstancingPointsLayer.js +0 -733
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsColorRenderer.js +0 -174
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsDepthRenderer.js +0 -156
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsOcclusionRenderer.js +0 -149
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsPickDepthRenderer.js +0 -170
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsPickMeshRenderer.js +0 -152
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsRenderer.js +0 -26
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsRenderers.js +0 -174
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsShadowRenderer.js +0 -119
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsSilhouetteRenderer.js +0 -154
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsSnapInitRenderer.js +0 -307
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingPointsSnapRenderer.js +0 -293
- package/src/viewer/scene/model/vbo/instancing/points/renderers/VBOInstancingTrianglesRenderer.js +0 -150
- package/src/viewer/scene/model/vbo/instancing/triangles/VBOInstancingTrianglesLayer.js +0 -1289
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/EdgesColorRenderer.js +0 -135
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/EdgesEmphasisRenderer.js +0 -137
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/EdgesRenderer.js +0 -12
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/Renderers.js +0 -403
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesColorRenderer.js +0 -267
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesColorTextureRenderer.js +0 -299
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesDepthRenderer.js +0 -126
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesFlatColorRenderer.js +0 -255
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesFlatNormalsRenderer.js +0 -130
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesInstancingRenderer.js +0 -32
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesNormalsRenderer.js +0 -138
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesOcclusionRenderer.js +0 -128
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPBRRenderer.js +0 -561
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickDepthRenderer.js +0 -149
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickMeshRenderer.js +0 -136
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickNormalsFlatRenderer.js +0 -130
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesPickNormalsRenderer.js +0 -145
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesShadowRenderer.js +0 -113
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSilhouetteRenderer.js +0 -148
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSnapInitRenderer.js +0 -319
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSnapRenderer.js +0 -310
- package/src/viewer/scene/webgl/Attribute.js +0 -23
- package/src/viewer/scene/webgl/Program.js +0 -181
- package/src/viewer/scene/webgl/RenderBufferManager.js +0 -34
- package/src/viewer/scene/webgl/Sampler.js +0 -18
- package/src/viewer/scene/webgl/Shader.js +0 -49
- package/src/viewer/scene/webgl/sao/SAODepthLimitedBlurRenderer.js +0 -324
- package/src/viewer/scene/webgl/sao/SAOOcclusionRenderer.js +0 -384
|
@@ -0,0 +1,940 @@
|
|
|
1
|
+
import {ENTITY_FLAGS} from "../ENTITY_FLAGS.js";
|
|
2
|
+
import {getColSilhEdgePickFlags, getRenderers, isPerspectiveMatrix, Layer} from "./Layer.js";
|
|
3
|
+
import {math} from "../../math/math.js";
|
|
4
|
+
import {Configs} from "../../../Configs.js";
|
|
5
|
+
|
|
6
|
+
const iota = (n) => { const ret = [ ]; for (let i = 0; i < n; ++i) ret.push(i); return ret; };
|
|
7
|
+
|
|
8
|
+
const dataTextureRamStats = {
|
|
9
|
+
sizeDataColorsAndFlags: 0,
|
|
10
|
+
sizeDataInstancesMatrices: 0,
|
|
11
|
+
sizeDataPositionDecodeMatrices: 0,
|
|
12
|
+
sizeDataTextureOffsets: 0,
|
|
13
|
+
sizeDataTexturePositions: 0,
|
|
14
|
+
sizeDataTextureIndices: 0,
|
|
15
|
+
sizeDataTextureEdgeIndices: 0,
|
|
16
|
+
sizeDataTexturePortionIds: 0,
|
|
17
|
+
numberOfGeometries: 0,
|
|
18
|
+
numberOfPortions: 0,
|
|
19
|
+
numberOfLayers: 0,
|
|
20
|
+
numberOfTextures: 0,
|
|
21
|
+
totalPolygons: 0,
|
|
22
|
+
totalPolygons8Bits: 0,
|
|
23
|
+
totalPolygons16Bits: 0,
|
|
24
|
+
totalPolygons32Bits: 0,
|
|
25
|
+
totalEdges: 0,
|
|
26
|
+
totalEdges8Bits: 0,
|
|
27
|
+
totalEdges16Bits: 0,
|
|
28
|
+
totalEdges32Bits: 0,
|
|
29
|
+
cannotCreatePortion: {
|
|
30
|
+
because10BitsObjectId: 0,
|
|
31
|
+
becauseTextureSize: 0,
|
|
32
|
+
},
|
|
33
|
+
overheadSizeAlignementIndices: 0,
|
|
34
|
+
overheadSizeAlignementEdgeIndices: 0,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
window.printDataTextureRamStats = function () {
|
|
38
|
+
|
|
39
|
+
console.log(JSON.stringify(dataTextureRamStats, null, 4));
|
|
40
|
+
|
|
41
|
+
let totalRamSize = 0;
|
|
42
|
+
|
|
43
|
+
Object.keys(dataTextureRamStats).forEach(key => {
|
|
44
|
+
if (key.startsWith("size")) {
|
|
45
|
+
totalRamSize += dataTextureRamStats[key];
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
console.log(`Total size ${totalRamSize} bytes (${(totalRamSize / 1000 / 1000).toFixed(2)} MB)`);
|
|
50
|
+
console.log(`Avg bytes / triangle: ${(totalRamSize / dataTextureRamStats.totalPolygons).toFixed(2)}`);
|
|
51
|
+
|
|
52
|
+
let percentualRamStats = {};
|
|
53
|
+
|
|
54
|
+
Object.keys(dataTextureRamStats).forEach(key => {
|
|
55
|
+
if (key.startsWith("size")) {
|
|
56
|
+
percentualRamStats[key] =
|
|
57
|
+
`${(dataTextureRamStats[key] / totalRamSize * 100).toFixed(2)} % of total`;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
console.log(JSON.stringify({percentualRamUsage: percentualRamStats}, null, 4));
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const configs = new Configs();
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 12-bits allowed for object ids.
|
|
68
|
+
* Limits the per-object texture height in the layer.
|
|
69
|
+
*/
|
|
70
|
+
const MAX_NUMBER_OF_OBJECTS_IN_LAYER = (1 << 16);
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 4096 is max data texture height.
|
|
74
|
+
* Limits the aggregated geometry texture height in the layer.
|
|
75
|
+
*/
|
|
76
|
+
const MAX_DATA_TEXTURE_HEIGHT = configs.maxDataTextureHeight;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Align `indices` and `edgeIndices` memory layout to 8 elements.
|
|
80
|
+
*
|
|
81
|
+
* Used as an optimization for the `...portionIds...` texture, so it
|
|
82
|
+
* can just be stored 1 out of 8 `portionIds` corresponding to a given
|
|
83
|
+
* `triangle-index` or `edge-index`.
|
|
84
|
+
*/
|
|
85
|
+
const INDICES_EDGE_INDICES_ALIGNEMENT_SIZE = 8;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Number of maximum allowed per-object flags update per render frame
|
|
89
|
+
* before switching to batch update mode.
|
|
90
|
+
*/
|
|
91
|
+
const MAX_OBJECT_UPDATES_IN_FRAME_WITHOUT_BATCHED_UPDATE = 10;
|
|
92
|
+
|
|
93
|
+
const tempVec3 = math.vec3();
|
|
94
|
+
const tempVec3a = math.vec3();
|
|
95
|
+
const tempVec4a = math.vec4();
|
|
96
|
+
const tempVec4b = math.vec4();
|
|
97
|
+
const tempMat4a = new Float32Array(16);
|
|
98
|
+
const tempUint8Array4 = new Uint8Array(4);
|
|
99
|
+
const tempFloat32Array3 = new Float32Array(3);
|
|
100
|
+
|
|
101
|
+
const DEFAULT_MATRIX = math.identityMat4();
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @private
|
|
105
|
+
*/
|
|
106
|
+
export class DTXLayer extends Layer {
|
|
107
|
+
|
|
108
|
+
constructor(model, primitive, origin) {
|
|
109
|
+
|
|
110
|
+
super(model, primitive, origin);
|
|
111
|
+
|
|
112
|
+
dataTextureRamStats.numberOfLayers++;
|
|
113
|
+
|
|
114
|
+
this._sortId = `TriDTX-${dataTextureRamStats.numberOfLayers}`;
|
|
115
|
+
|
|
116
|
+
const gl = model.scene.canvas.gl;
|
|
117
|
+
|
|
118
|
+
const geometryData = (indicesStatsProp, edgesStatsProp) => {
|
|
119
|
+
const indicesBuffer = [ ];
|
|
120
|
+
let lenIndices = 0;
|
|
121
|
+
const perTriangleNumberPortionId = [ ];
|
|
122
|
+
let numIndices = 0;
|
|
123
|
+
|
|
124
|
+
const edgeIndicesBuffer = [ ];
|
|
125
|
+
let lenEdgeIndices = 0;
|
|
126
|
+
const perEdgeNumberPortionId = [ ];
|
|
127
|
+
let numEdgeIndices = 0;
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
len: () => numIndices,
|
|
131
|
+
|
|
132
|
+
accumulateIndices: (indices, edgeIndices) => {
|
|
133
|
+
const accIndicesSubPortion = (indices && (indices.length > 0)) && (function() {
|
|
134
|
+
const indicesBase = lenIndices / 3;
|
|
135
|
+
lenIndices += indices.length;
|
|
136
|
+
indicesBuffer.push(indices);
|
|
137
|
+
const numTriangles = indices.length / 3;
|
|
138
|
+
return (subPortionId) => {
|
|
139
|
+
const currentNumIndices = numIndices;
|
|
140
|
+
numIndices += numTriangles * 3;
|
|
141
|
+
buffer.perObjectIndexBaseOffsets.push(currentNumIndices / 3 - indicesBase);
|
|
142
|
+
for (let i = 0; i < numTriangles; i += INDICES_EDGE_INDICES_ALIGNEMENT_SIZE) {
|
|
143
|
+
perTriangleNumberPortionId.push(subPortionId);
|
|
144
|
+
}
|
|
145
|
+
dataTextureRamStats[indicesStatsProp] += numTriangles;
|
|
146
|
+
dataTextureRamStats.totalPolygons += numTriangles;
|
|
147
|
+
};
|
|
148
|
+
})();
|
|
149
|
+
|
|
150
|
+
const accEdgesSubPortion = edgeIndices && (function() {
|
|
151
|
+
const edgeIndicesBase = lenEdgeIndices / 2;
|
|
152
|
+
lenEdgeIndices += edgeIndices.length;
|
|
153
|
+
edgeIndicesBuffer.push(edgeIndices);
|
|
154
|
+
const numEdges = edgeIndices.length / 2;
|
|
155
|
+
return subPortionId => {
|
|
156
|
+
const currentNumEdgeIndices = numEdgeIndices;
|
|
157
|
+
numEdgeIndices += numEdges * 2;
|
|
158
|
+
buffer.perObjectEdgeIndexBaseOffsets.push(currentNumEdgeIndices / 2 - edgeIndicesBase);
|
|
159
|
+
for (let i = 0; i < numEdges; i += INDICES_EDGE_INDICES_ALIGNEMENT_SIZE) {
|
|
160
|
+
perEdgeNumberPortionId.push(subPortionId);
|
|
161
|
+
}
|
|
162
|
+
dataTextureRamStats[edgesStatsProp] += numEdges;
|
|
163
|
+
dataTextureRamStats.totalEdges += numEdges;
|
|
164
|
+
};
|
|
165
|
+
})();
|
|
166
|
+
|
|
167
|
+
dataTextureRamStats.numberOfGeometries++;
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
numTriangles: indices ? (indices.length / 3) : 0,
|
|
171
|
+
accumulateSubPortionId: subPortionId => {
|
|
172
|
+
accIndicesSubPortion && accIndicesSubPortion(subPortionId);
|
|
173
|
+
accEdgesSubPortion && accEdgesSubPortion(subPortionId);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
createDrawers: (createTextureForSingleItems, indicesType) => {
|
|
179
|
+
const createTextureForPackedPortionIds = function(portionIdsArray, defaultIfEmpty) {
|
|
180
|
+
return (portionIdsArray.length > 0) ? createTextureForSingleItems([ portionIdsArray ], portionIdsArray.length, 1, gl.UNSIGNED_SHORT, "sizeDataTexturePortionIds") : defaultIfEmpty;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// Texture that holds the PortionId that corresponds to a given polygon-id.
|
|
184
|
+
const portionIdsTexture = createTextureForPackedPortionIds(perTriangleNumberPortionId, { texture: null });
|
|
185
|
+
|
|
186
|
+
// Texture that holds the unique-vertex-indices.
|
|
187
|
+
const indicesTexture = (lenIndices > 0) && createTextureForSingleItems(indicesBuffer, lenIndices, 3, indicesType, "sizeDataTextureIndices");
|
|
188
|
+
|
|
189
|
+
// Texture that holds the PortionId that corresponds to a given edge-id.
|
|
190
|
+
const portionEdgeIdsTexture = createTextureForPackedPortionIds(perEdgeNumberPortionId);
|
|
191
|
+
|
|
192
|
+
// Texture that holds the unique-vertex-indices for 8-bit based edge indices.
|
|
193
|
+
const edgeIndicesTexture = (lenEdgeIndices > 0) && createTextureForSingleItems(edgeIndicesBuffer, lenEdgeIndices, 2, indicesType, "sizeDataTextureEdgeIndices");
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
indices: function(layerTypeInputs, glMode) {
|
|
197
|
+
if (numIndices > 0) {
|
|
198
|
+
layerTypeInputs.perPrimIndices.setInputValue(indicesTexture);
|
|
199
|
+
layerTypeInputs.perPrimIdPorIds.setInputValue(portionIdsTexture);
|
|
200
|
+
gl.drawArrays(glMode, 0, numIndices);
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
edges: function(layerTypeInputs, glMode) {
|
|
204
|
+
if (numEdgeIndices > 0) {
|
|
205
|
+
layerTypeInputs.perPrimIndices.setInputValue(edgeIndicesTexture);
|
|
206
|
+
layerTypeInputs.perPrimIdPorIds.setInputValue(portionEdgeIdsTexture);
|
|
207
|
+
gl.drawArrays(glMode, 0, numEdgeIndices);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const buffer = this._buffer = {
|
|
216
|
+
positionsCompressed: [],
|
|
217
|
+
lenPositionsCompressed: 0,
|
|
218
|
+
|
|
219
|
+
geometry8Bits: geometryData("totalPolygons8Bits", "totalEdges8Bits"),
|
|
220
|
+
geometry16Bits: geometryData("totalPolygons16Bits", "totalEdges16Bits"),
|
|
221
|
+
geometry32Bits: geometryData("totalPolygons32Bits", "totalEdges32Bits"),
|
|
222
|
+
|
|
223
|
+
perObjectColors: [],
|
|
224
|
+
perObjectPickColors: [],
|
|
225
|
+
perObjectSolid: [],
|
|
226
|
+
perObjectPositionsDecodeMatrices: [],
|
|
227
|
+
perObjectInstancePositioningMatrices: [],
|
|
228
|
+
perObjectVertexBases: [],
|
|
229
|
+
perObjectIndexBaseOffsets: [],
|
|
230
|
+
perObjectEdgeIndexBaseOffsets: []
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
this._numVertices = 0;
|
|
234
|
+
|
|
235
|
+
this._portions = []; // These counts are used to avoid unnecessary render passes
|
|
236
|
+
|
|
237
|
+
this._subPortionReadableGeometries = this.model.scene.readableGeometryEnabled && {};
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Due to `index rebucketting` process in ```prepareMeshGeometry``` function, it's possible that a single
|
|
241
|
+
* portion is expanded to more than 1 real sub-portion.
|
|
242
|
+
*
|
|
243
|
+
* This Array tracks the mapping between:
|
|
244
|
+
*
|
|
245
|
+
* - external `portionIds` as seen by consumers of this class.
|
|
246
|
+
* - internal `sub-portionIds` actually managed by this class.
|
|
247
|
+
*
|
|
248
|
+
* The outer index of this array is the externally seen `portionId`.
|
|
249
|
+
* The inner value of the array, are `sub-portionIds` corresponding to the `portionId`.
|
|
250
|
+
*/
|
|
251
|
+
this._portionToSubPortionsMap = [];
|
|
252
|
+
|
|
253
|
+
this._bucketGeometries = {};
|
|
254
|
+
|
|
255
|
+
this._primitive = primitive;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Returns whether the ```TrianglesDataTextureLayer``` has room for more portions.
|
|
260
|
+
*
|
|
261
|
+
* @param {object} portionCfg An object containing the geometrical data (`positions`, `indices`, `edgeIndices`) for the portion.
|
|
262
|
+
* @returns {Boolean} Wheter the requested portion can be created
|
|
263
|
+
*/
|
|
264
|
+
canCreatePortion(portionCfg) {
|
|
265
|
+
const numNewPortions = portionCfg.buckets.length;
|
|
266
|
+
if ((this._portions.length + numNewPortions) > MAX_NUMBER_OF_OBJECTS_IN_LAYER) {
|
|
267
|
+
dataTextureRamStats.cannotCreatePortion.because10BitsObjectId++;
|
|
268
|
+
}
|
|
269
|
+
let retVal = (this._portions.length + numNewPortions) <= MAX_NUMBER_OF_OBJECTS_IN_LAYER;
|
|
270
|
+
const bucketIndex = 0; // TODO: Is this a bug?
|
|
271
|
+
const bucketGeometryId = portionCfg.geometryId !== undefined && portionCfg.geometryId !== null
|
|
272
|
+
? `${portionCfg.geometryId}#${bucketIndex}`
|
|
273
|
+
: `${portionCfg.id}#${bucketIndex}`;
|
|
274
|
+
const alreadyHasPortionGeometry = this._bucketGeometries[bucketGeometryId];
|
|
275
|
+
if (!alreadyHasPortionGeometry) {
|
|
276
|
+
const buffer = this._buffer;
|
|
277
|
+
const maxIndicesOfAnyBits = Math.max(buffer.geometry8Bits.len(), buffer.geometry16Bits.len(), buffer.geometry32Bits.len());
|
|
278
|
+
let numVertices = 0;
|
|
279
|
+
let numIndices = 0;
|
|
280
|
+
portionCfg.buckets.forEach(bucket => {
|
|
281
|
+
numVertices += bucket.positionsCompressed.length / 3;
|
|
282
|
+
numIndices += bucket.indices.length / 3;
|
|
283
|
+
});
|
|
284
|
+
if ((this._numVertices + numVertices) > MAX_DATA_TEXTURE_HEIGHT * 4096 ||
|
|
285
|
+
(maxIndicesOfAnyBits + numIndices) > MAX_DATA_TEXTURE_HEIGHT * 4096) {
|
|
286
|
+
dataTextureRamStats.cannotCreatePortion.becauseTextureSize++;
|
|
287
|
+
}
|
|
288
|
+
retVal &&=
|
|
289
|
+
(this._numVertices + numVertices) <= MAX_DATA_TEXTURE_HEIGHT * 4096 &&
|
|
290
|
+
(maxIndicesOfAnyBits + numIndices) <= MAX_DATA_TEXTURE_HEIGHT * 4096;
|
|
291
|
+
}
|
|
292
|
+
return retVal;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Creates a new portion within this TrianglesDataTextureLayer, returns the new portion ID.
|
|
297
|
+
*
|
|
298
|
+
* Gives the portion the specified geometry, color and matrix.
|
|
299
|
+
*
|
|
300
|
+
* @param mesh The SceneModelMesh that owns the portion
|
|
301
|
+
* @param portionCfg.positionsCompressed Flat float Local-space positionsCompressed array.
|
|
302
|
+
* @param [portionCfg.normals] Flat float normals array.
|
|
303
|
+
* @param [portionCfg.colors] Flat float colors array.
|
|
304
|
+
* @param portionCfg.indices Flat int indices array.
|
|
305
|
+
* @param [portionCfg.edgeIndices] Flat int edges indices array.
|
|
306
|
+
* @param portionCfg.color Quantized RGB color [0..255,0..255,0..255,0..255]
|
|
307
|
+
* @param portionCfg.opacity Opacity [0..255]
|
|
308
|
+
* @param [portionCfg.meshMatrix] Flat float 4x4 matrix - transforms the portion within the coordinate system that's local to the SceneModel
|
|
309
|
+
* @param portionCfg.worldAABB Flat float AABB World-space AABB
|
|
310
|
+
* @param portionCfg.pickColor Quantized pick color
|
|
311
|
+
* @returns {number} Portion ID
|
|
312
|
+
*/
|
|
313
|
+
createPortion(mesh, portionCfg) {
|
|
314
|
+
const buffer = this._buffer;
|
|
315
|
+
// const portionAABB = portionCfg.worldAABB;
|
|
316
|
+
const subPortionIds = portionCfg.buckets.map((bucket, bucketIndex) => {
|
|
317
|
+
const bucketGeometryId = (portionCfg.geometryId ?? portionCfg.id) + "#" + bucketIndex;
|
|
318
|
+
// const subPortionAABB = math.collapseAABB3(tempAABB3b);
|
|
319
|
+
if (! (bucketGeometryId in this._bucketGeometries)) {
|
|
320
|
+
const aligned = (indices, elementSize, statsProp) => {
|
|
321
|
+
// Indices and EdgeIndices alignement
|
|
322
|
+
// This will make every mesh consume a multiple of INDICES_EDGE_INDICES_ALIGNEMENT_SIZE
|
|
323
|
+
// array items for storing the triangles and edges of the mesh, and it supports:
|
|
324
|
+
// - a memory optimization of factor INDICES_EDGE_INDICES_ALIGNEMENT_SIZE
|
|
325
|
+
// - in exchange for a small RAM overhead
|
|
326
|
+
// (by adding some padding until a size that is multiple of INDICES_EDGE_INDICES_ALIGNEMENT_SIZE)
|
|
327
|
+
if (indices) {
|
|
328
|
+
const alignedLen = Math.ceil((indices.length / elementSize) / INDICES_EDGE_INDICES_ALIGNEMENT_SIZE) * INDICES_EDGE_INDICES_ALIGNEMENT_SIZE * elementSize;
|
|
329
|
+
const alignedArray = new Uint32Array(alignedLen);
|
|
330
|
+
alignedArray.set(indices);
|
|
331
|
+
dataTextureRamStats[statsProp] += 2 * (alignedArray.length - indices.length);
|
|
332
|
+
return alignedArray;
|
|
333
|
+
} else {
|
|
334
|
+
return indices;
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
bucket.indices = aligned(bucket.indices, 3, "overheadSizeAlignementIndices");
|
|
339
|
+
bucket.edgeIndices = aligned(bucket.edgeIndices, 2, "overheadSizeAlignementEdgeIndices");
|
|
340
|
+
|
|
341
|
+
const positionsCompressed = bucket.positionsCompressed;
|
|
342
|
+
buffer.positionsCompressed.push(positionsCompressed);
|
|
343
|
+
const numVertices = positionsCompressed.length / 3;
|
|
344
|
+
this._numVertices += numVertices;
|
|
345
|
+
const vertexBase = buffer.lenPositionsCompressed / 3;
|
|
346
|
+
buffer.lenPositionsCompressed += positionsCompressed.length;
|
|
347
|
+
|
|
348
|
+
this._bucketGeometries[bucketGeometryId] = {
|
|
349
|
+
vertexBase: vertexBase,
|
|
350
|
+
geometryData: (function() {
|
|
351
|
+
const indices = bucket.indices;
|
|
352
|
+
const edgeIndices = bucket.edgeIndices;
|
|
353
|
+
if (numVertices <= (1 << 8)) {
|
|
354
|
+
return buffer.geometry8Bits.accumulateIndices( indices, edgeIndices);
|
|
355
|
+
} else if (numVertices <= (1 << 16)) {
|
|
356
|
+
return buffer.geometry16Bits.accumulateIndices(indices, edgeIndices);
|
|
357
|
+
} else {
|
|
358
|
+
return buffer.geometry32Bits.accumulateIndices(indices, edgeIndices);
|
|
359
|
+
}
|
|
360
|
+
})()
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
//math.expandAABB3(portionAABB, subPortionAABB);
|
|
365
|
+
const bucketGeometry = this._bucketGeometries[bucketGeometryId];
|
|
366
|
+
buffer.perObjectPositionsDecodeMatrices.push(portionCfg.positionsDecodeMatrix);
|
|
367
|
+
buffer.perObjectInstancePositioningMatrices.push(portionCfg.meshMatrix || DEFAULT_MATRIX);
|
|
368
|
+
buffer.perObjectSolid.push(!!portionCfg.solid);
|
|
369
|
+
buffer.perObjectPickColors.push(portionCfg.pickColor);
|
|
370
|
+
buffer.perObjectVertexBases.push(bucketGeometry.vertexBase);
|
|
371
|
+
|
|
372
|
+
const colors = portionCfg.colors;
|
|
373
|
+
const color = portionCfg.color; // Color is pre-quantized by SceneModel
|
|
374
|
+
buffer.perObjectColors.push(colors
|
|
375
|
+
? [ colors[0] * 255, colors[1] * 255, colors[2] * 255, 255 ]
|
|
376
|
+
: [ color[0], color[1], color[2], portionCfg.opacity ]);
|
|
377
|
+
|
|
378
|
+
const subPortionId = this._portions.length;
|
|
379
|
+
this._portions.push({ });
|
|
380
|
+
bucketGeometry.geometryData.accumulateSubPortionId(subPortionId);
|
|
381
|
+
|
|
382
|
+
if (this._subPortionReadableGeometries) {
|
|
383
|
+
this._subPortionReadableGeometries[subPortionId] = {
|
|
384
|
+
indices: bucket.indices,
|
|
385
|
+
positionsCompressed: bucket.positionsCompressed,
|
|
386
|
+
positionsDecodeMatrix: portionCfg.positionsDecodeMatrix
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
dataTextureRamStats.numberOfPortions++;
|
|
391
|
+
|
|
392
|
+
return subPortionId;
|
|
393
|
+
});
|
|
394
|
+
const portionId = this._portionToSubPortionsMap.length;
|
|
395
|
+
this._portionToSubPortionsMap.push(subPortionIds);
|
|
396
|
+
this.model.numPortions++;
|
|
397
|
+
this._meshes.push(mesh);
|
|
398
|
+
return portionId;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Builds data textures from the appended geometries and loads them into the GPU.
|
|
403
|
+
*
|
|
404
|
+
* No more portions can then be created.
|
|
405
|
+
*/
|
|
406
|
+
compilePortions() {
|
|
407
|
+
const buffer = this._buffer;
|
|
408
|
+
const model = this.model;
|
|
409
|
+
const numPortions = this._portions.length;
|
|
410
|
+
const origin = this.origin;
|
|
411
|
+
const portionToSubPortionsMap = this._portionToSubPortionsMap;
|
|
412
|
+
const primitive = this._primitive;
|
|
413
|
+
const sortId = this._sortId;
|
|
414
|
+
const subPortionReadableGeometries = this._subPortionReadableGeometries;
|
|
415
|
+
|
|
416
|
+
const scene = model.scene;
|
|
417
|
+
const gl = scene.canvas.gl;
|
|
418
|
+
|
|
419
|
+
/*
|
|
420
|
+
* Texture that holds colors/pickColors/flags/flags2 per-object:
|
|
421
|
+
* - columns: one concept per column => color / pick-color / ...
|
|
422
|
+
* - row: the object Id
|
|
423
|
+
* The texture will have:
|
|
424
|
+
* - 4 RGBA columns per row: for each object (pick) color and flags(2)
|
|
425
|
+
* - N rows where N is the number of objects
|
|
426
|
+
*/
|
|
427
|
+
const populateTexArray = texArray => {
|
|
428
|
+
const pack32as4x8 = ui32 => [
|
|
429
|
+
(ui32 >> 24) & 255,
|
|
430
|
+
(ui32 >> 16) & 255,
|
|
431
|
+
(ui32 >> 8) & 255,
|
|
432
|
+
(ui32) & 255
|
|
433
|
+
];
|
|
434
|
+
for (let i = 0; i < numPortions; i++) {
|
|
435
|
+
// 8 columns per texture row:
|
|
436
|
+
texArray.set(buffer.perObjectColors[i], i * 32 + 0); // (RGBA)
|
|
437
|
+
texArray.set(buffer.perObjectPickColors[i], i * 32 + 4); // (packed Uint32 as RGBA)
|
|
438
|
+
texArray.set([0, 0, 0, 0], /* flags */ i * 32 + 8); // (packed 4 bytes as RGBA)
|
|
439
|
+
texArray.set([0, 0, 0, 0], /* flags2 */ i * 32 + 12); // (packed 4 bytes as RGBA)
|
|
440
|
+
texArray.set(pack32as4x8(buffer.perObjectVertexBases[i]), i * 32 + 16); // (packed Uint32 bytes as RGBA)
|
|
441
|
+
texArray.set(pack32as4x8(buffer.perObjectIndexBaseOffsets[i]), i * 32 + 20); // (packed Uint32 bytes as RGBA)
|
|
442
|
+
texArray.set(pack32as4x8(buffer.perObjectEdgeIndexBaseOffsets[i]), i * 32 + 24); // (packed Uint32 bytes as RGBA)
|
|
443
|
+
texArray.set([buffer.perObjectSolid[i] ? 1 : 0, 0, 0, 0], i * 32 + 28); // (packed 4 bytes as RGBA)
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
// The number of rows in the texture is the number of objects in the layer.
|
|
448
|
+
const texturePerObjectColorsAndFlags = createBindableDataTexture(gl, numPortions, 32, gl.UNSIGNED_BYTE, 512, populateTexArray, "sizeDataColorsAndFlags", true);
|
|
449
|
+
const texturePerObjectColorsAndFlagsData = texturePerObjectColorsAndFlags.textureData;
|
|
450
|
+
|
|
451
|
+
const createDataTexture = function(dataArrays, entitiesCnt, entitySize, type, entitiesPerRow, statsProp, exposeData) {
|
|
452
|
+
const populateTexArray = texArray => {
|
|
453
|
+
for (let i = 0, j = 0, len = dataArrays.length; i < len; i++) {
|
|
454
|
+
const pc = dataArrays[i];
|
|
455
|
+
texArray.set(pc, j);
|
|
456
|
+
j += pc.length;
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
return createBindableDataTexture(gl, entitiesCnt, entitySize, type, entitiesPerRow, populateTexArray, statsProp, exposeData);
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
const createTextureForMatrices = function(matrices, statsProp, exposeData) {
|
|
463
|
+
const numMatrices = matrices.length;
|
|
464
|
+
if (numMatrices === 0) {
|
|
465
|
+
throw "num " + statsProp + " matrices===0";
|
|
466
|
+
}
|
|
467
|
+
// in one row we can fit 512 matrices
|
|
468
|
+
return createDataTexture(matrices, numMatrices, 16, gl.FLOAT, 512, statsProp, exposeData);
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* This will generate a texture for all positions decode matrices in the layer.
|
|
473
|
+
* The texture will have:
|
|
474
|
+
* - 4 RGBA columns per row (each column will contain 4 packed half-float (16 bits) components).
|
|
475
|
+
* Thus, each row will contain 16 packed half-floats corresponding to a complete positions decode matrix)
|
|
476
|
+
* - N rows where N is the number of objects
|
|
477
|
+
*/
|
|
478
|
+
const texturePerObjectInstanceMatrices = createTextureForMatrices(buffer.perObjectInstancePositioningMatrices, "sizeDataInstancesMatrices", true);
|
|
479
|
+
const texturePerObjectInstanceMatricesData = texturePerObjectInstanceMatrices.textureData;
|
|
480
|
+
|
|
481
|
+
/*
|
|
482
|
+
* Texture that holds the objectDecodeAndInstanceMatrix per-object:
|
|
483
|
+
* - columns: each column is one column of the matrix
|
|
484
|
+
* - row: the object Id
|
|
485
|
+
* The texture will have:
|
|
486
|
+
* - 4 RGBA columns per row (each column will contain 4 packed half-float (16 bits) components).
|
|
487
|
+
* Thus, each row will contain 16 packed half-floats corresponding to a complete positions decode matrix)
|
|
488
|
+
* - N rows where N is the number of objects
|
|
489
|
+
*/
|
|
490
|
+
const texturePerObjectPositionsDecodeMatrix = createTextureForMatrices(buffer.perObjectPositionsDecodeMatrices, "sizeDataPositionDecodeMatrices", false);
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
const createTextureForSingleItems = function(dataArrays, dataCnt, entitySize, type, statsProp) {
|
|
494
|
+
return createDataTexture(dataArrays, dataCnt / entitySize, entitySize, type, 4096, statsProp, false);
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
/*
|
|
498
|
+
* Texture that holds all the `different-vertices` used by the layer.
|
|
499
|
+
* This will generate a texture for positions in the layer.
|
|
500
|
+
*
|
|
501
|
+
* The texture will have:
|
|
502
|
+
* - 1024 columns, where each pixel will be a 16-bit-per-component RGB texture, corresponding to the XYZ of the position
|
|
503
|
+
* - a number of rows R where R*1024 is just >= than the number of vertices (positions / 3)
|
|
504
|
+
*/
|
|
505
|
+
const texturePerVertexIdCoordinates = createTextureForSingleItems(
|
|
506
|
+
buffer.positionsCompressed, buffer.lenPositionsCompressed, 3, gl.UNSIGNED_SHORT, "sizeDataTexturePositions");
|
|
507
|
+
|
|
508
|
+
const draw8 = buffer.geometry8Bits.createDrawers( createTextureForSingleItems, gl.UNSIGNED_BYTE);
|
|
509
|
+
const draw16 = buffer.geometry16Bits.createDrawers(createTextureForSingleItems, gl.UNSIGNED_SHORT);
|
|
510
|
+
const draw32 = buffer.geometry32Bits.createDrawers(createTextureForSingleItems, gl.UNSIGNED_INT);
|
|
511
|
+
|
|
512
|
+
// Free up memory
|
|
513
|
+
this._buffer = null;
|
|
514
|
+
|
|
515
|
+
let deferredSetFlagsActive = false;
|
|
516
|
+
let deferredSetFlagsDirty = false;
|
|
517
|
+
let destroyed = false;
|
|
518
|
+
let numUpdatesInFrame = 0;
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* This will _start_ a "set-flags transaction".
|
|
523
|
+
*
|
|
524
|
+
* After invoking this method, calling setFlags/setFlags2 will not update
|
|
525
|
+
* the colors+flags texture but only store the new flags/flag2 in the
|
|
526
|
+
* colors+flags texture data array.
|
|
527
|
+
*
|
|
528
|
+
* After invoking this method, and when all desired setFlags/setFlags2 have
|
|
529
|
+
* been called on needed portions of the layer, invoke `uploadDeferredFlags`
|
|
530
|
+
* to actually upload the data array into the texture.
|
|
531
|
+
*
|
|
532
|
+
* In massive "set-flags" scenarios like VFC or LOD mechanisms, the combination of
|
|
533
|
+
* `beginDeferredFlags` + `uploadDeferredFlags`brings a speed-up of
|
|
534
|
+
* up to 80x when e.g. objects are massively (un)culled 🚀.
|
|
535
|
+
*/
|
|
536
|
+
const beginDeferredFlags = () => { deferredSetFlagsActive = true; };
|
|
537
|
+
|
|
538
|
+
const onSceneRendering = scene.on("rendering", () => {
|
|
539
|
+
if (deferredSetFlagsDirty) {
|
|
540
|
+
// uploadDeferredFlags
|
|
541
|
+
/**
|
|
542
|
+
* This will _commit_ a "set-flags transaction".
|
|
543
|
+
* Invoking this method will update the colors+flags texture data with new
|
|
544
|
+
* flags/flags2 set since the previous invocation of `beginDeferredFlags`.
|
|
545
|
+
*/
|
|
546
|
+
deferredSetFlagsActive = false;
|
|
547
|
+
deferredSetFlagsDirty = false;
|
|
548
|
+
texturePerObjectColorsAndFlagsData.reloadData();
|
|
549
|
+
}
|
|
550
|
+
numUpdatesInFrame = 0;
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
const forEachSubPortionId = (portionId, cb) => {
|
|
554
|
+
const subPortionIds = portionToSubPortionsMap[portionId];
|
|
555
|
+
if (!subPortionIds) {
|
|
556
|
+
model.error("portion not found: " + portionId);
|
|
557
|
+
} else {
|
|
558
|
+
for (let i = 0, len = subPortionIds.length; i < len; i++) {
|
|
559
|
+
cb(subPortionIds[i]);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
const setPortionColorsAndFlags = (subPortionId, offset, data, deferred) => {
|
|
565
|
+
const defer = deferredSetFlagsActive || deferred;
|
|
566
|
+
if (defer) {
|
|
567
|
+
deferredSetFlagsDirty = true;
|
|
568
|
+
} else if (++numUpdatesInFrame >= MAX_OBJECT_UPDATES_IN_FRAME_WITHOUT_BATCHED_UPDATE) {
|
|
569
|
+
beginDeferredFlags(); // Subsequent flags updates now deferred
|
|
570
|
+
}
|
|
571
|
+
texturePerObjectColorsAndFlagsData.setData(data, subPortionId, offset, !defer);
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
const setFlags2 = (portionId, flags, deferred = false) => {
|
|
575
|
+
tempUint8Array4.set([ (flags & ENTITY_FLAGS.CLIPPABLE) ? 255 : 0, 0, 1, 2 ]);
|
|
576
|
+
forEachSubPortionId(portionId, subPortionId => setPortionColorsAndFlags(subPortionId, 3, tempUint8Array4, deferred));
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
return {
|
|
580
|
+
edgesColorOpaqueAllowed: () => {
|
|
581
|
+
if (scene.logarithmicDepthBufferEnabled) {
|
|
582
|
+
if (!scene._loggedWarning) {
|
|
583
|
+
console.log("Edge enhancement for SceneModel data texture layers currently disabled with logarithmic depth buffer");
|
|
584
|
+
scene._loggedWarning = true;
|
|
585
|
+
}
|
|
586
|
+
return false;
|
|
587
|
+
} else {
|
|
588
|
+
return true;
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
sortId: sortId,
|
|
592
|
+
setClippableFlags: setFlags2,
|
|
593
|
+
setFlags: (portionId, flags, transparent, deferred = false) => {
|
|
594
|
+
getColSilhEdgePickFlags(flags, transparent, true, scene, tempUint8Array4);
|
|
595
|
+
forEachSubPortionId(portionId, subPortionId => setPortionColorsAndFlags(subPortionId, 2, tempUint8Array4, deferred));
|
|
596
|
+
},
|
|
597
|
+
setFlags2: setFlags2,
|
|
598
|
+
setDeferredFlags: () => { },
|
|
599
|
+
|
|
600
|
+
setColor: (portionId, color) => {
|
|
601
|
+
tempUint8Array4.set(color);
|
|
602
|
+
forEachSubPortionId(portionId, subPortionId => setPortionColorsAndFlags(subPortionId, 0, tempUint8Array4, false));
|
|
603
|
+
},
|
|
604
|
+
setMatrix: (portionId, matrix) => {
|
|
605
|
+
forEachSubPortionId(portionId, subPortionId => {
|
|
606
|
+
const defer = deferredSetFlagsActive;
|
|
607
|
+
if (defer) {
|
|
608
|
+
deferredSetFlagsDirty = true;
|
|
609
|
+
} else if (++numUpdatesInFrame >= MAX_OBJECT_UPDATES_IN_FRAME_WITHOUT_BATCHED_UPDATE) {
|
|
610
|
+
beginDeferredFlags(); // Subsequent flags updates now deferred
|
|
611
|
+
}
|
|
612
|
+
tempMat4a.set(matrix);
|
|
613
|
+
texturePerObjectInstanceMatricesData.setData(tempMat4a, subPortionId, 0, !defer);
|
|
614
|
+
});
|
|
615
|
+
},
|
|
616
|
+
setOffset: (portionId, offset) => { /* NOT COMPLETE */ },
|
|
617
|
+
|
|
618
|
+
getEachIndex: (portionId, callback) => {
|
|
619
|
+
if (subPortionReadableGeometries) {
|
|
620
|
+
forEachSubPortionId(
|
|
621
|
+
portionId,
|
|
622
|
+
subPortionId => subPortionReadableGeometries[subPortionId].indices.forEach(i => callback(i)));
|
|
623
|
+
}
|
|
624
|
+
},
|
|
625
|
+
getEachVertex: (portionId, callback) => {
|
|
626
|
+
if (subPortionReadableGeometries) {
|
|
627
|
+
forEachSubPortionId(portionId, subPortionId => {
|
|
628
|
+
const subPortionReadableGeometry = subPortionReadableGeometries[subPortionId];
|
|
629
|
+
const positions = subPortionReadableGeometry.positionsCompressed;
|
|
630
|
+
const positionsDecodeMatrix = subPortionReadableGeometry.positionsDecodeMatrix;
|
|
631
|
+
const worldPos = tempVec4a;
|
|
632
|
+
for (let i = 0, len = positions.length; i < len; i += 3) {
|
|
633
|
+
worldPos[0] = positions[i];
|
|
634
|
+
worldPos[1] = positions[i + 1];
|
|
635
|
+
worldPos[2] = positions[i + 2];
|
|
636
|
+
worldPos[3] = 1.0;
|
|
637
|
+
math.decompressPosition(worldPos, positionsDecodeMatrix);
|
|
638
|
+
math.mulMat4v4(model.worldMatrix, worldPos, worldPos);
|
|
639
|
+
math.addVec3(origin, worldPos, worldPos);
|
|
640
|
+
callback(worldPos);
|
|
641
|
+
}
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
},
|
|
645
|
+
precisionRayPickSurface: (portionId, worldRayOrigin, worldRayDir, worldSurfacePos, worldNormal) => false,
|
|
646
|
+
|
|
647
|
+
renderers: getRenderers(scene, "dtx", primitive, model.saoEnabled, false, false, true,
|
|
648
|
+
(programVariables, subGeometry) => makeDTXRenderingAttributes(programVariables, !subGeometry)),
|
|
649
|
+
drawCalls: (function() {
|
|
650
|
+
const drawer = function(drawCall) {
|
|
651
|
+
const setInputValue = (input, value) => (input.setInputValue && input.setInputValue(value));
|
|
652
|
+
return (attributesHash, layerTypeInputs, viewState) => {
|
|
653
|
+
setInputValue(layerTypeInputs.worldMatrix, model.rotationMatrix);
|
|
654
|
+
setInputValue(layerTypeInputs.viewMatrix, viewState.viewMatrix);
|
|
655
|
+
setInputValue(layerTypeInputs.projMatrix, viewState.projMatrix);
|
|
656
|
+
const rtcOrigin = math.transformPoint3(model.matrix, origin, tempVec3);
|
|
657
|
+
setInputValue(layerTypeInputs.uCameraEyeRtc, math.subVec3(viewState.eye, rtcOrigin, tempVec3a));
|
|
658
|
+
setInputValue(layerTypeInputs.perObjPosDecode, texturePerObjectPositionsDecodeMatrix);
|
|
659
|
+
setInputValue(layerTypeInputs.perVertIdCoords, texturePerVertexIdCoordinates);
|
|
660
|
+
setInputValue(layerTypeInputs.perObjColsFlags, texturePerObjectColorsAndFlags);
|
|
661
|
+
setInputValue(layerTypeInputs.perObjectMatrix, texturePerObjectInstanceMatrices);
|
|
662
|
+
drawCall(layerTypeInputs);
|
|
663
|
+
};
|
|
664
|
+
};
|
|
665
|
+
|
|
666
|
+
const vertEdgesDrawer = function(glMode) {
|
|
667
|
+
return drawer((layerTypeInputs) => {
|
|
668
|
+
draw8.edges( layerTypeInputs, glMode);
|
|
669
|
+
draw16.edges(layerTypeInputs, glMode);
|
|
670
|
+
draw32.edges(layerTypeInputs, glMode);
|
|
671
|
+
});
|
|
672
|
+
};
|
|
673
|
+
|
|
674
|
+
return {
|
|
675
|
+
drawVertices: vertEdgesDrawer(gl.POINTS),
|
|
676
|
+
drawEdges: vertEdgesDrawer(gl.LINES),
|
|
677
|
+
drawSurface: drawer((layerTypeInputs) => {
|
|
678
|
+
const glMode = gl.TRIANGLES;
|
|
679
|
+
draw8.indices( layerTypeInputs, glMode);
|
|
680
|
+
draw16.indices(layerTypeInputs, glMode);
|
|
681
|
+
draw32.indices(layerTypeInputs, glMode);
|
|
682
|
+
})
|
|
683
|
+
};
|
|
684
|
+
})(),
|
|
685
|
+
|
|
686
|
+
destroy: () => {
|
|
687
|
+
if (! destroyed) {
|
|
688
|
+
scene.off(onSceneRendering);
|
|
689
|
+
destroyed = true;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
const createBindableDataTexture = function(gl, entitiesCnt, entitySize, type, entitiesPerRow, populateTexArray, statsProp, exposeData) {
|
|
697
|
+
if ((entitySize > 4) && ((entitySize % 4) > 0)) {
|
|
698
|
+
throw "Unhandled data size " + entitySize;
|
|
699
|
+
}
|
|
700
|
+
const pixelsPerEntity = Math.ceil(entitySize / 4);
|
|
701
|
+
const pixelWidth = entitySize / pixelsPerEntity;
|
|
702
|
+
|
|
703
|
+
const [ arrayType, internalFormat, format ] = (function() {
|
|
704
|
+
switch(type) {
|
|
705
|
+
case gl.UNSIGNED_BYTE:
|
|
706
|
+
return [ Uint8Array, ...((pixelWidth === 1) ? [ gl.R8UI, gl.RED_INTEGER ] : ((pixelWidth === 2) ? [ gl.RG8UI, gl.RG_INTEGER ] : ((pixelWidth === 3) ? [ gl.RGB8UI, gl.RGB_INTEGER ] : [ gl.RGBA8UI, gl.RGBA_INTEGER ]))) ];
|
|
707
|
+
case gl.UNSIGNED_SHORT:
|
|
708
|
+
return [ Uint16Array, ...((pixelWidth === 1) ? [ gl.R16UI, gl.RED_INTEGER ] : ((pixelWidth === 2) ? [ gl.RG16UI, gl.RG_INTEGER ] : ((pixelWidth === 3) ? [ gl.RGB16UI, gl.RGB_INTEGER ] : [ gl.RGBA16UI, gl.RGBA_INTEGER ]))) ];
|
|
709
|
+
case gl.UNSIGNED_INT:
|
|
710
|
+
return [ Uint32Array, ...((pixelWidth === 1) ? [ gl.R32UI, gl.RED_INTEGER ] : ((pixelWidth === 2) ? [ gl.RG32UI, gl.RG_INTEGER ] : ((pixelWidth === 3) ? [ gl.RGB32UI, gl.RGB_INTEGER ] : [ gl.RGBA32UI, gl.RGBA_INTEGER ]))) ];
|
|
711
|
+
case gl.FLOAT:
|
|
712
|
+
return [ Float32Array, ...((pixelWidth === 1) ? [ gl.R32F, gl.RED ] : ((pixelWidth === 2) ? [ gl.RG32F, gl.RG ] : ((pixelWidth === 3) ? [ gl.RGB32F, gl.RGB ] : [ gl.RGBA32F, gl.RGBA ]))) ];
|
|
713
|
+
default:
|
|
714
|
+
throw "Unhandled data type " + type;
|
|
715
|
+
}
|
|
716
|
+
})();
|
|
717
|
+
|
|
718
|
+
const textureWidth = entitiesPerRow * pixelsPerEntity;
|
|
719
|
+
const textureHeight = Math.ceil(entitiesCnt / entitiesPerRow);
|
|
720
|
+
if (textureHeight === 0) {
|
|
721
|
+
throw "texture height===0";
|
|
722
|
+
}
|
|
723
|
+
const texArray = new arrayType(textureWidth * textureHeight * pixelWidth);
|
|
724
|
+
dataTextureRamStats[statsProp] += texArray.byteLength;
|
|
725
|
+
dataTextureRamStats.numberOfTextures++;
|
|
726
|
+
|
|
727
|
+
populateTexArray(texArray);
|
|
728
|
+
|
|
729
|
+
const texture = gl.createTexture();
|
|
730
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
731
|
+
gl.texStorage2D(gl.TEXTURE_2D, 1, internalFormat, textureWidth, textureHeight);
|
|
732
|
+
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, textureWidth, textureHeight, format, type, texArray);
|
|
733
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
734
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
735
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
736
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
737
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
738
|
+
|
|
739
|
+
return {
|
|
740
|
+
// called by createSampler::bindTexture
|
|
741
|
+
bind(unit) {
|
|
742
|
+
gl.activeTexture(gl["TEXTURE" + unit]);
|
|
743
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
744
|
+
return true;
|
|
745
|
+
},
|
|
746
|
+
|
|
747
|
+
unbind(unit) {
|
|
748
|
+
// This `unbind` method is ignored at the moment to allow avoiding
|
|
749
|
+
// to rebind same texture already bound to a texture unit.
|
|
750
|
+
|
|
751
|
+
// this._gl.activeTexture(gl["TEXTURE" + unit]);
|
|
752
|
+
// this._gl.bindTexture(gl.TEXTURE_2D, null);
|
|
753
|
+
},
|
|
754
|
+
|
|
755
|
+
textureData: exposeData && {
|
|
756
|
+
setData(data, subPortionId, offset = 0, load = false) {
|
|
757
|
+
texArray.set(data, subPortionId * entitySize + offset * pixelWidth);
|
|
758
|
+
if (load) {
|
|
759
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
760
|
+
const xoffset = (subPortionId % entitiesPerRow) * pixelsPerEntity + offset;
|
|
761
|
+
const yoffset = Math.floor(subPortionId / entitiesPerRow);
|
|
762
|
+
const width = data.length / pixelWidth;
|
|
763
|
+
gl.texSubImage2D(gl.TEXTURE_2D, 0, xoffset, yoffset, width, 1, format, type, data);
|
|
764
|
+
// gl.bindTexture (gl.TEXTURE_2D, null);
|
|
765
|
+
}
|
|
766
|
+
},
|
|
767
|
+
|
|
768
|
+
reloadData() {
|
|
769
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
770
|
+
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, textureWidth, textureHeight, format, type, texArray);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
};
|
|
775
|
+
|
|
776
|
+
const makeDTXRenderingAttributes = function(programVariables, isTriangle) {
|
|
777
|
+
const setupTex = (type, name) => {
|
|
778
|
+
const map = programVariables.createUniform(type, name);
|
|
779
|
+
const texelFetch = (P) => `texelFetch(${map}, ${P}, 0)`;
|
|
780
|
+
texelFetch.map = map;
|
|
781
|
+
return texelFetch;
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
const perPrimIndices = setupTex("highp usampler2D", "perPrimIndices");
|
|
785
|
+
const perPrimIdPorIds = setupTex("mediump usampler2D", "perPrimIdPorIds");
|
|
786
|
+
|
|
787
|
+
const perObjPosDecode = setupTex("highp sampler2D", "perObjPosDecode");
|
|
788
|
+
const perVertIdCoords = setupTex("mediump usampler2D", "perVertIdCoords");
|
|
789
|
+
const perObjColsFlags = setupTex("lowp usampler2D", "perObjColsFlags");
|
|
790
|
+
const perObjectMatrix = setupTex("highp sampler2D", "perObjectMatrix");
|
|
791
|
+
|
|
792
|
+
const worldMatrix = programVariables.createUniform("mat4", "worldMatrix");
|
|
793
|
+
const viewMatrix = programVariables.createUniform("mat4", "viewMatrix");
|
|
794
|
+
const projMatrix = programVariables.createUniform("mat4", "projMatrix");
|
|
795
|
+
const uCameraEyeRtc = programVariables.createUniform("vec3", "uCameraEyeRtc");
|
|
796
|
+
|
|
797
|
+
const lazyShaderVariable = function(name) {
|
|
798
|
+
const variable = {
|
|
799
|
+
toString: () => {
|
|
800
|
+
variable.needed = true;
|
|
801
|
+
return name;
|
|
802
|
+
}
|
|
803
|
+
};
|
|
804
|
+
return variable;
|
|
805
|
+
};
|
|
806
|
+
|
|
807
|
+
const colorA = lazyShaderVariable("colorA");
|
|
808
|
+
const pickColorA = lazyShaderVariable("pickColor");
|
|
809
|
+
const worldNormal = lazyShaderVariable("worldNormal");
|
|
810
|
+
const viewNormal = lazyShaderVariable("viewNormal");
|
|
811
|
+
|
|
812
|
+
const colorsAndFlags = (offset) => perObjColsFlags(`ivec2(objectIndexCoords.x*8+${offset}, objectIndexCoords.y)`);
|
|
813
|
+
|
|
814
|
+
return {
|
|
815
|
+
geometryParameters: {
|
|
816
|
+
attributes: {
|
|
817
|
+
clippable: "(flags2.r > 0u)",
|
|
818
|
+
color: colorA,
|
|
819
|
+
flags: iota(4).map(i => `int(flags[${i}])`),
|
|
820
|
+
metallicRoughness: null,
|
|
821
|
+
normal: {
|
|
822
|
+
view: viewNormal,
|
|
823
|
+
world: worldNormal
|
|
824
|
+
},
|
|
825
|
+
pickColor: pickColorA,
|
|
826
|
+
position: {
|
|
827
|
+
clip: "gl_Position",
|
|
828
|
+
view: "viewPosition",
|
|
829
|
+
world: "worldPosition"
|
|
830
|
+
},
|
|
831
|
+
uv: null
|
|
832
|
+
},
|
|
833
|
+
projMatrix: projMatrix,
|
|
834
|
+
viewMatrix: viewMatrix
|
|
835
|
+
},
|
|
836
|
+
|
|
837
|
+
ensureColorAndFlagAvailable: (src) => {
|
|
838
|
+
// constants
|
|
839
|
+
src.push("int primitiveIndex = gl_VertexID / " + (isTriangle ? 3 : 2) + ";");
|
|
840
|
+
|
|
841
|
+
// get packed object-id
|
|
842
|
+
src.push("int h_packed_object_id_index = (primitiveIndex >> 3) & 4095;");
|
|
843
|
+
src.push("int v_packed_object_id_index = (primitiveIndex >> 3) >> 12;");
|
|
844
|
+
|
|
845
|
+
src.push(`int objectIndex = int(${perPrimIdPorIds("ivec2(h_packed_object_id_index, v_packed_object_id_index)")}.r);`);
|
|
846
|
+
src.push("ivec2 objectIndexCoords = ivec2(objectIndex % 512, objectIndex / 512);");
|
|
847
|
+
|
|
848
|
+
// get flags & flags2
|
|
849
|
+
src.push(`uvec4 flags = ${colorsAndFlags(2)};`);
|
|
850
|
+
src.push(`uvec4 flags2 = ${colorsAndFlags(3)};`);
|
|
851
|
+
|
|
852
|
+
colorA.needed && src.push(`vec4 ${colorA} = vec4(${colorsAndFlags(0)}) / 255.0;`);
|
|
853
|
+
},
|
|
854
|
+
|
|
855
|
+
appendVertexData: (src) => {
|
|
856
|
+
const objMatrix = (offset) => perObjectMatrix(`ivec2(objectIndexCoords.x*4+${offset}, objectIndexCoords.y)`);
|
|
857
|
+
src.push(`mat4 objectInstanceMatrix = mat4(${objMatrix(0)}, ${objMatrix(1)}, ${objMatrix(2)}, ${objMatrix(3)});`);
|
|
858
|
+
|
|
859
|
+
const posMatrix = (offset) => perObjPosDecode(`ivec2(objectIndexCoords.x*4+${offset}, objectIndexCoords.y)`);
|
|
860
|
+
src.push(`mat4 objectDecodeAndInstanceMatrix = objectInstanceMatrix * mat4(${posMatrix(0)}, ${posMatrix(1)}, ${posMatrix(2)}, ${posMatrix(3)});`);
|
|
861
|
+
|
|
862
|
+
src.push(`ivec4 packedVertexBase = ivec4(${colorsAndFlags(4)});`);
|
|
863
|
+
src.push(`ivec4 packedIndexBaseOffset = ivec4(${colorsAndFlags(isTriangle ? 5 : 6)});`);
|
|
864
|
+
src.push("int indexBaseOffset = (packedIndexBaseOffset.r << 24) + (packedIndexBaseOffset.g << 16) + (packedIndexBaseOffset.b << 8) + packedIndexBaseOffset.a;");
|
|
865
|
+
|
|
866
|
+
src.push("int h_index = (primitiveIndex - indexBaseOffset) & 4095;");
|
|
867
|
+
src.push("int v_index = (primitiveIndex - indexBaseOffset) >> 12;");
|
|
868
|
+
|
|
869
|
+
src.push(`ivec3 vertexIndices = ivec3(${perPrimIndices("ivec2(h_index, v_index)")});`);
|
|
870
|
+
src.push("ivec3 uniqueVertexIndexes = vertexIndices + (packedVertexBase.r << 24) + (packedVertexBase.g << 16) + (packedVertexBase.b << 8) + packedVertexBase.a;");
|
|
871
|
+
|
|
872
|
+
if (isTriangle) {
|
|
873
|
+
src.push("ivec3 indexPositionH = uniqueVertexIndexes & 4095;");
|
|
874
|
+
src.push("ivec3 indexPositionV = uniqueVertexIndexes >> 12;");
|
|
875
|
+
src.push(`uint solid = ${colorsAndFlags(7)}.r;`);
|
|
876
|
+
const vertIdCoords = (idx) => `vec3(${perVertIdCoords(`ivec2(indexPositionH[${idx}], indexPositionV[${idx}])`)})`;
|
|
877
|
+
src.push(`vec3 positions[] = vec3[](${vertIdCoords(0)}, ${vertIdCoords(1)}, ${vertIdCoords(2)});`);
|
|
878
|
+
src.push("vec3 normal = normalize(cross(positions[2] - positions[0], positions[1] - positions[0]));");
|
|
879
|
+
src.push("vec3 position = positions[gl_VertexID % 3];");
|
|
880
|
+
if (worldNormal.needed) { // WARNING: Not thoroughly tested, as not being used at the moment
|
|
881
|
+
src.push(`vec3 worldNormal = -normalize((transpose(inverse(${worldMatrix} * objectDecodeAndInstanceMatrix)) * vec4(normal,1)).xyz);`);
|
|
882
|
+
}
|
|
883
|
+
if (viewNormal.needed) {
|
|
884
|
+
src.push(`vec3 viewNormal = -normalize((transpose(inverse(${viewMatrix} * objectDecodeAndInstanceMatrix)) * vec4(normal,1)).xyz);`);
|
|
885
|
+
}
|
|
886
|
+
// when the geometry is not solid, if needed, flip the triangle winding
|
|
887
|
+
src.push("if (solid != 1u) {");
|
|
888
|
+
src.push(` if (${isPerspectiveMatrix(projMatrix)}) {`);
|
|
889
|
+
src.push(` vec3 uCameraEyeRtcInQuantizedSpace = (inverse(${worldMatrix} * objectDecodeAndInstanceMatrix) * vec4(${uCameraEyeRtc}, 1)).xyz;`);
|
|
890
|
+
src.push(" if (dot(position.xyz - uCameraEyeRtcInQuantizedSpace, normal) < 0.0) {");
|
|
891
|
+
src.push(" position = positions[2 - (gl_VertexID % 3)];");
|
|
892
|
+
if (worldNormal.needed) {
|
|
893
|
+
src.push(" worldNormal = -worldNormal;");
|
|
894
|
+
}
|
|
895
|
+
if (viewNormal.needed) {
|
|
896
|
+
src.push(" viewNormal = -viewNormal;");
|
|
897
|
+
}
|
|
898
|
+
src.push(" }");
|
|
899
|
+
src.push(" } else {");
|
|
900
|
+
if (!viewNormal.needed) {
|
|
901
|
+
src.push(` vec3 viewNormal = -normalize((transpose(inverse(${viewMatrix} * objectDecodeAndInstanceMatrix)) * vec4(normal,1)).xyz);`);
|
|
902
|
+
}
|
|
903
|
+
src.push(" if (viewNormal.z < 0.0) {");
|
|
904
|
+
src.push(" position = positions[2 - (gl_VertexID % 3)];");
|
|
905
|
+
if (worldNormal.needed) {
|
|
906
|
+
src.push(" worldNormal = -worldNormal;");
|
|
907
|
+
}
|
|
908
|
+
if (viewNormal.needed) {
|
|
909
|
+
src.push(" viewNormal = -viewNormal;");
|
|
910
|
+
}
|
|
911
|
+
src.push(" }");
|
|
912
|
+
src.push(" }");
|
|
913
|
+
src.push("}");
|
|
914
|
+
} else {
|
|
915
|
+
src.push("int indexPositionH = uniqueVertexIndexes[gl_VertexID % 2] & 4095;");
|
|
916
|
+
src.push("int indexPositionV = uniqueVertexIndexes[gl_VertexID % 2] >> 12;");
|
|
917
|
+
src.push(`vec3 position = vec3(${perVertIdCoords("ivec2(indexPositionH, indexPositionV)")});`);
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
pickColorA.needed && src.push(`vec4 pickColor = vec4(${colorsAndFlags(1)});`); // TODO: Normalize color "/ 255.0"?
|
|
921
|
+
|
|
922
|
+
src.push(`vec4 worldPosition = ${worldMatrix} * (objectDecodeAndInstanceMatrix * vec4(position, 1.0));`);
|
|
923
|
+
},
|
|
924
|
+
|
|
925
|
+
layerTypeInputs: {
|
|
926
|
+
perPrimIndices: perPrimIndices.map,
|
|
927
|
+
perPrimIdPorIds: perPrimIdPorIds.map,
|
|
928
|
+
|
|
929
|
+
perObjPosDecode: perObjPosDecode.map,
|
|
930
|
+
perVertIdCoords: perVertIdCoords.map,
|
|
931
|
+
perObjColsFlags: perObjColsFlags.map,
|
|
932
|
+
perObjectMatrix: perObjectMatrix.map,
|
|
933
|
+
|
|
934
|
+
worldMatrix: worldMatrix,
|
|
935
|
+
viewMatrix: viewMatrix,
|
|
936
|
+
projMatrix: projMatrix,
|
|
937
|
+
uCameraEyeRtc: uCameraEyeRtc
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
};
|