@xeokit/xeokit-sdk 2.4.1 → 2.4.2-beta-1
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 +139 -76
- package/dist/xeokit-sdk.es.js +139 -76
- package/dist/xeokit-sdk.es5.js +149 -127
- package/dist/xeokit-sdk.min.cjs.js +2 -2
- package/dist/xeokit-sdk.min.es.js +2 -2
- package/dist/xeokit-sdk.min.es5.js +2 -2
- package/package.json +1 -1
- package/src/plugins/LODCullingPlugin/LODCullingPlugin.js +209 -0
- package/src/plugins/LODCullingPlugin/LODManager.js +82 -0
- package/src/plugins/LODCullingPlugin/LODState.js +130 -0
- package/src/plugins/LODCullingPlugin/index.js +1 -0
- package/src/viewer/scene/model/dtx/triangles/DataTextureGenerator.js +72 -44
- package/src/viewer/scene/model/dtx/triangles/TrianglesDataTextureBuffer.js +15 -0
- package/src/viewer/scene/model/dtx/triangles/TrianglesDataTextureLayer.js +39 -29
- package/src/viewer/scene/model/vbo/trianglesInstancing/TrianglesInstancingLayer.js +13 -3
- package/src/viewer/scene/webgl/Renderer2.js +1830 -0
package/package.json
CHANGED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
|
|
2
|
+
import {LODManager} from "./LODManager.js";
|
|
3
|
+
import {Plugin} from "../../viewer";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Manages LOD culling for {@link SceneModel} implementations.
|
|
7
|
+
*/
|
|
8
|
+
export class LODCullingPlugin extends Plugin {
|
|
9
|
+
|
|
10
|
+
constructor(viewer, cfg = {}) {
|
|
11
|
+
|
|
12
|
+
super("LODCulling", viewer);
|
|
13
|
+
|
|
14
|
+
this._scene = viewer.scene;
|
|
15
|
+
this._lodLevels = [2000, 600, 150, 80, 20];
|
|
16
|
+
this._neverCullTypes = [];
|
|
17
|
+
this._neverCullTypesMap = {};
|
|
18
|
+
this._lodManagers = {};
|
|
19
|
+
this._lodManagerList = [];
|
|
20
|
+
|
|
21
|
+
this.enabled = cfg.enabled;
|
|
22
|
+
this.targetFPS = cfg.targetFPS;
|
|
23
|
+
|
|
24
|
+
this._init();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
_init() {
|
|
28
|
+
|
|
29
|
+
const MAX_NUM_TICKS = 4;
|
|
30
|
+
const tickTimeArray = new Array(MAX_NUM_TICKS);
|
|
31
|
+
|
|
32
|
+
let numTick = 0;
|
|
33
|
+
let currentFPS = -1;
|
|
34
|
+
let preRenderTime = Date.now();
|
|
35
|
+
let deltaTime = 0;
|
|
36
|
+
let sceneTick = 0;
|
|
37
|
+
let lastTickCameraMoved = sceneTick;
|
|
38
|
+
|
|
39
|
+
this._scene.on("rendering", () => { // Apply LOD-culling before rendering the scene
|
|
40
|
+
if (currentFPS === -1) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
for (let i = 0, len = this._lodManagerList.length; i < len; i++) {
|
|
44
|
+
this._lodManagerList[i].applyLodCulling(currentFPS);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
this._scene.on("rendered", () => {
|
|
49
|
+
preRenderTime = Date.now();
|
|
50
|
+
window.requestAnimationFrame(() => {
|
|
51
|
+
numTick++;
|
|
52
|
+
const newTime = Date.now();
|
|
53
|
+
deltaTime = newTime - preRenderTime;
|
|
54
|
+
preRenderTime = newTime;
|
|
55
|
+
tickTimeArray[numTick % MAX_NUM_TICKS] = deltaTime;
|
|
56
|
+
let sumTickTimes = 0;
|
|
57
|
+
if (numTick > MAX_NUM_TICKS) {
|
|
58
|
+
for (let i = 0; i < MAX_NUM_TICKS; i++) {
|
|
59
|
+
sumTickTimes += tickTimeArray[i];
|
|
60
|
+
}
|
|
61
|
+
currentFPS = MAX_NUM_TICKS / sumTickTimes * 1000;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
this._scene.camera.on("matrix", () => {
|
|
67
|
+
lastTickCameraMoved = sceneTick;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
this._scene.on("tick", () => {
|
|
71
|
+
if ((sceneTick - lastTickCameraMoved) > 3) {
|
|
72
|
+
for (let i = 0, len = this._lodManagerList.length; i < len; i++) { // Call LOD-culling tasks
|
|
73
|
+
this._lodManagerList[i].resetLodCulling();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
sceneTick++;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
this._onModelLoaded = viewer.scene.on("modelLoaded", (modelId) => {
|
|
80
|
+
const sceneModel = this.viewer.scene.models[modelId];
|
|
81
|
+
if (sceneModel) {
|
|
82
|
+
this._getLODManager(sceneModel);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Sets whether LOD is enabled for the {@link Scene}.
|
|
89
|
+
*
|
|
90
|
+
* Default value is ````false````.
|
|
91
|
+
*
|
|
92
|
+
* @type {Boolean}
|
|
93
|
+
*/
|
|
94
|
+
set enabled(value) {
|
|
95
|
+
value = !!value;
|
|
96
|
+
if (this._enabled === value) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
this._enabled = value;
|
|
100
|
+
this.glRedraw();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Gets whether LOD is enabled for the {@link Scene}.
|
|
105
|
+
*
|
|
106
|
+
* Default value is ````false````.
|
|
107
|
+
*
|
|
108
|
+
* @type {Boolean}
|
|
109
|
+
*/
|
|
110
|
+
get enabled() {
|
|
111
|
+
return this._enabled;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Sets the maximum area that LOD takes into account when checking for possible occlusion for each fragment.
|
|
116
|
+
*
|
|
117
|
+
* Default value is ````30.0````.
|
|
118
|
+
*
|
|
119
|
+
* @type {Number}
|
|
120
|
+
*/
|
|
121
|
+
set targetFPS(value) {
|
|
122
|
+
if (value === undefined || value === null) {
|
|
123
|
+
value = 30.0;
|
|
124
|
+
}
|
|
125
|
+
if (this._targetFPS === value) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
this._targetFPS = value;
|
|
129
|
+
this.glRedraw();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Gets the maximum area that LOD takes into account when checking for possible occlusion for each fragment.
|
|
134
|
+
*
|
|
135
|
+
* Default value is ````30.0````.
|
|
136
|
+
*
|
|
137
|
+
* @type {Number}
|
|
138
|
+
*/
|
|
139
|
+
get targetFPS() {
|
|
140
|
+
return this._targetFPS;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Sets the {@link MetaObject} types that are never culled.
|
|
145
|
+
*
|
|
146
|
+
* Default value is ````[]````.
|
|
147
|
+
*
|
|
148
|
+
* @type {string[]}
|
|
149
|
+
*/
|
|
150
|
+
set neverCullTypes(value) {
|
|
151
|
+
if (value === undefined || value === null) {
|
|
152
|
+
value = [];
|
|
153
|
+
}
|
|
154
|
+
this._neverCullTypes = value;
|
|
155
|
+
this._neverCullTypesMap = {};
|
|
156
|
+
for (let i = 0, len = this._neverCullTypes.length; i < len; i++) {
|
|
157
|
+
this._neverCullTypesMap[this._neverCullTypes[i]] = true;
|
|
158
|
+
}
|
|
159
|
+
// this.glRedraw();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Gets the {@link MetaObject} types that are never culled.
|
|
164
|
+
*
|
|
165
|
+
* Default value is ````[]````.
|
|
166
|
+
*
|
|
167
|
+
* @type {string[]}
|
|
168
|
+
*/
|
|
169
|
+
get neverCullTypes() {
|
|
170
|
+
return this._neverCullTypes;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @private
|
|
175
|
+
* @returns {*|{}}
|
|
176
|
+
*/
|
|
177
|
+
get neverCullTypesMap() {
|
|
178
|
+
return this._neverCullTypesMap;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Called within SceneModel constructors
|
|
183
|
+
* @private
|
|
184
|
+
*/
|
|
185
|
+
_getLODManager(sceneModel) {
|
|
186
|
+
const lodManager = new LODManager(this.scene, sceneModel, this._lodLevels, this._targetFPS);
|
|
187
|
+
this._lodManagers[lodManager.id] = lodManager;
|
|
188
|
+
this._lodManagerList = Object.values(this._lodManagers);
|
|
189
|
+
return lodManager;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Called within SceneModel destructors
|
|
194
|
+
* @private
|
|
195
|
+
*/
|
|
196
|
+
_putLODManager(lodManager) {
|
|
197
|
+
delete this._lodManagers[lodManager.id];
|
|
198
|
+
this._lodManagerList = Object.values(this._lodManagers);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Destroys this component.
|
|
203
|
+
*
|
|
204
|
+
* @private
|
|
205
|
+
*/
|
|
206
|
+
destroy() {
|
|
207
|
+
super.destroy();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {LODState} from "./LODState.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @private
|
|
5
|
+
*/
|
|
6
|
+
export class LODManager {
|
|
7
|
+
|
|
8
|
+
constructor(scene, sceneModel, lodLevels, targetFps) {
|
|
9
|
+
this.id = sceneModel.id;
|
|
10
|
+
this.scene = scene;
|
|
11
|
+
this.sceneModel = sceneModel;
|
|
12
|
+
this.lodState = new LODState(lodLevels, targetFps);
|
|
13
|
+
this.lodState.initializeLodState(sceneModel);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Cull any objects belonging to the current `LOD` level, and increase the `LOD` level.
|
|
18
|
+
*/
|
|
19
|
+
_increaseLODLevelIndex() {
|
|
20
|
+
const lodState = this.lodState;
|
|
21
|
+
if (lodState.lodLevelIndex === lodState.primLODLevels.length) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const entitiesInLOD = lodState.entitiesInLOD [lodState.primLODLevels[lodState.lodLevelIndex]] || [];
|
|
25
|
+
for (let i = 0, len = entitiesInLOD.length; i < len; i++) {
|
|
26
|
+
entitiesInLOD[i].culledLOD = true;
|
|
27
|
+
}
|
|
28
|
+
lodState.lodLevelIndex++;
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Un-cull any objects belonging to the current `LOD` level, and decrease the `LOD` level.
|
|
34
|
+
*/
|
|
35
|
+
_decreaseLODLevelIndex() {
|
|
36
|
+
const lodState = this.lodState;
|
|
37
|
+
if (lodState.lodLevelIndex === 0) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const entitiesInLOD = lodState.entitiesInLOD [lodState.primLODLevels[lodState.lodLevelIndex - 1]] || [];
|
|
41
|
+
for (let i = 0, len = entitiesInLOD.length; i < len; i++) {
|
|
42
|
+
entitiesInLOD[i].culledLOD = false;
|
|
43
|
+
}
|
|
44
|
+
lodState.lodLevelIndex--;
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Apply LOD culling.
|
|
50
|
+
*
|
|
51
|
+
* Will update LOD level, if needed, based on current FPS and target FPS,
|
|
52
|
+
* and then will cull/uncull the needed objects according to the LOD level.
|
|
53
|
+
*
|
|
54
|
+
* @param {number} currentFPS The current FPS (frames per second)
|
|
55
|
+
* @returns {boolean} Whether the LOD level was changed. This is, if some object was culled/unculled.
|
|
56
|
+
*/
|
|
57
|
+
applyLodCulling(currentFPS) {
|
|
58
|
+
let lodState = this.lodState;
|
|
59
|
+
let retVal = false;
|
|
60
|
+
if (currentFPS < lodState.targetFps) {
|
|
61
|
+
if (++lodState.consecutiveFramesWithoutTargetFps > 2) {
|
|
62
|
+
lodState.consecutiveFramesWithoutTargetFps = 0;
|
|
63
|
+
retVal = this._increaseLODLevelIndex();
|
|
64
|
+
}
|
|
65
|
+
} else if (currentFPS > (lodState.targetFps + 4)) {
|
|
66
|
+
if (++lodState.consecutiveFramesWithTargetFps > 2) {
|
|
67
|
+
lodState.consecutiveFramesWithTargetFps = 0;
|
|
68
|
+
retVal = this._decreaseLODLevelIndex();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return retVal;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
resetLodCulling() {
|
|
75
|
+
let retVal = false;
|
|
76
|
+
let decreasedLevel = false;
|
|
77
|
+
do {
|
|
78
|
+
retVal |= (decreasedLevel = this._decreaseLODLevelIndex());
|
|
79
|
+
} while (decreasedLevel);
|
|
80
|
+
return retVal;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import {math} from "../math/math.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Data structure containing pre-initialized `LOD` data.
|
|
5
|
+
*
|
|
6
|
+
* Will be used by the rest of `LOD` related code.
|
|
7
|
+
*
|
|
8
|
+
* @private
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export class LODState {
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {Array<number>} primLODLevels The primtive counts for the LOD levels, for example ```[ 2000, 600, 150, 80, 20 ]```
|
|
15
|
+
* @param {number} targetFps The target FPS (_Frames Per Second_) for the dynamic culling of objects in the different LOD levels.
|
|
16
|
+
*/
|
|
17
|
+
constructor(primLODLevels, targetFps) {
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* An array ordered DESC with the number of primtives allowed in each LOD bucket.
|
|
21
|
+
*
|
|
22
|
+
* @type {Array<number>}
|
|
23
|
+
*/
|
|
24
|
+
this.primLODLevels = primLODLevels;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A computed dictionary for `primtive-number-buckets` where:
|
|
28
|
+
* - key: the number of primtives allowed for the objects in the bucket.
|
|
29
|
+
* - value: all PerformanceNodes that have the number of primtives or more.
|
|
30
|
+
*
|
|
31
|
+
* @type {Map<number, Array<DataTextureSceneModelNode>>}
|
|
32
|
+
*/
|
|
33
|
+
this.entitiesInLOD = {};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* A computed dictionary for `primtive-number-buckets` where:
|
|
37
|
+
* - key: the number of primtives allowed for the objects in the bucket.
|
|
38
|
+
* - value: the sum of primtives counts for all PeformanceNodes in the bucket.
|
|
39
|
+
*
|
|
40
|
+
* @type {Map<number, number>}
|
|
41
|
+
*/
|
|
42
|
+
this.primCountInLOD = {};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The target FPS for the `LOD` mechanism:
|
|
46
|
+
* - if real FPS are below this number, the next `LOD` level will be applied.
|
|
47
|
+
*
|
|
48
|
+
* - if real FPS are...
|
|
49
|
+
* - above this number plus a margin
|
|
50
|
+
* - and for some consecutive frames
|
|
51
|
+
* ... then the previous `LOD` level will be applied.
|
|
52
|
+
*
|
|
53
|
+
* @type {number}
|
|
54
|
+
*/
|
|
55
|
+
this.targetFps = targetFps;
|
|
56
|
+
|
|
57
|
+
// /**
|
|
58
|
+
// * Not used at the moment.
|
|
59
|
+
// */
|
|
60
|
+
// this.restoreTime = LOD_RESTORE_TIME;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Current `LOD` level. Starts at 0.
|
|
64
|
+
*
|
|
65
|
+
* @type {number}
|
|
66
|
+
*/
|
|
67
|
+
this.lodLevelIndex = 0;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Number of consecutive frames in current `LOD` level where FPS was above `targetFps`
|
|
71
|
+
*
|
|
72
|
+
* @type {number}
|
|
73
|
+
*/
|
|
74
|
+
this.consecutiveFramesWithTargetFps = 0;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Number of consecutive frames in current `LOD` level where FPS was below `targetFps`
|
|
78
|
+
*
|
|
79
|
+
* @type {number}
|
|
80
|
+
*/
|
|
81
|
+
this.consecutiveFramesWithoutTargetFps = 0;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @param {SceneModel} sceneModel
|
|
86
|
+
*/
|
|
87
|
+
initializeLodState(sceneModel) {
|
|
88
|
+
const entityList = Object.values(sceneModel.objects);
|
|
89
|
+
if (entityList.length === 0) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const neverCullTypesMap = sceneModel.scene.lod.neverCullTypesMap;
|
|
93
|
+
const metaScene = sceneModel.scene.viewer.metaScene;
|
|
94
|
+
const entitiesInLOD = {};
|
|
95
|
+
const primCountInLOD = {};
|
|
96
|
+
const maxSize = 20;
|
|
97
|
+
const minComplexity = 25;
|
|
98
|
+
|
|
99
|
+
for (let i = 0, len = entityList.length; i < len; i++) {
|
|
100
|
+
const entity = entityList[i];
|
|
101
|
+
const metaObject = metaScene.metaObjects[entity.id];
|
|
102
|
+
if (metaObject && neverCullTypesMap[metaObject.type]) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const entityComplexity = entity.numPrimitives;
|
|
106
|
+
const entitySize = math.getAABB3Diag(entity.aabb);
|
|
107
|
+
// const isCullable = ((minComplexity <= entityComplexity) && (entitySize <= maxSize));
|
|
108
|
+
// if (!isCullable) {
|
|
109
|
+
// continue;
|
|
110
|
+
// }
|
|
111
|
+
let lodLevel = 0, len;
|
|
112
|
+
for (lodLevel = 0, len = this.primLODLevels.length; lodLevel < len; lodLevel++) {
|
|
113
|
+
if (entity.numPrimitives >= this.primLODLevels [lodLevel]) {
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const lodPrims = this.primLODLevels [lodLevel] || 0;
|
|
118
|
+
if (!(lodPrims in entitiesInLOD)) {
|
|
119
|
+
entitiesInLOD [lodPrims] = [];
|
|
120
|
+
}
|
|
121
|
+
entitiesInLOD [lodPrims].push(entity);
|
|
122
|
+
if (!(lodPrims in primCountInLOD)) {
|
|
123
|
+
primCountInLOD [lodPrims] = 0;
|
|
124
|
+
}
|
|
125
|
+
primCountInLOD [lodPrims] += entity.numPrimitives;
|
|
126
|
+
}
|
|
127
|
+
this.entitiesInLOD = entitiesInLOD;
|
|
128
|
+
this.primCountInLOD = primCountInLOD;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./LOD.js";
|
|
@@ -199,16 +199,17 @@ export class DataTextureGenerator {
|
|
|
199
199
|
|
|
200
200
|
/**
|
|
201
201
|
* @param {WebGL2RenderingContext} gl
|
|
202
|
-
* @param
|
|
202
|
+
* @param indicesArrays
|
|
203
|
+
* @param lenIndices
|
|
203
204
|
*
|
|
204
205
|
* @returns {BindableDataTexture}
|
|
205
206
|
*/
|
|
206
|
-
generateTextureFor8BitIndices(gl,
|
|
207
|
-
if (
|
|
207
|
+
generateTextureFor8BitIndices(gl, indicesArrays, lenIndices) {
|
|
208
|
+
if (lenIndices === 0) {
|
|
208
209
|
return {texture: null, textureHeight: 0,};
|
|
209
210
|
}
|
|
210
211
|
const textureWidth = 4096;
|
|
211
|
-
const textureHeight = Math.ceil(
|
|
212
|
+
const textureHeight = Math.ceil(lenIndices / 3 / textureWidth);
|
|
212
213
|
if (textureHeight === 0) {
|
|
213
214
|
throw "texture height===0";
|
|
214
215
|
}
|
|
@@ -216,8 +217,11 @@ export class DataTextureGenerator {
|
|
|
216
217
|
const texArray = new Uint8Array(texArraySize);
|
|
217
218
|
dataTextureRamStats.sizeDataTextureIndices += texArray.byteLength;
|
|
218
219
|
dataTextureRamStats.numberOfTextures++;
|
|
219
|
-
|
|
220
|
-
|
|
220
|
+
for (let i = 0, j = 0, len = indicesArrays.length; i < len; i++) {
|
|
221
|
+
const pc = indicesArrays[i];
|
|
222
|
+
texArray.set(pc, j);
|
|
223
|
+
j += pc.length;
|
|
224
|
+
}
|
|
221
225
|
const texture = gl.createTexture();
|
|
222
226
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
223
227
|
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGB8UI, textureWidth, textureHeight);
|
|
@@ -229,16 +233,17 @@ export class DataTextureGenerator {
|
|
|
229
233
|
|
|
230
234
|
/**
|
|
231
235
|
* @param {WebGL2RenderingContext} gl
|
|
232
|
-
* @param
|
|
236
|
+
* @param indicesArrays
|
|
237
|
+
* @param lenIndices
|
|
233
238
|
*
|
|
234
239
|
* @returns {BindableDataTexture}
|
|
235
240
|
*/
|
|
236
|
-
generateTextureFor16BitIndices(gl,
|
|
237
|
-
if (
|
|
241
|
+
generateTextureFor16BitIndices(gl, indicesArrays, lenIndices) {
|
|
242
|
+
if (lenIndices === 0) {
|
|
238
243
|
return {texture: null, textureHeight: 0,};
|
|
239
244
|
}
|
|
240
245
|
const textureWidth = 4096;
|
|
241
|
-
const textureHeight = Math.ceil(
|
|
246
|
+
const textureHeight = Math.ceil(lenIndices / 3 / textureWidth);
|
|
242
247
|
if (textureHeight === 0) {
|
|
243
248
|
throw "texture height===0";
|
|
244
249
|
}
|
|
@@ -246,8 +251,11 @@ export class DataTextureGenerator {
|
|
|
246
251
|
const texArray = new Uint16Array(texArraySize);
|
|
247
252
|
dataTextureRamStats.sizeDataTextureIndices += texArray.byteLength;
|
|
248
253
|
dataTextureRamStats.numberOfTextures++;
|
|
249
|
-
|
|
250
|
-
|
|
254
|
+
for (let i = 0, j = 0, len = indicesArrays.length; i < len; i++) {
|
|
255
|
+
const pc = indicesArrays[i];
|
|
256
|
+
texArray.set(pc, j);
|
|
257
|
+
j += pc.length;
|
|
258
|
+
}
|
|
251
259
|
const texture = gl.createTexture();
|
|
252
260
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
253
261
|
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGB16UI, textureWidth, textureHeight);
|
|
@@ -259,16 +267,17 @@ export class DataTextureGenerator {
|
|
|
259
267
|
|
|
260
268
|
/**
|
|
261
269
|
* @param {WebGL2RenderingContext} gl
|
|
262
|
-
* @param
|
|
270
|
+
* @param indicesArrays
|
|
271
|
+
* @param lenIndices
|
|
263
272
|
*
|
|
264
273
|
* @returns {BindableDataTexture}
|
|
265
274
|
*/
|
|
266
|
-
generateTextureFor32BitIndices(gl,
|
|
267
|
-
if (
|
|
268
|
-
return {texture: null, textureHeight: 0};
|
|
275
|
+
generateTextureFor32BitIndices(gl, indicesArrays, lenIndices) {
|
|
276
|
+
if (lenIndices === 0) {
|
|
277
|
+
return {texture: null, textureHeight: 0,};
|
|
269
278
|
}
|
|
270
279
|
const textureWidth = 4096;
|
|
271
|
-
const textureHeight = Math.ceil(
|
|
280
|
+
const textureHeight = Math.ceil(lenIndices / 3 / textureWidth);
|
|
272
281
|
if (textureHeight === 0) {
|
|
273
282
|
throw "texture height===0";
|
|
274
283
|
}
|
|
@@ -276,8 +285,11 @@ export class DataTextureGenerator {
|
|
|
276
285
|
const texArray = new Uint32Array(texArraySize);
|
|
277
286
|
dataTextureRamStats.sizeDataTextureIndices += texArray.byteLength;
|
|
278
287
|
dataTextureRamStats.numberOfTextures++;
|
|
279
|
-
|
|
280
|
-
|
|
288
|
+
for (let i = 0, j = 0, len = indicesArrays.length; i < len; i++) {
|
|
289
|
+
const pc = indicesArrays[i];
|
|
290
|
+
texArray.set(pc, j);
|
|
291
|
+
j += pc.length;
|
|
292
|
+
}
|
|
281
293
|
const texture = gl.createTexture();
|
|
282
294
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
283
295
|
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGB32UI, textureWidth, textureHeight);
|
|
@@ -289,16 +301,17 @@ export class DataTextureGenerator {
|
|
|
289
301
|
|
|
290
302
|
/**
|
|
291
303
|
* @param {WebGL2RenderingContext} gl
|
|
292
|
-
* @param
|
|
304
|
+
* @param indicesArrays
|
|
305
|
+
* @param lenIndices
|
|
293
306
|
*
|
|
294
307
|
* @returns {BindableDataTexture}
|
|
295
308
|
*/
|
|
296
|
-
generateTextureFor8BitsEdgeIndices(gl,
|
|
297
|
-
if (
|
|
298
|
-
return {texture: null, textureHeight: 0};
|
|
309
|
+
generateTextureFor8BitsEdgeIndices(gl, indicesArrays, lenIndices) {
|
|
310
|
+
if (lenIndices === 0) {
|
|
311
|
+
return {texture: null, textureHeight: 0,};
|
|
299
312
|
}
|
|
300
313
|
const textureWidth = 4096;
|
|
301
|
-
const textureHeight = Math.ceil(
|
|
314
|
+
const textureHeight = Math.ceil(lenIndices / 2 / textureWidth);
|
|
302
315
|
if (textureHeight === 0) {
|
|
303
316
|
throw "texture height===0";
|
|
304
317
|
}
|
|
@@ -306,8 +319,11 @@ export class DataTextureGenerator {
|
|
|
306
319
|
const texArray = new Uint8Array(texArraySize);
|
|
307
320
|
dataTextureRamStats.sizeDataTextureEdgeIndices += texArray.byteLength;
|
|
308
321
|
dataTextureRamStats.numberOfTextures++;
|
|
309
|
-
|
|
310
|
-
|
|
322
|
+
for (let i = 0, j = 0, len = indicesArrays.length; i < len; i++) {
|
|
323
|
+
const pc = indicesArrays[i];
|
|
324
|
+
texArray.set(pc, j);
|
|
325
|
+
j += pc.length;
|
|
326
|
+
}
|
|
311
327
|
const texture = gl.createTexture();
|
|
312
328
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
313
329
|
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RG8UI, textureWidth, textureHeight);
|
|
@@ -319,16 +335,17 @@ export class DataTextureGenerator {
|
|
|
319
335
|
|
|
320
336
|
/**
|
|
321
337
|
* @param {WebGL2RenderingContext} gl
|
|
322
|
-
* @param
|
|
338
|
+
* @param indicesArrays
|
|
339
|
+
* @param lenIndices
|
|
323
340
|
*
|
|
324
341
|
* @returns {BindableDataTexture}
|
|
325
342
|
*/
|
|
326
|
-
generateTextureFor16BitsEdgeIndices(gl,
|
|
327
|
-
if (
|
|
328
|
-
return {texture: null, textureHeight: 0};
|
|
343
|
+
generateTextureFor16BitsEdgeIndices(gl, indicesArrays, lenIndices) {
|
|
344
|
+
if (lenIndices === 0) {
|
|
345
|
+
return {texture: null, textureHeight: 0,};
|
|
329
346
|
}
|
|
330
347
|
const textureWidth = 4096;
|
|
331
|
-
const textureHeight = Math.ceil(
|
|
348
|
+
const textureHeight = Math.ceil(lenIndices / 2 / textureWidth);
|
|
332
349
|
if (textureHeight === 0) {
|
|
333
350
|
throw "texture height===0";
|
|
334
351
|
}
|
|
@@ -336,8 +353,11 @@ export class DataTextureGenerator {
|
|
|
336
353
|
const texArray = new Uint16Array(texArraySize);
|
|
337
354
|
dataTextureRamStats.sizeDataTextureEdgeIndices += texArray.byteLength;
|
|
338
355
|
dataTextureRamStats.numberOfTextures++;
|
|
339
|
-
|
|
340
|
-
|
|
356
|
+
for (let i = 0, j = 0, len = indicesArrays.length; i < len; i++) {
|
|
357
|
+
const pc = indicesArrays[i];
|
|
358
|
+
texArray.set(pc, j);
|
|
359
|
+
j += pc.length;
|
|
360
|
+
}
|
|
341
361
|
const texture = gl.createTexture();
|
|
342
362
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
343
363
|
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RG16UI, textureWidth, textureHeight);
|
|
@@ -349,16 +369,17 @@ export class DataTextureGenerator {
|
|
|
349
369
|
|
|
350
370
|
/**
|
|
351
371
|
* @param {WebGL2RenderingContext} gl
|
|
352
|
-
* @param
|
|
372
|
+
* @param indicesArrays
|
|
373
|
+
* @param lenIndices
|
|
353
374
|
*
|
|
354
375
|
* @returns {BindableDataTexture}
|
|
355
376
|
*/
|
|
356
|
-
generateTextureFor32BitsEdgeIndices(gl,
|
|
357
|
-
if (
|
|
377
|
+
generateTextureFor32BitsEdgeIndices(gl, indicesArrays, lenIndices) {
|
|
378
|
+
if (lenIndices === 0) {
|
|
358
379
|
return {texture: null, textureHeight: 0,};
|
|
359
380
|
}
|
|
360
381
|
const textureWidth = 4096;
|
|
361
|
-
const textureHeight = Math.ceil(
|
|
382
|
+
const textureHeight = Math.ceil(lenIndices / 2 / textureWidth);
|
|
362
383
|
if (textureHeight === 0) {
|
|
363
384
|
throw "texture height===0";
|
|
364
385
|
}
|
|
@@ -366,8 +387,11 @@ export class DataTextureGenerator {
|
|
|
366
387
|
const texArray = new Uint32Array(texArraySize);
|
|
367
388
|
dataTextureRamStats.sizeDataTextureEdgeIndices += texArray.byteLength;
|
|
368
389
|
dataTextureRamStats.numberOfTextures++;
|
|
369
|
-
|
|
370
|
-
|
|
390
|
+
for (let i = 0, j = 0, len = indicesArrays.length; i < len; i++) {
|
|
391
|
+
const pc = indicesArrays[i];
|
|
392
|
+
texArray.set(pc, j);
|
|
393
|
+
j += pc.length;
|
|
394
|
+
}
|
|
371
395
|
const texture = gl.createTexture();
|
|
372
396
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
373
397
|
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RG32UI, textureWidth, textureHeight);
|
|
@@ -379,7 +403,8 @@ export class DataTextureGenerator {
|
|
|
379
403
|
|
|
380
404
|
/**
|
|
381
405
|
* @param {WebGL2RenderingContext} gl
|
|
382
|
-
* @param {ArrayLike<int>}
|
|
406
|
+
* @param {ArrayLike<int>} positionsArrays Arrays of quantized positions in the layer
|
|
407
|
+
* @param lenPositions
|
|
383
408
|
*
|
|
384
409
|
* This will generate a texture for positions in the layer.
|
|
385
410
|
*
|
|
@@ -389,8 +414,8 @@ export class DataTextureGenerator {
|
|
|
389
414
|
*
|
|
390
415
|
* @returns {BindableDataTexture}
|
|
391
416
|
*/
|
|
392
|
-
generateTextureForPositions(gl,
|
|
393
|
-
const numVertices =
|
|
417
|
+
generateTextureForPositions(gl, positionsArrays, lenPositions) {
|
|
418
|
+
const numVertices = lenPositions / 3;
|
|
394
419
|
const textureWidth = 4096;
|
|
395
420
|
const textureHeight = Math.ceil(numVertices / textureWidth);
|
|
396
421
|
if (textureHeight === 0) {
|
|
@@ -400,8 +425,11 @@ export class DataTextureGenerator {
|
|
|
400
425
|
const texArray = new Uint16Array(texArraySize);
|
|
401
426
|
dataTextureRamStats.sizeDataTexturePositions += texArray.byteLength;
|
|
402
427
|
dataTextureRamStats.numberOfTextures++;
|
|
403
|
-
|
|
404
|
-
|
|
428
|
+
for (let i = 0, j = 0, len = positionsArrays.length; i < len; i++) {
|
|
429
|
+
const pc = positionsArrays[i];
|
|
430
|
+
texArray.set(pc, j);
|
|
431
|
+
j += pc.length;
|
|
432
|
+
}
|
|
405
433
|
const texture = gl.createTexture();
|
|
406
434
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
407
435
|
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGB16UI, textureWidth, textureHeight);
|