@xeokit/xeokit-sdk 2.0.15 → 2.0.16
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.es.js +1461 -1296
- package/dist/xeokit-sdk.min.es.js +1 -1
- package/package.json +1 -1
package/dist/xeokit-sdk.es.js
CHANGED
|
@@ -7020,7 +7020,7 @@ function Core() {
|
|
|
7020
7020
|
/**
|
|
7021
7021
|
* @private
|
|
7022
7022
|
*/
|
|
7023
|
-
this.setRAFEnabled = function(value) {
|
|
7023
|
+
this.setRAFEnabled = function (value) {
|
|
7024
7024
|
if (value === rafEnabled) {
|
|
7025
7025
|
return;
|
|
7026
7026
|
}
|
|
@@ -7030,7 +7030,7 @@ function Core() {
|
|
|
7030
7030
|
clearInterval(interval);
|
|
7031
7031
|
interval = null;
|
|
7032
7032
|
}
|
|
7033
|
-
window.requestAnimationFrame(frame);
|
|
7033
|
+
(window.requestPostAnimationFrame !== undefined) ? window.requestPostAnimationFrame(frame) : requestAnimationFrame(frame);
|
|
7034
7034
|
} else {
|
|
7035
7035
|
interval = setInterval(frame, 16);
|
|
7036
7036
|
}
|
|
@@ -7039,7 +7039,7 @@ function Core() {
|
|
|
7039
7039
|
/**
|
|
7040
7040
|
* @private
|
|
7041
7041
|
*/
|
|
7042
|
-
this.getRAFEnabled = function() {
|
|
7042
|
+
this.getRAFEnabled = function () {
|
|
7043
7043
|
return rafEnabled;
|
|
7044
7044
|
};
|
|
7045
7045
|
|
|
@@ -7126,7 +7126,7 @@ const frame = function () {
|
|
|
7126
7126
|
renderScenes();
|
|
7127
7127
|
lastTime = time;
|
|
7128
7128
|
if (rafEnabled) {
|
|
7129
|
-
window.requestAnimationFrame(frame);
|
|
7129
|
+
(window.requestPostAnimationFrame !== undefined) ? window.requestPostAnimationFrame(frame) : requestAnimationFrame(frame);
|
|
7130
7130
|
}
|
|
7131
7131
|
};
|
|
7132
7132
|
|
|
@@ -7204,7 +7204,7 @@ function renderScenes() {
|
|
|
7204
7204
|
}
|
|
7205
7205
|
|
|
7206
7206
|
if (rafEnabled) {
|
|
7207
|
-
window.requestAnimationFrame(frame);
|
|
7207
|
+
(window.requestPostAnimationFrame !== undefined) ? window.requestPostAnimationFrame(frame) : requestAnimationFrame(frame);
|
|
7208
7208
|
} else {
|
|
7209
7209
|
interval = setInterval(frame, 16);
|
|
7210
7210
|
}
|
|
@@ -11986,13 +11986,6 @@ const WEBGL_CONTEXT_NAMES = [
|
|
|
11986
11986
|
*/
|
|
11987
11987
|
class Canvas extends Component {
|
|
11988
11988
|
|
|
11989
|
-
/**
|
|
11990
|
-
@private
|
|
11991
|
-
*/
|
|
11992
|
-
get type() {
|
|
11993
|
-
return "Canvas";
|
|
11994
|
-
}
|
|
11995
|
-
|
|
11996
11989
|
/**
|
|
11997
11990
|
* @constructor
|
|
11998
11991
|
* @private
|
|
@@ -12060,8 +12053,10 @@ class Canvas extends Component {
|
|
|
12060
12053
|
// If the canvas uses css styles to specify the sizes make sure the basic
|
|
12061
12054
|
// width and height attributes match or the WebGL context will use 300 x 150
|
|
12062
12055
|
|
|
12063
|
-
this.
|
|
12064
|
-
|
|
12056
|
+
this.resolutionScale = cfg.resolutionScale;
|
|
12057
|
+
|
|
12058
|
+
this.canvas.width = Math.round(this.canvas.clientWidth * this._resolutionScale);
|
|
12059
|
+
this.canvas.height = Math.round(this.canvas.clientHeight * this._resolutionScale);
|
|
12065
12060
|
|
|
12066
12061
|
/**
|
|
12067
12062
|
* Boundary of the Canvas in absolute browser window coordinates.
|
|
@@ -12124,6 +12119,8 @@ class Canvas extends Component {
|
|
|
12124
12119
|
|
|
12125
12120
|
// Publish canvas size and position changes on each scene tick
|
|
12126
12121
|
|
|
12122
|
+
let lastResolutionScale = null;
|
|
12123
|
+
|
|
12127
12124
|
let lastWindowWidth = null;
|
|
12128
12125
|
let lastWindowHeight = null;
|
|
12129
12126
|
|
|
@@ -12135,10 +12132,11 @@ class Canvas extends Component {
|
|
|
12135
12132
|
|
|
12136
12133
|
let lastParent = null;
|
|
12137
12134
|
|
|
12138
|
-
this._tick = this.scene.on("tick",
|
|
12135
|
+
this._tick = this.scene.on("tick", () => {
|
|
12139
12136
|
|
|
12140
|
-
const canvas =
|
|
12137
|
+
const canvas = this.canvas;
|
|
12141
12138
|
|
|
12139
|
+
const newResolutionScale = (this._resolutionScale !== lastResolutionScale);
|
|
12142
12140
|
const newWindowSize = (window.innerWidth !== lastWindowWidth || window.innerHeight !== lastWindowHeight);
|
|
12143
12141
|
const newCanvasSize = (canvas.clientWidth !== lastCanvasWidth || canvas.clientHeight !== lastCanvasHeight);
|
|
12144
12142
|
const newCanvasPos = (canvas.offsetLeft !== lastCanvasOffsetLeft || canvas.offsetTop !== lastCanvasOffsetTop);
|
|
@@ -12146,32 +12144,32 @@ class Canvas extends Component {
|
|
|
12146
12144
|
const parent = canvas.parentElement;
|
|
12147
12145
|
const newParent = (parent !== lastParent);
|
|
12148
12146
|
|
|
12149
|
-
if (newWindowSize || newCanvasSize || newCanvasPos || newParent) {
|
|
12147
|
+
if (newResolutionScale || newWindowSize || newCanvasSize || newCanvasPos || newParent) {
|
|
12150
12148
|
|
|
12151
|
-
|
|
12149
|
+
this._spinner._adjustPosition();
|
|
12152
12150
|
|
|
12153
|
-
if (newCanvasSize || newCanvasPos) {
|
|
12151
|
+
if (newResolutionScale || newCanvasSize || newCanvasPos) {
|
|
12154
12152
|
|
|
12155
12153
|
const newWidth = canvas.clientWidth;
|
|
12156
12154
|
const newHeight = canvas.clientHeight;
|
|
12157
12155
|
|
|
12158
12156
|
// TODO: Wasteful to re-count pixel size of each canvas on each canvas' resize
|
|
12159
|
-
if (newCanvasSize) {
|
|
12157
|
+
if (newResolutionScale || newCanvasSize) {
|
|
12160
12158
|
let countPixels = 0;
|
|
12161
12159
|
let scene;
|
|
12162
12160
|
for (const sceneId in core.scenes) {
|
|
12163
12161
|
if (core.scenes.hasOwnProperty(sceneId)) {
|
|
12164
12162
|
scene = core.scenes[sceneId];
|
|
12165
|
-
countPixels += scene.canvas.canvas.clientWidth * scene.canvas.canvas.clientHeight;
|
|
12163
|
+
countPixels += Math.round((scene.canvas.canvas.clientWidth * this._resolutionScale) * (scene.canvas.canvas.clientHeight * this._resolutionScale));
|
|
12166
12164
|
}
|
|
12167
12165
|
}
|
|
12168
12166
|
stats.memory.pixels = countPixels;
|
|
12169
12167
|
|
|
12170
|
-
canvas.width = canvas.clientWidth;
|
|
12171
|
-
canvas.height = canvas.clientHeight;
|
|
12168
|
+
canvas.width = Math.round(canvas.clientWidth * this._resolutionScale);
|
|
12169
|
+
canvas.height = Math.round(canvas.clientHeight * this._resolutionScale);
|
|
12172
12170
|
}
|
|
12173
12171
|
|
|
12174
|
-
const boundary =
|
|
12172
|
+
const boundary = this.boundary;
|
|
12175
12173
|
|
|
12176
12174
|
boundary[0] = canvas.offsetLeft;
|
|
12177
12175
|
boundary[1] = canvas.offsetTop;
|
|
@@ -12184,12 +12182,18 @@ class Canvas extends Component {
|
|
|
12184
12182
|
* @event boundary
|
|
12185
12183
|
* @param value The property's new value
|
|
12186
12184
|
*/
|
|
12187
|
-
|
|
12185
|
+
if (!newResolutionScale) {
|
|
12186
|
+
this.fire("boundary", boundary);
|
|
12187
|
+
}
|
|
12188
12188
|
|
|
12189
12189
|
lastCanvasWidth = newWidth;
|
|
12190
12190
|
lastCanvasHeight = newHeight;
|
|
12191
12191
|
}
|
|
12192
12192
|
|
|
12193
|
+
if (newResolutionScale) {
|
|
12194
|
+
lastResolutionScale = this._resolutionScale;
|
|
12195
|
+
}
|
|
12196
|
+
|
|
12193
12197
|
if (newWindowSize) {
|
|
12194
12198
|
lastWindowWidth = window.innerWidth;
|
|
12195
12199
|
lastWindowHeight = window.innerHeight;
|
|
@@ -12210,6 +12214,122 @@ class Canvas extends Component {
|
|
|
12210
12214
|
});
|
|
12211
12215
|
}
|
|
12212
12216
|
|
|
12217
|
+
/**
|
|
12218
|
+
@private
|
|
12219
|
+
*/
|
|
12220
|
+
get type() {
|
|
12221
|
+
return "Canvas";
|
|
12222
|
+
}
|
|
12223
|
+
|
|
12224
|
+
/**
|
|
12225
|
+
* Gets whether the canvas clear color will be derived from {@link AmbientLight} or {@link Canvas#backgroundColor}
|
|
12226
|
+
* when {@link Canvas#transparent} is ```true```.
|
|
12227
|
+
*
|
|
12228
|
+
* When {@link Canvas#transparent} is ```true``` and this is ````true````, then the canvas clear color will
|
|
12229
|
+
* be taken from the {@link Scene}'s ambient light color.
|
|
12230
|
+
*
|
|
12231
|
+
* When {@link Canvas#transparent} is ```true``` and this is ````false````, then the canvas clear color will
|
|
12232
|
+
* be taken from {@link Canvas#backgroundColor}.
|
|
12233
|
+
*
|
|
12234
|
+
* Default value is ````true````.
|
|
12235
|
+
*
|
|
12236
|
+
* @type {Boolean}
|
|
12237
|
+
*/
|
|
12238
|
+
get backgroundColorFromAmbientLight() {
|
|
12239
|
+
return this._backgroundColorFromAmbientLight;
|
|
12240
|
+
}
|
|
12241
|
+
|
|
12242
|
+
/**
|
|
12243
|
+
* Sets if the canvas background color is derived from an {@link AmbientLight}.
|
|
12244
|
+
*
|
|
12245
|
+
* This only has effect when the canvas is not transparent. When not enabled, the background color
|
|
12246
|
+
* will be the canvas element's HTML/CSS background color.
|
|
12247
|
+
*
|
|
12248
|
+
* Default value is ````true````.
|
|
12249
|
+
*
|
|
12250
|
+
* @type {Boolean}
|
|
12251
|
+
*/
|
|
12252
|
+
set backgroundColorFromAmbientLight(backgroundColorFromAmbientLight) {
|
|
12253
|
+
this._backgroundColorFromAmbientLight = (backgroundColorFromAmbientLight !== false);
|
|
12254
|
+
this.glRedraw();
|
|
12255
|
+
}
|
|
12256
|
+
|
|
12257
|
+
/**
|
|
12258
|
+
* Gets the canvas clear color.
|
|
12259
|
+
*
|
|
12260
|
+
* Default value is ````[1, 1, 1]````.
|
|
12261
|
+
*
|
|
12262
|
+
* @type {Number[]}
|
|
12263
|
+
*/
|
|
12264
|
+
get backgroundColor() {
|
|
12265
|
+
return this._backgroundColor;
|
|
12266
|
+
}
|
|
12267
|
+
|
|
12268
|
+
/**
|
|
12269
|
+
* Sets the canvas clear color.
|
|
12270
|
+
*
|
|
12271
|
+
* Default value is ````[1, 1, 1]````.
|
|
12272
|
+
*
|
|
12273
|
+
* @type {Number[]}
|
|
12274
|
+
*/
|
|
12275
|
+
set backgroundColor(value) {
|
|
12276
|
+
if (value) {
|
|
12277
|
+
this._backgroundColor[0] = value[0];
|
|
12278
|
+
this._backgroundColor[1] = value[1];
|
|
12279
|
+
this._backgroundColor[2] = value[2];
|
|
12280
|
+
} else {
|
|
12281
|
+
this._backgroundColor[0] = 1.0;
|
|
12282
|
+
this._backgroundColor[1] = 1.0;
|
|
12283
|
+
this._backgroundColor[2] = 1.0;
|
|
12284
|
+
}
|
|
12285
|
+
this.glRedraw();
|
|
12286
|
+
}
|
|
12287
|
+
|
|
12288
|
+
/**
|
|
12289
|
+
* Gets the scale of the canvas back buffer relative to the CSS-defined size of the canvas.
|
|
12290
|
+
*
|
|
12291
|
+
* This is a common way to trade off rendering quality for speed. If the canvas size is defined in CSS, then
|
|
12292
|
+
* setting this to a value between ````[0..1]```` (eg ````0.5````) will render into a smaller back buffer, giving
|
|
12293
|
+
* a performance boost.
|
|
12294
|
+
*
|
|
12295
|
+
* @returns {*|number} The resolution scale.
|
|
12296
|
+
*/
|
|
12297
|
+
get resolutionScale() {
|
|
12298
|
+
return this._resolutionScale;
|
|
12299
|
+
}
|
|
12300
|
+
|
|
12301
|
+
/**
|
|
12302
|
+
* Sets the scale of the canvas back buffer relative to the CSS-defined size of the canvas.
|
|
12303
|
+
*
|
|
12304
|
+
* This is a common way to trade off rendering quality for speed. If the canvas size is defined in CSS, then
|
|
12305
|
+
* setting this to a value between ````[0..1]```` (eg ````0.5````) will render into a smaller back buffer, giving
|
|
12306
|
+
* a performance boost.
|
|
12307
|
+
*
|
|
12308
|
+
* @param {*|number} resolutionScale The resolution scale.
|
|
12309
|
+
*/
|
|
12310
|
+
set resolutionScale(resolutionScale) {
|
|
12311
|
+
resolutionScale = resolutionScale || 1.0;
|
|
12312
|
+
if (resolutionScale === this._resolutionScale) {
|
|
12313
|
+
return;
|
|
12314
|
+
}
|
|
12315
|
+
this._resolutionScale = resolutionScale;
|
|
12316
|
+
const canvas = this.canvas;
|
|
12317
|
+
canvas.width = Math.round(canvas.clientWidth * this._resolutionScale);
|
|
12318
|
+
canvas.height = Math.round(canvas.clientHeight * this._resolutionScale);
|
|
12319
|
+
this.glRedraw();
|
|
12320
|
+
}
|
|
12321
|
+
|
|
12322
|
+
/**
|
|
12323
|
+
* The busy {@link Spinner} for this Canvas.
|
|
12324
|
+
*
|
|
12325
|
+
* @property spinner
|
|
12326
|
+
* @type Spinner
|
|
12327
|
+
* @final
|
|
12328
|
+
*/
|
|
12329
|
+
get spinner() {
|
|
12330
|
+
return this._spinner;
|
|
12331
|
+
}
|
|
12332
|
+
|
|
12213
12333
|
/**
|
|
12214
12334
|
* Creates a default canvas in the DOM.
|
|
12215
12335
|
* @private
|
|
@@ -12298,69 +12418,6 @@ class Canvas extends Component {
|
|
|
12298
12418
|
}
|
|
12299
12419
|
}
|
|
12300
12420
|
|
|
12301
|
-
/**
|
|
12302
|
-
* Sets if the canvas background color is derived from an {@link AmbientLight}.
|
|
12303
|
-
*
|
|
12304
|
-
* This only has effect when the canvas is not transparent. When not enabled, the background color
|
|
12305
|
-
* will be the canvas element's HTML/CSS background color.
|
|
12306
|
-
*
|
|
12307
|
-
* Default value is ````true````.
|
|
12308
|
-
*
|
|
12309
|
-
* @type {Boolean}
|
|
12310
|
-
*/
|
|
12311
|
-
set backgroundColorFromAmbientLight(backgroundColorFromAmbientLight) {
|
|
12312
|
-
this._backgroundColorFromAmbientLight = (backgroundColorFromAmbientLight !== false);
|
|
12313
|
-
}
|
|
12314
|
-
|
|
12315
|
-
/**
|
|
12316
|
-
* Gets whether the canvas clear color will be derived from {@link AmbientLight} or {@link Canvas#backgroundColor}
|
|
12317
|
-
* when {@link Canvas#transparent} is ```true```.
|
|
12318
|
-
*
|
|
12319
|
-
* When {@link Canvas#transparent} is ```true``` and this is ````true````, then the canvas clear color will
|
|
12320
|
-
* be taken from the {@link Scene}'s ambient light color.
|
|
12321
|
-
*
|
|
12322
|
-
* When {@link Canvas#transparent} is ```true``` and this is ````false````, then the canvas clear color will
|
|
12323
|
-
* be taken from {@link Canvas#backgroundColor}.
|
|
12324
|
-
*
|
|
12325
|
-
* Default value is ````true````.
|
|
12326
|
-
*
|
|
12327
|
-
* @type {Boolean}
|
|
12328
|
-
*/
|
|
12329
|
-
get backgroundColorFromAmbientLight() {
|
|
12330
|
-
return this._backgroundColorFromAmbientLight;
|
|
12331
|
-
}
|
|
12332
|
-
|
|
12333
|
-
/**
|
|
12334
|
-
* Sets the canvas clear color.
|
|
12335
|
-
*
|
|
12336
|
-
* Default value is ````[1, 1, 1]````.
|
|
12337
|
-
*
|
|
12338
|
-
* @type {Number[]}
|
|
12339
|
-
*/
|
|
12340
|
-
set backgroundColor(value) {
|
|
12341
|
-
if (value) {
|
|
12342
|
-
this._backgroundColor[0] = value[0];
|
|
12343
|
-
this._backgroundColor[1] = value[1];
|
|
12344
|
-
this._backgroundColor[2] = value[2];
|
|
12345
|
-
} else {
|
|
12346
|
-
this._backgroundColor[0] = 1.0;
|
|
12347
|
-
this._backgroundColor[1] = 1.0;
|
|
12348
|
-
this._backgroundColor[2] = 1.0;
|
|
12349
|
-
}
|
|
12350
|
-
this.glRedraw();
|
|
12351
|
-
}
|
|
12352
|
-
|
|
12353
|
-
/**
|
|
12354
|
-
* Gets the canvas clear color.
|
|
12355
|
-
*
|
|
12356
|
-
* Default value is ````[1, 1, 1]````.
|
|
12357
|
-
*
|
|
12358
|
-
* @type {Number[]}
|
|
12359
|
-
*/
|
|
12360
|
-
get backgroundColor() {
|
|
12361
|
-
return this._backgroundColor;
|
|
12362
|
-
}
|
|
12363
|
-
|
|
12364
12421
|
/**
|
|
12365
12422
|
* @private
|
|
12366
12423
|
* @deprecated
|
|
@@ -12404,17 +12461,6 @@ class Canvas extends Component {
|
|
|
12404
12461
|
}
|
|
12405
12462
|
}
|
|
12406
12463
|
|
|
12407
|
-
/**
|
|
12408
|
-
* The busy {@link Spinner} for this Canvas.
|
|
12409
|
-
*
|
|
12410
|
-
* @property spinner
|
|
12411
|
-
* @type Spinner
|
|
12412
|
-
* @final
|
|
12413
|
-
*/
|
|
12414
|
-
get spinner() {
|
|
12415
|
-
return this._spinner;
|
|
12416
|
-
}
|
|
12417
|
-
|
|
12418
12464
|
destroy() {
|
|
12419
12465
|
this.scene.off(this._tick);
|
|
12420
12466
|
this._spinner._destroy();
|
|
@@ -12681,1115 +12727,1115 @@ class FrameContext {
|
|
|
12681
12727
|
}
|
|
12682
12728
|
}
|
|
12683
12729
|
|
|
12684
|
-
|
|
12685
|
-
*
|
|
12686
|
-
* Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com
|
|
12687
|
-
* MIT License [http://www.opensource.org/licenses/mit-license.php]
|
|
12730
|
+
/**
|
|
12731
|
+
* @desc Pick result returned by {@link Scene#pick}.
|
|
12688
12732
|
*
|
|
12689
|
-
* Modified by @xeolabs to permit vertical flipping, so that snapshot can be taken from WebGL frame buffers,
|
|
12690
|
-
* which vertically flip image data as part of the way that WebGL renders textures.
|
|
12691
12733
|
*/
|
|
12734
|
+
class PickResult {
|
|
12692
12735
|
|
|
12693
|
-
/**
|
|
12694
|
-
|
|
12695
|
-
|
|
12696
|
-
|
|
12697
|
-
|
|
12698
|
-
const oCanvas = document.createElement("canvas"), sc = String.fromCharCode;
|
|
12736
|
+
/**
|
|
12737
|
+
* @private
|
|
12738
|
+
* @param value
|
|
12739
|
+
*/
|
|
12740
|
+
constructor() {
|
|
12699
12741
|
|
|
12700
|
-
|
|
12701
|
-
|
|
12702
|
-
|
|
12703
|
-
|
|
12704
|
-
|
|
12705
|
-
|
|
12706
|
-
|
|
12707
|
-
saveAsJPEG: function () {
|
|
12708
|
-
}
|
|
12709
|
-
}
|
|
12710
|
-
}
|
|
12742
|
+
/**
|
|
12743
|
+
* Picked entity.
|
|
12744
|
+
* Null when no entity was picked.
|
|
12745
|
+
* @property entity
|
|
12746
|
+
* @type {Entity|*}
|
|
12747
|
+
*/
|
|
12748
|
+
this.entity = null;
|
|
12711
12749
|
|
|
12712
|
-
|
|
12713
|
-
|
|
12750
|
+
/**
|
|
12751
|
+
* Type of primitive that was picked - usually "triangle".
|
|
12752
|
+
* Null when no primitive was picked.
|
|
12753
|
+
* @property primitive
|
|
12754
|
+
* @type {String}
|
|
12755
|
+
*/
|
|
12756
|
+
this.primitive = null;
|
|
12714
12757
|
|
|
12715
|
-
|
|
12716
|
-
|
|
12717
|
-
|
|
12718
|
-
|
|
12719
|
-
|
|
12758
|
+
/**
|
|
12759
|
+
* Index of primitive that was picked.
|
|
12760
|
+
* -1 when no entity was picked.
|
|
12761
|
+
* @property primIndex
|
|
12762
|
+
* @type {number}
|
|
12763
|
+
*/
|
|
12764
|
+
this.primIndex = -1;
|
|
12720
12765
|
|
|
12721
|
-
|
|
12722
|
-
|
|
12723
|
-
|
|
12766
|
+
/**
|
|
12767
|
+
* True when the picked surface position is full precision.
|
|
12768
|
+
* When false, the picked surface position should be regarded as approximate.
|
|
12769
|
+
* Full-precision surface picking is performed with the {@link Scene#pick} method's ````pickSurfacePrecision```` option.
|
|
12770
|
+
* @property pickSurfacePrecision
|
|
12771
|
+
* @type {Boolean}
|
|
12772
|
+
*/
|
|
12773
|
+
this.pickSurfacePrecision = false;
|
|
12724
12774
|
|
|
12725
|
-
|
|
12726
|
-
|
|
12727
|
-
|
|
12728
|
-
|
|
12729
|
-
|
|
12730
|
-
|
|
12731
|
-
|
|
12732
|
-
|
|
12733
|
-
|
|
12734
|
-
|
|
12735
|
-
|
|
12736
|
-
// creates a base64 encoded string containing BMP data takes an imagedata object as argument
|
|
12737
|
-
const createBMP = function (oData) {
|
|
12738
|
-
let strHeader = '';
|
|
12739
|
-
const iWidth = oData.width;
|
|
12740
|
-
const iHeight = oData.height;
|
|
12741
|
-
|
|
12742
|
-
strHeader += 'BM';
|
|
12743
|
-
|
|
12744
|
-
let iFileSize = iWidth * iHeight * 4 + 54; // total header size = 54 bytes
|
|
12745
|
-
strHeader += sc(iFileSize % 256);
|
|
12746
|
-
iFileSize = Math.floor(iFileSize / 256);
|
|
12747
|
-
strHeader += sc(iFileSize % 256);
|
|
12748
|
-
iFileSize = Math.floor(iFileSize / 256);
|
|
12749
|
-
strHeader += sc(iFileSize % 256);
|
|
12750
|
-
iFileSize = Math.floor(iFileSize / 256);
|
|
12751
|
-
strHeader += sc(iFileSize % 256);
|
|
12752
|
-
|
|
12753
|
-
strHeader += sc(0, 0, 0, 0, 54, 0, 0, 0); // data offset
|
|
12754
|
-
strHeader += sc(40, 0, 0, 0); // info header size
|
|
12755
|
-
|
|
12756
|
-
let iImageWidth = iWidth;
|
|
12757
|
-
strHeader += sc(iImageWidth % 256);
|
|
12758
|
-
iImageWidth = Math.floor(iImageWidth / 256);
|
|
12759
|
-
strHeader += sc(iImageWidth % 256);
|
|
12760
|
-
iImageWidth = Math.floor(iImageWidth / 256);
|
|
12761
|
-
strHeader += sc(iImageWidth % 256);
|
|
12762
|
-
iImageWidth = Math.floor(iImageWidth / 256);
|
|
12763
|
-
strHeader += sc(iImageWidth % 256);
|
|
12764
|
-
|
|
12765
|
-
let iImageHeight = iHeight;
|
|
12766
|
-
strHeader += sc(iImageHeight % 256);
|
|
12767
|
-
iImageHeight = Math.floor(iImageHeight / 256);
|
|
12768
|
-
strHeader += sc(iImageHeight % 256);
|
|
12769
|
-
iImageHeight = Math.floor(iImageHeight / 256);
|
|
12770
|
-
strHeader += sc(iImageHeight % 256);
|
|
12771
|
-
iImageHeight = Math.floor(iImageHeight / 256);
|
|
12772
|
-
strHeader += sc(iImageHeight % 256);
|
|
12773
|
-
|
|
12774
|
-
strHeader += sc(1, 0, 32, 0); // num of planes & num of bits per pixel
|
|
12775
|
-
strHeader += sc(0, 0, 0, 0); // compression = none
|
|
12776
|
-
|
|
12777
|
-
let iDataSize = iWidth * iHeight * 4;
|
|
12778
|
-
strHeader += sc(iDataSize % 256);
|
|
12779
|
-
iDataSize = Math.floor(iDataSize / 256);
|
|
12780
|
-
strHeader += sc(iDataSize % 256);
|
|
12781
|
-
iDataSize = Math.floor(iDataSize / 256);
|
|
12782
|
-
strHeader += sc(iDataSize % 256);
|
|
12783
|
-
iDataSize = Math.floor(iDataSize / 256);
|
|
12784
|
-
strHeader += sc(iDataSize % 256);
|
|
12785
|
-
|
|
12786
|
-
strHeader += sc(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // these bytes are not used
|
|
12787
|
-
|
|
12788
|
-
const aImgData = oData.data;
|
|
12789
|
-
let strPixelData = "";
|
|
12790
|
-
let x;
|
|
12791
|
-
let y = iHeight;
|
|
12792
|
-
let iOffsetX;
|
|
12793
|
-
let iOffsetY;
|
|
12794
|
-
let strPixelRow;
|
|
12775
|
+
this._canvasPos = new Int16Array([0, 0]);
|
|
12776
|
+
this._origin = new Float64Array([0, 0, 0]);
|
|
12777
|
+
this._direction = new Float64Array([0, 0, 0]);
|
|
12778
|
+
this._indices = new Int32Array(3);
|
|
12779
|
+
this._localPos = new Float64Array([0, 0, 0]);
|
|
12780
|
+
this._worldPos = new Float64Array([0, 0, 0]);
|
|
12781
|
+
this._viewPos = new Float64Array([0, 0, 0]);
|
|
12782
|
+
this._bary = new Float64Array([0, 0, 0]);
|
|
12783
|
+
this._worldNormal = new Float64Array([0, 0, 0]);
|
|
12784
|
+
this._uv = new Float64Array([0, 0]);
|
|
12795
12785
|
|
|
12796
|
-
|
|
12797
|
-
|
|
12798
|
-
strPixelRow = "";
|
|
12799
|
-
for (x = 0; x < iWidth; x++) {
|
|
12800
|
-
iOffsetX = 4 * x;
|
|
12801
|
-
strPixelRow += sc(
|
|
12802
|
-
aImgData[iOffsetY + iOffsetX + 2], // B
|
|
12803
|
-
aImgData[iOffsetY + iOffsetX + 1], // G
|
|
12804
|
-
aImgData[iOffsetY + iOffsetX], // R
|
|
12805
|
-
aImgData[iOffsetY + iOffsetX + 3] // A
|
|
12806
|
-
);
|
|
12807
|
-
}
|
|
12808
|
-
strPixelData += strPixelRow;
|
|
12809
|
-
} while (--y);
|
|
12786
|
+
this.reset();
|
|
12787
|
+
}
|
|
12810
12788
|
|
|
12811
|
-
|
|
12812
|
-
|
|
12789
|
+
/**
|
|
12790
|
+
* Canvas coordinates when picking with a 2D pointer.
|
|
12791
|
+
* @property canvasPos
|
|
12792
|
+
* @type {Number[]}
|
|
12793
|
+
*/
|
|
12794
|
+
get canvasPos() {
|
|
12795
|
+
return this._gotCanvasPos ? this._canvasPos : null;
|
|
12796
|
+
}
|
|
12813
12797
|
|
|
12814
|
-
|
|
12815
|
-
|
|
12816
|
-
|
|
12817
|
-
|
|
12798
|
+
/**
|
|
12799
|
+
* @private
|
|
12800
|
+
* @param value
|
|
12801
|
+
*/
|
|
12802
|
+
set canvasPos(value) {
|
|
12803
|
+
if (value) {
|
|
12804
|
+
this._canvasPos[0] = value[0];
|
|
12805
|
+
this._canvasPos[1] = value[1];
|
|
12806
|
+
this._gotCanvasPos = true;
|
|
12807
|
+
} else {
|
|
12808
|
+
this._gotCanvasPos = false;
|
|
12818
12809
|
}
|
|
12819
|
-
}
|
|
12820
|
-
|
|
12821
|
-
const makeDataURI = function (strData, strMime) {
|
|
12822
|
-
return "data:" + strMime + ";base64," + strData;
|
|
12823
|
-
};
|
|
12810
|
+
}
|
|
12824
12811
|
|
|
12825
|
-
|
|
12826
|
-
|
|
12827
|
-
|
|
12828
|
-
|
|
12829
|
-
|
|
12830
|
-
|
|
12812
|
+
/**
|
|
12813
|
+
* World-space 3D ray origin when raypicked.
|
|
12814
|
+
* @property origin
|
|
12815
|
+
* @type {Number[]}
|
|
12816
|
+
*/
|
|
12817
|
+
get origin() {
|
|
12818
|
+
return this._gotOrigin ? this._origin : null;
|
|
12819
|
+
}
|
|
12831
12820
|
|
|
12832
|
-
|
|
12833
|
-
|
|
12834
|
-
|
|
12835
|
-
|
|
12836
|
-
|
|
12837
|
-
|
|
12838
|
-
|
|
12839
|
-
|
|
12840
|
-
|
|
12841
|
-
|
|
12842
|
-
|
|
12843
|
-
|
|
12844
|
-
oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, -iHeight);
|
|
12845
|
-
oSaveCtx.restore();
|
|
12846
|
-
} else {
|
|
12847
|
-
oSaveCtx.imageSmoothingEnabled = true;
|
|
12848
|
-
oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iHeight);
|
|
12849
|
-
}
|
|
12850
|
-
return oSaveCanvas;
|
|
12821
|
+
/**
|
|
12822
|
+
* @private
|
|
12823
|
+
* @param value
|
|
12824
|
+
*/
|
|
12825
|
+
set origin(value) {
|
|
12826
|
+
if (value) {
|
|
12827
|
+
this._origin[0] = value[0];
|
|
12828
|
+
this._origin[1] = value[1];
|
|
12829
|
+
this._origin[2] = value[2];
|
|
12830
|
+
this._gotOrigin = true;
|
|
12831
|
+
} else {
|
|
12832
|
+
this._gotOrigin = false;
|
|
12851
12833
|
}
|
|
12852
|
-
|
|
12853
|
-
};
|
|
12854
|
-
|
|
12855
|
-
return {
|
|
12856
|
-
saveAsPNG: function (oCanvas, bReturnImg, iWidth, iHeight, flipy) {
|
|
12857
|
-
if (!bHasDataURL) return false;
|
|
12858
|
-
const oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight, flipy);
|
|
12859
|
-
const strMime = "image/png";
|
|
12860
|
-
const strData = oScaledCanvas.toDataURL(strMime);
|
|
12861
|
-
if (bReturnImg) {
|
|
12862
|
-
return makeImageObject(strData);
|
|
12863
|
-
} else {
|
|
12864
|
-
saveFile(strData);
|
|
12865
|
-
}
|
|
12866
|
-
return true;
|
|
12867
|
-
},
|
|
12834
|
+
}
|
|
12868
12835
|
|
|
12869
|
-
|
|
12870
|
-
|
|
12871
|
-
|
|
12872
|
-
|
|
12873
|
-
|
|
12874
|
-
|
|
12875
|
-
|
|
12876
|
-
|
|
12877
|
-
return makeImageObject(strData);
|
|
12878
|
-
} else {
|
|
12879
|
-
saveFile(strData);
|
|
12880
|
-
}
|
|
12881
|
-
return true;
|
|
12882
|
-
},
|
|
12836
|
+
/**
|
|
12837
|
+
* World-space 3D ray direction when raypicked.
|
|
12838
|
+
* @property direction
|
|
12839
|
+
* @type {Number[]}
|
|
12840
|
+
*/
|
|
12841
|
+
get direction() {
|
|
12842
|
+
return this._gotDirection ? this._direction : null;
|
|
12843
|
+
}
|
|
12883
12844
|
|
|
12884
|
-
|
|
12885
|
-
|
|
12886
|
-
|
|
12887
|
-
|
|
12888
|
-
|
|
12889
|
-
|
|
12890
|
-
|
|
12891
|
-
|
|
12892
|
-
|
|
12893
|
-
|
|
12894
|
-
|
|
12845
|
+
/**
|
|
12846
|
+
* @private
|
|
12847
|
+
* @param value
|
|
12848
|
+
*/
|
|
12849
|
+
set direction(value) {
|
|
12850
|
+
if (value) {
|
|
12851
|
+
this._direction[0] = value[0];
|
|
12852
|
+
this._direction[1] = value[1];
|
|
12853
|
+
this._direction[2] = value[2];
|
|
12854
|
+
this._gotDirection = true;
|
|
12855
|
+
} else {
|
|
12856
|
+
this._gotDirection = false;
|
|
12895
12857
|
}
|
|
12896
|
-
}
|
|
12897
|
-
|
|
12898
|
-
|
|
12899
|
-
|
|
12900
|
-
|
|
12901
|
-
|
|
12902
|
-
|
|
12903
|
-
|
|
12904
|
-
|
|
12905
|
-
|
|
12906
|
-
options = options || {};
|
|
12907
|
-
this.gl = gl;
|
|
12908
|
-
this.allocated = false;
|
|
12909
|
-
this.canvas = canvas;
|
|
12910
|
-
this.buffer = null;
|
|
12911
|
-
this.bound = false;
|
|
12912
|
-
this.size = options.size;
|
|
12913
|
-
this._hasDepthTexture = !!options.depthTexture;
|
|
12858
|
+
}
|
|
12859
|
+
|
|
12860
|
+
/**
|
|
12861
|
+
* Picked triangle's vertex indices.
|
|
12862
|
+
* Only defined when an entity and triangle was picked.
|
|
12863
|
+
* @property indices
|
|
12864
|
+
* @type {Int32Array}
|
|
12865
|
+
*/
|
|
12866
|
+
get indices() {
|
|
12867
|
+
return this.entity && this._gotIndices ? this._indices : null;
|
|
12914
12868
|
}
|
|
12915
12869
|
|
|
12916
|
-
|
|
12917
|
-
|
|
12870
|
+
/**
|
|
12871
|
+
* @private
|
|
12872
|
+
* @param value
|
|
12873
|
+
*/
|
|
12874
|
+
set indices(value) {
|
|
12875
|
+
if (value) {
|
|
12876
|
+
this._indices[0] = value[0];
|
|
12877
|
+
this._indices[1] = value[1];
|
|
12878
|
+
this._indices[2] = value[2];
|
|
12879
|
+
this._gotIndices = true;
|
|
12880
|
+
} else {
|
|
12881
|
+
this._gotIndices = false;
|
|
12882
|
+
}
|
|
12918
12883
|
}
|
|
12919
12884
|
|
|
12920
|
-
|
|
12921
|
-
|
|
12922
|
-
|
|
12923
|
-
|
|
12924
|
-
|
|
12885
|
+
/**
|
|
12886
|
+
* Picked Local-space point on surface.
|
|
12887
|
+
* Only defined when an entity and a point on its surface was picked.
|
|
12888
|
+
* @property localPos
|
|
12889
|
+
* @type {Number[]}
|
|
12890
|
+
*/
|
|
12891
|
+
get localPos() {
|
|
12892
|
+
return this.entity && this._gotLocalPos ? this._localPos : null;
|
|
12925
12893
|
}
|
|
12926
12894
|
|
|
12927
|
-
|
|
12928
|
-
|
|
12929
|
-
|
|
12930
|
-
|
|
12895
|
+
/**
|
|
12896
|
+
* @private
|
|
12897
|
+
* @param value
|
|
12898
|
+
*/
|
|
12899
|
+
set localPos(value) {
|
|
12900
|
+
if (value) {
|
|
12901
|
+
this._localPos[0] = value[0];
|
|
12902
|
+
this._localPos[1] = value[1];
|
|
12903
|
+
this._localPos[2] = value[2];
|
|
12904
|
+
this._gotLocalPos = true;
|
|
12905
|
+
} else {
|
|
12906
|
+
this._gotLocalPos = false;
|
|
12931
12907
|
}
|
|
12932
|
-
const gl = this.gl;
|
|
12933
|
-
gl.bindFramebuffer(gl.FRAMEBUFFER, this.buffer.framebuf);
|
|
12934
|
-
this.bound = true;
|
|
12935
12908
|
}
|
|
12936
12909
|
|
|
12937
|
-
|
|
12910
|
+
/**
|
|
12911
|
+
* Picked World-space point on surface.
|
|
12912
|
+
* Only defined when an entity and a point on its surface was picked.
|
|
12913
|
+
* @property worldPos
|
|
12914
|
+
* @type {Number[]}
|
|
12915
|
+
*/
|
|
12916
|
+
get worldPos() {
|
|
12917
|
+
return this.entity && this._gotWorldPos ? this._worldPos : null;
|
|
12918
|
+
}
|
|
12938
12919
|
|
|
12939
|
-
|
|
12940
|
-
|
|
12941
|
-
|
|
12920
|
+
/**
|
|
12921
|
+
* @private
|
|
12922
|
+
* @param value
|
|
12923
|
+
*/
|
|
12924
|
+
set worldPos(value) {
|
|
12925
|
+
if (value) {
|
|
12926
|
+
this._worldPos[0] = value[0];
|
|
12927
|
+
this._worldPos[1] = value[1];
|
|
12928
|
+
this._worldPos[2] = value[2];
|
|
12929
|
+
this._gotWorldPos = true;
|
|
12930
|
+
} else {
|
|
12931
|
+
this._gotWorldPos = false;
|
|
12932
|
+
}
|
|
12933
|
+
}
|
|
12942
12934
|
|
|
12943
|
-
|
|
12944
|
-
|
|
12945
|
-
|
|
12935
|
+
/**
|
|
12936
|
+
* Picked View-space point on surface.
|
|
12937
|
+
* Only defined when an entity and a point on its surface was picked.
|
|
12938
|
+
* @property viewPos
|
|
12939
|
+
* @type {Number[]}
|
|
12940
|
+
*/
|
|
12941
|
+
get viewPos() {
|
|
12942
|
+
return this.entity && this._gotViewPos ? this._viewPos : null;
|
|
12943
|
+
}
|
|
12946
12944
|
|
|
12945
|
+
/**
|
|
12946
|
+
* @private
|
|
12947
|
+
* @param value
|
|
12948
|
+
*/
|
|
12949
|
+
set viewPos(value) {
|
|
12950
|
+
if (value) {
|
|
12951
|
+
this._viewPos[0] = value[0];
|
|
12952
|
+
this._viewPos[1] = value[1];
|
|
12953
|
+
this._viewPos[2] = value[2];
|
|
12954
|
+
this._gotViewPos = true;
|
|
12947
12955
|
} else {
|
|
12948
|
-
|
|
12949
|
-
height = gl.drawingBufferHeight;
|
|
12956
|
+
this._gotViewPos = false;
|
|
12950
12957
|
}
|
|
12958
|
+
}
|
|
12951
12959
|
|
|
12952
|
-
|
|
12953
|
-
|
|
12954
|
-
|
|
12955
|
-
|
|
12960
|
+
/**
|
|
12961
|
+
* Barycentric coordinate within picked triangle.
|
|
12962
|
+
* Only defined when an entity and a point on its surface was picked.
|
|
12963
|
+
* @property bary
|
|
12964
|
+
* @type {Number[]}
|
|
12965
|
+
*/
|
|
12966
|
+
get bary() {
|
|
12967
|
+
return this.entity && this._gotBary ? this._bary : null;
|
|
12968
|
+
}
|
|
12956
12969
|
|
|
12957
|
-
|
|
12958
|
-
|
|
12959
|
-
|
|
12960
|
-
|
|
12961
|
-
|
|
12970
|
+
/**
|
|
12971
|
+
* @private
|
|
12972
|
+
* @param value
|
|
12973
|
+
*/
|
|
12974
|
+
set bary(value) {
|
|
12975
|
+
if (value) {
|
|
12976
|
+
this._bary[0] = value[0];
|
|
12977
|
+
this._bary[1] = value[1];
|
|
12978
|
+
this._bary[2] = value[2];
|
|
12979
|
+
this._gotBary = true;
|
|
12980
|
+
} else {
|
|
12981
|
+
this._gotBary = false;
|
|
12962
12982
|
}
|
|
12983
|
+
}
|
|
12963
12984
|
|
|
12964
|
-
|
|
12965
|
-
|
|
12966
|
-
|
|
12967
|
-
|
|
12968
|
-
|
|
12969
|
-
|
|
12970
|
-
|
|
12971
|
-
|
|
12972
|
-
|
|
12985
|
+
/**
|
|
12986
|
+
* Normal vector at picked position on surface.
|
|
12987
|
+
* Only defined when an entity and a point on its surface was picked.
|
|
12988
|
+
* @property worldNormal
|
|
12989
|
+
* @type {Number[]}
|
|
12990
|
+
*/
|
|
12991
|
+
get worldNormal() {
|
|
12992
|
+
return this.entity && this._gotWorldNormal ? this._worldNormal : null;
|
|
12993
|
+
}
|
|
12973
12994
|
|
|
12974
|
-
|
|
12975
|
-
|
|
12976
|
-
|
|
12977
|
-
|
|
12978
|
-
|
|
12979
|
-
|
|
12980
|
-
|
|
12981
|
-
|
|
12995
|
+
/**
|
|
12996
|
+
* @private
|
|
12997
|
+
* @param value
|
|
12998
|
+
*/
|
|
12999
|
+
set worldNormal(value) {
|
|
13000
|
+
if (value) {
|
|
13001
|
+
this._worldNormal[0] = value[0];
|
|
13002
|
+
this._worldNormal[1] = value[1];
|
|
13003
|
+
this._worldNormal[2] = value[2];
|
|
13004
|
+
this._gotWorldNormal = true;
|
|
13005
|
+
} else {
|
|
13006
|
+
this._gotWorldNormal = false;
|
|
12982
13007
|
}
|
|
13008
|
+
}
|
|
12983
13009
|
|
|
12984
|
-
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
|
|
12988
|
-
|
|
12989
|
-
|
|
12990
|
-
|
|
13010
|
+
/**
|
|
13011
|
+
* UV coordinates at picked position on surface.
|
|
13012
|
+
* Only defined when an entity and a point on its surface was picked.
|
|
13013
|
+
* @property uv
|
|
13014
|
+
* @type {Number[]}
|
|
13015
|
+
*/
|
|
13016
|
+
get uv() {
|
|
13017
|
+
return this.entity && this._gotUV ? this._uv : null;
|
|
13018
|
+
}
|
|
12991
13019
|
|
|
12992
|
-
|
|
12993
|
-
|
|
13020
|
+
/**
|
|
13021
|
+
* @private
|
|
13022
|
+
* @param value
|
|
13023
|
+
*/
|
|
13024
|
+
set uv(value) {
|
|
13025
|
+
if (value) {
|
|
13026
|
+
this._uv[0] = value[0];
|
|
13027
|
+
this._uv[1] = value[1];
|
|
13028
|
+
this._gotUV = true;
|
|
12994
13029
|
} else {
|
|
12995
|
-
|
|
13030
|
+
this._gotUV = false;
|
|
12996
13031
|
}
|
|
13032
|
+
}
|
|
12997
13033
|
|
|
12998
|
-
|
|
12999
|
-
|
|
13000
|
-
|
|
13034
|
+
/**
|
|
13035
|
+
* @private
|
|
13036
|
+
*/
|
|
13037
|
+
reset() {
|
|
13038
|
+
this.entity = null;
|
|
13039
|
+
this.primIndex = -1;
|
|
13040
|
+
this.primitive = null;
|
|
13041
|
+
this.pickSurfacePrecision = false;
|
|
13042
|
+
this._gotCanvasPos = false;
|
|
13043
|
+
this._gotOrigin = false;
|
|
13044
|
+
this._gotDirection = false;
|
|
13045
|
+
this._gotIndices = false;
|
|
13046
|
+
this._gotLocalPos = false;
|
|
13047
|
+
this._gotWorldPos = false;
|
|
13048
|
+
this._gotViewPos = false;
|
|
13049
|
+
this._gotBary = false;
|
|
13050
|
+
this._gotWorldNormal = false;
|
|
13051
|
+
this._gotUV = false;
|
|
13052
|
+
}
|
|
13053
|
+
}
|
|
13001
13054
|
|
|
13002
|
-
|
|
13055
|
+
/**
|
|
13056
|
+
* @desc Represents a vertex or fragment stage within a {@link Program}.
|
|
13057
|
+
* @private
|
|
13058
|
+
*/
|
|
13059
|
+
class Shader {
|
|
13003
13060
|
|
|
13004
|
-
|
|
13005
|
-
if (!gl.isFramebuffer(framebuf)) {
|
|
13006
|
-
throw "Invalid framebuffer";
|
|
13007
|
-
}
|
|
13008
|
-
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
13061
|
+
constructor(gl, type, source) {
|
|
13009
13062
|
|
|
13010
|
-
|
|
13063
|
+
this.allocated = false;
|
|
13064
|
+
this.compiled = false;
|
|
13065
|
+
this.handle = gl.createShader(type);
|
|
13011
13066
|
|
|
13012
|
-
|
|
13067
|
+
if (!this.handle) {
|
|
13068
|
+
this.errors = [
|
|
13069
|
+
"Failed to allocate"
|
|
13070
|
+
];
|
|
13071
|
+
return;
|
|
13072
|
+
}
|
|
13013
13073
|
|
|
13014
|
-
|
|
13015
|
-
break;
|
|
13074
|
+
this.allocated = true;
|
|
13016
13075
|
|
|
13017
|
-
|
|
13018
|
-
|
|
13076
|
+
gl.shaderSource(this.handle, source);
|
|
13077
|
+
gl.compileShader(this.handle);
|
|
13019
13078
|
|
|
13020
|
-
|
|
13021
|
-
throw "Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
|
|
13079
|
+
this.compiled = gl.getShaderParameter(this.handle, gl.COMPILE_STATUS);
|
|
13022
13080
|
|
|
13023
|
-
|
|
13024
|
-
throw "Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
|
|
13081
|
+
if (!this.compiled) {
|
|
13025
13082
|
|
|
13026
|
-
|
|
13027
|
-
throw "Incomplete framebuffer: FRAMEBUFFER_UNSUPPORTED";
|
|
13083
|
+
if (!gl.isContextLost()) { // Handled explicitly elsewhere, so won't re-handle here
|
|
13028
13084
|
|
|
13029
|
-
|
|
13030
|
-
|
|
13085
|
+
const lines = source.split("\n");
|
|
13086
|
+
const numberedLines = [];
|
|
13087
|
+
for (let i = 0; i < lines.length; i++) {
|
|
13088
|
+
numberedLines.push((i + 1) + ": " + lines[i] + "\n");
|
|
13089
|
+
}
|
|
13090
|
+
this.errors = [];
|
|
13091
|
+
this.errors.push("");
|
|
13092
|
+
this.errors.push(gl.getShaderInfoLog(this.handle));
|
|
13093
|
+
this.errors = this.errors.concat(numberedLines.join(""));
|
|
13094
|
+
}
|
|
13031
13095
|
}
|
|
13096
|
+
}
|
|
13032
13097
|
|
|
13033
|
-
|
|
13034
|
-
framebuf: framebuf,
|
|
13035
|
-
renderbuf: renderbuf,
|
|
13036
|
-
texture: colorTexture,
|
|
13037
|
-
depthTexture: depthTexture,
|
|
13038
|
-
width: width,
|
|
13039
|
-
height: height
|
|
13040
|
-
};
|
|
13098
|
+
destroy() {
|
|
13041
13099
|
|
|
13042
|
-
this.bound = false;
|
|
13043
13100
|
}
|
|
13101
|
+
}
|
|
13044
13102
|
|
|
13045
|
-
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
|
|
13103
|
+
/**
|
|
13104
|
+
* @desc A low-level component that represents a WebGL Sampler.
|
|
13105
|
+
* @private
|
|
13106
|
+
*/
|
|
13107
|
+
class Sampler {
|
|
13108
|
+
|
|
13109
|
+
constructor(gl, location) {
|
|
13110
|
+
this.bindTexture = function (texture, unit) {
|
|
13111
|
+
if (texture.bind(unit)) {
|
|
13112
|
+
gl.uniform1i(location, unit);
|
|
13113
|
+
return true;
|
|
13114
|
+
}
|
|
13115
|
+
return false;
|
|
13116
|
+
};
|
|
13051
13117
|
}
|
|
13118
|
+
}
|
|
13052
13119
|
|
|
13053
|
-
|
|
13054
|
-
|
|
13055
|
-
|
|
13056
|
-
|
|
13057
|
-
|
|
13058
|
-
|
|
13059
|
-
|
|
13120
|
+
/**
|
|
13121
|
+
* @desc Represents a WebGL vertex attribute buffer (VBO).
|
|
13122
|
+
* @private
|
|
13123
|
+
* @param gl {WebGLRenderingContext} The WebGL rendering context.
|
|
13124
|
+
*/
|
|
13125
|
+
class Attribute {
|
|
13126
|
+
|
|
13127
|
+
constructor(gl, location) {
|
|
13128
|
+
this._gl = gl;
|
|
13129
|
+
this.location = location;
|
|
13060
13130
|
}
|
|
13061
13131
|
|
|
13062
|
-
|
|
13132
|
+
bindArrayBuffer(arrayBuf) {
|
|
13133
|
+
if (!arrayBuf) {
|
|
13134
|
+
return;
|
|
13135
|
+
}
|
|
13136
|
+
arrayBuf.bind();
|
|
13137
|
+
this._gl.enableVertexAttribArray(this.location);
|
|
13138
|
+
this._gl.vertexAttribPointer(this.location, arrayBuf.itemSize, arrayBuf.itemType, arrayBuf.normalized, arrayBuf.stride, arrayBuf.offset);
|
|
13139
|
+
}
|
|
13140
|
+
}
|
|
13063
13141
|
|
|
13064
|
-
|
|
13065
|
-
const imageDataCache = this._getImageDataCache();
|
|
13066
|
-
const pixelData = imageDataCache.pixelData;
|
|
13067
|
-
const canvas = imageDataCache.canvas;
|
|
13068
|
-
const imageData = imageDataCache.imageData;
|
|
13069
|
-
const context = imageDataCache.context;
|
|
13142
|
+
const ids$4 = new Map$1({});
|
|
13070
13143
|
|
|
13071
|
-
|
|
13144
|
+
function joinSansComments(srcLines) {
|
|
13145
|
+
const src = [];
|
|
13146
|
+
let line;
|
|
13147
|
+
let n;
|
|
13148
|
+
for (let i = 0, len = srcLines.length; i < len; i++) {
|
|
13149
|
+
line = srcLines[i];
|
|
13150
|
+
n = line.indexOf("/");
|
|
13151
|
+
if (n > 0) {
|
|
13152
|
+
if (line.charAt(n + 1) === "/") {
|
|
13153
|
+
line = line.substring(0, n);
|
|
13154
|
+
}
|
|
13155
|
+
}
|
|
13156
|
+
src.push(line);
|
|
13157
|
+
}
|
|
13158
|
+
return src.join("\n");
|
|
13159
|
+
}
|
|
13072
13160
|
|
|
13073
|
-
|
|
13074
|
-
|
|
13161
|
+
function logErrors(errors) {
|
|
13162
|
+
console.error(errors.join("\n"));
|
|
13163
|
+
}
|
|
13075
13164
|
|
|
13076
|
-
|
|
13077
|
-
|
|
13078
|
-
|
|
13079
|
-
|
|
13165
|
+
/**
|
|
13166
|
+
* @desc Represents a WebGL program.
|
|
13167
|
+
* @private
|
|
13168
|
+
*/
|
|
13169
|
+
class Program {
|
|
13080
13170
|
|
|
13081
|
-
|
|
13171
|
+
constructor(gl, shaderSource) {
|
|
13172
|
+
this.id = ids$4.addItem({});
|
|
13173
|
+
this.source = shaderSource;
|
|
13174
|
+
this.init(gl);
|
|
13175
|
+
}
|
|
13082
13176
|
|
|
13083
|
-
|
|
13084
|
-
|
|
13085
|
-
|
|
13086
|
-
|
|
13087
|
-
|
|
13088
|
-
|
|
13089
|
-
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
|
|
13093
|
-
|
|
13094
|
-
|
|
13095
|
-
|
|
13177
|
+
init(gl) {
|
|
13178
|
+
this.gl = gl;
|
|
13179
|
+
this.allocated = false;
|
|
13180
|
+
this.compiled = false;
|
|
13181
|
+
this.linked = false;
|
|
13182
|
+
this.validated = false;
|
|
13183
|
+
this.errors = null;
|
|
13184
|
+
this.uniforms = {};
|
|
13185
|
+
this.samplers = {};
|
|
13186
|
+
this.attributes = {};
|
|
13187
|
+
this._vertexShader = new Shader(gl, gl.VERTEX_SHADER, joinSansComments(this.source.vertex));
|
|
13188
|
+
this._fragmentShader = new Shader(gl, gl.FRAGMENT_SHADER, joinSansComments(this.source.fragment));
|
|
13189
|
+
if (!this._vertexShader.allocated) {
|
|
13190
|
+
this.errors = ["Vertex shader failed to allocate"].concat(this._vertexShader.errors);
|
|
13191
|
+
logErrors(this.errors);
|
|
13192
|
+
return;
|
|
13193
|
+
}
|
|
13194
|
+
if (!this._fragmentShader.allocated) {
|
|
13195
|
+
this.errors = ["Fragment shader failed to allocate"].concat(this._fragmentShader.errors);
|
|
13196
|
+
logErrors(this.errors);
|
|
13197
|
+
return;
|
|
13198
|
+
}
|
|
13199
|
+
this.allocated = true;
|
|
13200
|
+
if (!this._vertexShader.compiled) {
|
|
13201
|
+
this.errors = ["Vertex shader failed to compile"].concat(this._vertexShader.errors);
|
|
13202
|
+
logErrors(this.errors);
|
|
13203
|
+
return;
|
|
13204
|
+
}
|
|
13205
|
+
if (!this._fragmentShader.compiled) {
|
|
13206
|
+
this.errors = ["Fragment shader failed to compile"].concat(this._fragmentShader.errors);
|
|
13207
|
+
logErrors(this.errors);
|
|
13208
|
+
return;
|
|
13209
|
+
}
|
|
13210
|
+
this.compiled = true;
|
|
13211
|
+
let a;
|
|
13212
|
+
let i;
|
|
13213
|
+
let u;
|
|
13214
|
+
let uName;
|
|
13215
|
+
let location;
|
|
13216
|
+
this.handle = gl.createProgram();
|
|
13217
|
+
if (!this.handle) {
|
|
13218
|
+
this.errors = ["Failed to allocate program"];
|
|
13219
|
+
return;
|
|
13220
|
+
}
|
|
13221
|
+
gl.attachShader(this.handle, this._vertexShader.handle);
|
|
13222
|
+
gl.attachShader(this.handle, this._fragmentShader.handle);
|
|
13223
|
+
gl.linkProgram(this.handle);
|
|
13224
|
+
this.linked = gl.getProgramParameter(this.handle, gl.LINK_STATUS);
|
|
13225
|
+
// HACK: Disable validation temporarily: https://github.com/xeolabs/xeokit/issues/5
|
|
13226
|
+
// Perhaps we should defer validation until render-time, when the program has values set for all inputs?
|
|
13227
|
+
this.validated = true;
|
|
13228
|
+
if (!this.linked || !this.validated) {
|
|
13229
|
+
this.errors = [];
|
|
13230
|
+
this.errors.push("");
|
|
13231
|
+
this.errors.push(gl.getProgramInfoLog(this.handle));
|
|
13232
|
+
this.errors.push("\nVertex shader:\n");
|
|
13233
|
+
this.errors = this.errors.concat(this.source.vertex);
|
|
13234
|
+
this.errors.push("\nFragment shader:\n");
|
|
13235
|
+
this.errors = this.errors.concat(this.source.fragment);
|
|
13236
|
+
logErrors(this.errors);
|
|
13237
|
+
return;
|
|
13096
13238
|
}
|
|
13097
|
-
|
|
13098
|
-
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
|
|
13102
|
-
|
|
13103
|
-
|
|
13104
|
-
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
|
|
13108
|
-
|
|
13109
|
-
|
|
13110
|
-
|
|
13111
|
-
imageDataCache = null;
|
|
13239
|
+
const numUniforms = gl.getProgramParameter(this.handle, gl.ACTIVE_UNIFORMS);
|
|
13240
|
+
for (i = 0; i < numUniforms; ++i) {
|
|
13241
|
+
u = gl.getActiveUniform(this.handle, i);
|
|
13242
|
+
if (u) {
|
|
13243
|
+
uName = u.name;
|
|
13244
|
+
if (uName[uName.length - 1] === "\u0000") {
|
|
13245
|
+
uName = uName.substr(0, uName.length - 1);
|
|
13246
|
+
}
|
|
13247
|
+
location = gl.getUniformLocation(this.handle, uName);
|
|
13248
|
+
if ((u.type === gl.SAMPLER_2D) || (u.type === gl.SAMPLER_CUBE) || (u.type === 35682)) {
|
|
13249
|
+
this.samplers[uName] = new Sampler(gl, location);
|
|
13250
|
+
} else {
|
|
13251
|
+
this.uniforms[uName] = location;
|
|
13252
|
+
}
|
|
13112
13253
|
}
|
|
13113
13254
|
}
|
|
13114
|
-
|
|
13115
|
-
|
|
13116
|
-
|
|
13117
|
-
|
|
13118
|
-
|
|
13119
|
-
|
|
13120
|
-
|
|
13121
|
-
const context = canvas.getContext('2d');
|
|
13122
|
-
const imageData = context.createImageData(bufferWidth, bufferHeight);
|
|
13123
|
-
|
|
13124
|
-
imageDataCache = {
|
|
13125
|
-
pixelData: new Uint8Array(bufferWidth * bufferHeight * 4),
|
|
13126
|
-
canvas: canvas,
|
|
13127
|
-
context: context,
|
|
13128
|
-
imageData: imageData,
|
|
13129
|
-
width: bufferWidth,
|
|
13130
|
-
height: bufferHeight
|
|
13131
|
-
};
|
|
13132
|
-
|
|
13133
|
-
this._imageDataCache = imageDataCache;
|
|
13255
|
+
const numAttribs = gl.getProgramParameter(this.handle, gl.ACTIVE_ATTRIBUTES);
|
|
13256
|
+
for (i = 0; i < numAttribs; i++) {
|
|
13257
|
+
a = gl.getActiveAttrib(this.handle, i);
|
|
13258
|
+
if (a) {
|
|
13259
|
+
location = gl.getAttribLocation(this.handle, a.name);
|
|
13260
|
+
this.attributes[a.name] = new Attribute(gl, location);
|
|
13261
|
+
}
|
|
13134
13262
|
}
|
|
13135
|
-
|
|
13136
|
-
return imageDataCache;
|
|
13263
|
+
this.allocated = true;
|
|
13137
13264
|
}
|
|
13138
13265
|
|
|
13139
|
-
|
|
13140
|
-
|
|
13141
|
-
|
|
13142
|
-
|
|
13266
|
+
bind() {
|
|
13267
|
+
if (!this.allocated) {
|
|
13268
|
+
return;
|
|
13269
|
+
}
|
|
13270
|
+
this.gl.useProgram(this.handle);
|
|
13143
13271
|
}
|
|
13144
13272
|
|
|
13145
|
-
|
|
13146
|
-
|
|
13147
|
-
|
|
13148
|
-
|
|
13149
|
-
|
|
13150
|
-
if (self.buffer && self.buffer.texture) {
|
|
13151
|
-
self.gl.activeTexture(self.gl["TEXTURE" + unit]);
|
|
13152
|
-
self.gl.bindTexture(self.gl.TEXTURE_2D, self.buffer.texture);
|
|
13153
|
-
return true;
|
|
13154
|
-
}
|
|
13155
|
-
return false;
|
|
13156
|
-
},
|
|
13157
|
-
unbind: function (unit) {
|
|
13158
|
-
if (self.buffer && self.buffer.texture) {
|
|
13159
|
-
self.gl.activeTexture(self.gl["TEXTURE" + unit]);
|
|
13160
|
-
self.gl.bindTexture(self.gl.TEXTURE_2D, null);
|
|
13161
|
-
}
|
|
13162
|
-
}
|
|
13163
|
-
});
|
|
13273
|
+
getLocation(name) {
|
|
13274
|
+
if (!this.allocated) {
|
|
13275
|
+
return;
|
|
13276
|
+
}
|
|
13277
|
+
return this.uniforms[name];
|
|
13164
13278
|
}
|
|
13165
13279
|
|
|
13166
|
-
|
|
13167
|
-
|
|
13280
|
+
getAttribute(name) {
|
|
13281
|
+
if (!this.allocated) {
|
|
13282
|
+
return;
|
|
13283
|
+
}
|
|
13284
|
+
return this.attributes[name];
|
|
13168
13285
|
}
|
|
13169
13286
|
|
|
13170
|
-
|
|
13171
|
-
if (!this.
|
|
13172
|
-
return
|
|
13287
|
+
bindTexture(name, texture, unit) {
|
|
13288
|
+
if (!this.allocated) {
|
|
13289
|
+
return false;
|
|
13290
|
+
}
|
|
13291
|
+
const sampler = this.samplers[name];
|
|
13292
|
+
if (sampler) {
|
|
13293
|
+
return sampler.bindTexture(texture, unit);
|
|
13294
|
+
} else {
|
|
13295
|
+
return false;
|
|
13173
13296
|
}
|
|
13174
|
-
const self = this;
|
|
13175
|
-
return this._depthTexture || (this._dethTexture = {
|
|
13176
|
-
renderBuffer: this,
|
|
13177
|
-
bind: function (unit) {
|
|
13178
|
-
if (self.buffer && self.buffer.depthTexture) {
|
|
13179
|
-
self.gl.activeTexture(self.gl["TEXTURE" + unit]);
|
|
13180
|
-
self.gl.bindTexture(self.gl.TEXTURE_2D, self.buffer.depthTexture);
|
|
13181
|
-
return true;
|
|
13182
|
-
}
|
|
13183
|
-
return false;
|
|
13184
|
-
},
|
|
13185
|
-
unbind: function (unit) {
|
|
13186
|
-
if (self.buffer && self.buffer.depthTexture) {
|
|
13187
|
-
self.gl.activeTexture(self.gl["TEXTURE" + unit]);
|
|
13188
|
-
self.gl.bindTexture(self.gl.TEXTURE_2D, null);
|
|
13189
|
-
}
|
|
13190
|
-
}
|
|
13191
|
-
});
|
|
13192
13297
|
}
|
|
13193
13298
|
|
|
13194
13299
|
destroy() {
|
|
13195
|
-
if (this.allocated) {
|
|
13196
|
-
|
|
13197
|
-
gl.deleteTexture(this.buffer.texture);
|
|
13198
|
-
gl.deleteTexture(this.buffer.depthTexture);
|
|
13199
|
-
gl.deleteFramebuffer(this.buffer.framebuf);
|
|
13200
|
-
gl.deleteRenderbuffer(this.buffer.renderbuf);
|
|
13201
|
-
this.allocated = false;
|
|
13202
|
-
this.buffer = null;
|
|
13203
|
-
this.bound = false;
|
|
13300
|
+
if (!this.allocated) {
|
|
13301
|
+
return;
|
|
13204
13302
|
}
|
|
13205
|
-
this.
|
|
13206
|
-
this.
|
|
13207
|
-
this.
|
|
13303
|
+
ids$4.removeItem(this.id);
|
|
13304
|
+
this.gl.deleteProgram(this.handle);
|
|
13305
|
+
this.gl.deleteShader(this._vertexShader.handle);
|
|
13306
|
+
this.gl.deleteShader(this._fragmentShader.handle);
|
|
13307
|
+
this.handle = null;
|
|
13308
|
+
this.attributes = null;
|
|
13309
|
+
this.uniforms = null;
|
|
13310
|
+
this.samplers = null;
|
|
13311
|
+
this.allocated = false;
|
|
13208
13312
|
}
|
|
13209
13313
|
}
|
|
13210
13314
|
|
|
13211
|
-
|
|
13212
|
-
*
|
|
13315
|
+
/*
|
|
13316
|
+
* Canvas2Image v0.1
|
|
13317
|
+
* Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com
|
|
13318
|
+
* MIT License [http://www.opensource.org/licenses/mit-license.php]
|
|
13213
13319
|
*
|
|
13320
|
+
* Modified by @xeolabs to permit vertical flipping, so that snapshot can be taken from WebGL frame buffers,
|
|
13321
|
+
* which vertically flip image data as part of the way that WebGL renders textures.
|
|
13214
13322
|
*/
|
|
13215
|
-
class PickResult {
|
|
13216
13323
|
|
|
13217
|
-
|
|
13218
|
-
|
|
13219
|
-
|
|
13220
|
-
|
|
13221
|
-
|
|
13324
|
+
/**
|
|
13325
|
+
* @private
|
|
13326
|
+
*/
|
|
13327
|
+
const Canvas2Image = (function () {
|
|
13328
|
+
// check if we have canvas support
|
|
13329
|
+
const oCanvas = document.createElement("canvas"), sc = String.fromCharCode;
|
|
13222
13330
|
|
|
13223
|
-
|
|
13224
|
-
|
|
13225
|
-
|
|
13226
|
-
|
|
13227
|
-
|
|
13228
|
-
|
|
13229
|
-
|
|
13331
|
+
// no canvas, bail out.
|
|
13332
|
+
if (!oCanvas.getContext) {
|
|
13333
|
+
return {
|
|
13334
|
+
saveAsBMP: function () {
|
|
13335
|
+
},
|
|
13336
|
+
saveAsPNG: function () {
|
|
13337
|
+
},
|
|
13338
|
+
saveAsJPEG: function () {
|
|
13339
|
+
}
|
|
13340
|
+
}
|
|
13341
|
+
}
|
|
13342
|
+
|
|
13343
|
+
const bHasImageData = !!(oCanvas.getContext("2d").getImageData), bHasDataURL = !!(oCanvas.toDataURL),
|
|
13344
|
+
bHasBase64 = !!(window.btoa);
|
|
13345
|
+
|
|
13346
|
+
// ok, we're good
|
|
13347
|
+
const readCanvasData = function (oCanvas) {
|
|
13348
|
+
const iWidth = parseInt(oCanvas.width), iHeight = parseInt(oCanvas.height);
|
|
13349
|
+
return oCanvas.getContext("2d").getImageData(0, 0, iWidth, iHeight);
|
|
13350
|
+
};
|
|
13351
|
+
|
|
13352
|
+
// base64 encodes either a string or an array of charcodes
|
|
13353
|
+
const encodeData = function (data) {
|
|
13354
|
+
let i, aData, strData = "";
|
|
13355
|
+
|
|
13356
|
+
if (typeof data == "string") {
|
|
13357
|
+
strData = data;
|
|
13358
|
+
} else {
|
|
13359
|
+
aData = data;
|
|
13360
|
+
for (i = 0; i < aData.length; i++) {
|
|
13361
|
+
strData += sc(aData[i]);
|
|
13362
|
+
}
|
|
13363
|
+
}
|
|
13364
|
+
return btoa(strData);
|
|
13365
|
+
};
|
|
13366
|
+
|
|
13367
|
+
// creates a base64 encoded string containing BMP data takes an imagedata object as argument
|
|
13368
|
+
const createBMP = function (oData) {
|
|
13369
|
+
let strHeader = '';
|
|
13370
|
+
const iWidth = oData.width;
|
|
13371
|
+
const iHeight = oData.height;
|
|
13372
|
+
|
|
13373
|
+
strHeader += 'BM';
|
|
13374
|
+
|
|
13375
|
+
let iFileSize = iWidth * iHeight * 4 + 54; // total header size = 54 bytes
|
|
13376
|
+
strHeader += sc(iFileSize % 256);
|
|
13377
|
+
iFileSize = Math.floor(iFileSize / 256);
|
|
13378
|
+
strHeader += sc(iFileSize % 256);
|
|
13379
|
+
iFileSize = Math.floor(iFileSize / 256);
|
|
13380
|
+
strHeader += sc(iFileSize % 256);
|
|
13381
|
+
iFileSize = Math.floor(iFileSize / 256);
|
|
13382
|
+
strHeader += sc(iFileSize % 256);
|
|
13383
|
+
|
|
13384
|
+
strHeader += sc(0, 0, 0, 0, 54, 0, 0, 0); // data offset
|
|
13385
|
+
strHeader += sc(40, 0, 0, 0); // info header size
|
|
13386
|
+
|
|
13387
|
+
let iImageWidth = iWidth;
|
|
13388
|
+
strHeader += sc(iImageWidth % 256);
|
|
13389
|
+
iImageWidth = Math.floor(iImageWidth / 256);
|
|
13390
|
+
strHeader += sc(iImageWidth % 256);
|
|
13391
|
+
iImageWidth = Math.floor(iImageWidth / 256);
|
|
13392
|
+
strHeader += sc(iImageWidth % 256);
|
|
13393
|
+
iImageWidth = Math.floor(iImageWidth / 256);
|
|
13394
|
+
strHeader += sc(iImageWidth % 256);
|
|
13395
|
+
|
|
13396
|
+
let iImageHeight = iHeight;
|
|
13397
|
+
strHeader += sc(iImageHeight % 256);
|
|
13398
|
+
iImageHeight = Math.floor(iImageHeight / 256);
|
|
13399
|
+
strHeader += sc(iImageHeight % 256);
|
|
13400
|
+
iImageHeight = Math.floor(iImageHeight / 256);
|
|
13401
|
+
strHeader += sc(iImageHeight % 256);
|
|
13402
|
+
iImageHeight = Math.floor(iImageHeight / 256);
|
|
13403
|
+
strHeader += sc(iImageHeight % 256);
|
|
13230
13404
|
|
|
13231
|
-
|
|
13232
|
-
|
|
13233
|
-
* Null when no primitive was picked.
|
|
13234
|
-
* @property primitive
|
|
13235
|
-
* @type {String}
|
|
13236
|
-
*/
|
|
13237
|
-
this.primitive = null;
|
|
13405
|
+
strHeader += sc(1, 0, 32, 0); // num of planes & num of bits per pixel
|
|
13406
|
+
strHeader += sc(0, 0, 0, 0); // compression = none
|
|
13238
13407
|
|
|
13239
|
-
|
|
13240
|
-
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
|
|
13408
|
+
let iDataSize = iWidth * iHeight * 4;
|
|
13409
|
+
strHeader += sc(iDataSize % 256);
|
|
13410
|
+
iDataSize = Math.floor(iDataSize / 256);
|
|
13411
|
+
strHeader += sc(iDataSize % 256);
|
|
13412
|
+
iDataSize = Math.floor(iDataSize / 256);
|
|
13413
|
+
strHeader += sc(iDataSize % 256);
|
|
13414
|
+
iDataSize = Math.floor(iDataSize / 256);
|
|
13415
|
+
strHeader += sc(iDataSize % 256);
|
|
13246
13416
|
|
|
13247
|
-
|
|
13248
|
-
* True when the picked surface position is full precision.
|
|
13249
|
-
* When false, the picked surface position should be regarded as approximate.
|
|
13250
|
-
* Full-precision surface picking is performed with the {@link Scene#pick} method's ````pickSurfacePrecision```` option.
|
|
13251
|
-
* @property pickSurfacePrecision
|
|
13252
|
-
* @type {Boolean}
|
|
13253
|
-
*/
|
|
13254
|
-
this.pickSurfacePrecision = false;
|
|
13417
|
+
strHeader += sc(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // these bytes are not used
|
|
13255
13418
|
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
|
|
13259
|
-
|
|
13260
|
-
|
|
13261
|
-
|
|
13262
|
-
|
|
13263
|
-
this._bary = new Float64Array([0, 0, 0]);
|
|
13264
|
-
this._worldNormal = new Float64Array([0, 0, 0]);
|
|
13265
|
-
this._uv = new Float64Array([0, 0]);
|
|
13419
|
+
const aImgData = oData.data;
|
|
13420
|
+
let strPixelData = "";
|
|
13421
|
+
let x;
|
|
13422
|
+
let y = iHeight;
|
|
13423
|
+
let iOffsetX;
|
|
13424
|
+
let iOffsetY;
|
|
13425
|
+
let strPixelRow;
|
|
13266
13426
|
|
|
13267
|
-
|
|
13268
|
-
|
|
13427
|
+
do {
|
|
13428
|
+
iOffsetY = iWidth * (y - 1) * 4;
|
|
13429
|
+
strPixelRow = "";
|
|
13430
|
+
for (x = 0; x < iWidth; x++) {
|
|
13431
|
+
iOffsetX = 4 * x;
|
|
13432
|
+
strPixelRow += sc(
|
|
13433
|
+
aImgData[iOffsetY + iOffsetX + 2], // B
|
|
13434
|
+
aImgData[iOffsetY + iOffsetX + 1], // G
|
|
13435
|
+
aImgData[iOffsetY + iOffsetX], // R
|
|
13436
|
+
aImgData[iOffsetY + iOffsetX + 3] // A
|
|
13437
|
+
);
|
|
13438
|
+
}
|
|
13439
|
+
strPixelData += strPixelRow;
|
|
13440
|
+
} while (--y);
|
|
13269
13441
|
|
|
13270
|
-
|
|
13271
|
-
|
|
13272
|
-
* @property canvasPos
|
|
13273
|
-
* @type {Number[]}
|
|
13274
|
-
*/
|
|
13275
|
-
get canvasPos() {
|
|
13276
|
-
return this._gotCanvasPos ? this._canvasPos : null;
|
|
13277
|
-
}
|
|
13442
|
+
return encodeData(strHeader + strPixelData);
|
|
13443
|
+
};
|
|
13278
13444
|
|
|
13279
|
-
|
|
13280
|
-
|
|
13281
|
-
|
|
13282
|
-
|
|
13283
|
-
set canvasPos(value) {
|
|
13284
|
-
if (value) {
|
|
13285
|
-
this._canvasPos[0] = value[0];
|
|
13286
|
-
this._canvasPos[1] = value[1];
|
|
13287
|
-
this._gotCanvasPos = true;
|
|
13288
|
-
} else {
|
|
13289
|
-
this._gotCanvasPos = false;
|
|
13445
|
+
// sends the generated file to the client
|
|
13446
|
+
const saveFile = function (strData) {
|
|
13447
|
+
if (!window.open(strData)) {
|
|
13448
|
+
document.location.href = strData;
|
|
13290
13449
|
}
|
|
13291
|
-
}
|
|
13450
|
+
};
|
|
13292
13451
|
|
|
13293
|
-
|
|
13294
|
-
|
|
13295
|
-
|
|
13296
|
-
* @type {Number[]}
|
|
13297
|
-
*/
|
|
13298
|
-
get origin() {
|
|
13299
|
-
return this._gotOrigin ? this._origin : null;
|
|
13300
|
-
}
|
|
13452
|
+
const makeDataURI = function (strData, strMime) {
|
|
13453
|
+
return "data:" + strMime + ";base64," + strData;
|
|
13454
|
+
};
|
|
13301
13455
|
|
|
13302
|
-
|
|
13303
|
-
|
|
13304
|
-
|
|
13305
|
-
|
|
13306
|
-
|
|
13307
|
-
|
|
13308
|
-
|
|
13309
|
-
|
|
13310
|
-
|
|
13311
|
-
|
|
13312
|
-
|
|
13313
|
-
|
|
13456
|
+
// generates a <img> object containing the imagedata
|
|
13457
|
+
const makeImageObject = function (strSource) {
|
|
13458
|
+
const oImgElement = document.createElement("img");
|
|
13459
|
+
oImgElement.src = strSource;
|
|
13460
|
+
return oImgElement;
|
|
13461
|
+
};
|
|
13462
|
+
|
|
13463
|
+
const scaleCanvas = function (oCanvas, iWidth, iHeight, flipy) {
|
|
13464
|
+
if (iWidth && iHeight) {
|
|
13465
|
+
const oSaveCanvas = document.createElement("canvas");
|
|
13466
|
+
oSaveCanvas.width = iWidth;
|
|
13467
|
+
oSaveCanvas.height = iHeight;
|
|
13468
|
+
oSaveCanvas.style.width = iWidth + "px";
|
|
13469
|
+
oSaveCanvas.style.height = iHeight + "px";
|
|
13470
|
+
const oSaveCtx = oSaveCanvas.getContext("2d");
|
|
13471
|
+
if (flipy) {
|
|
13472
|
+
oSaveCtx.save();
|
|
13473
|
+
oSaveCtx.scale(1.0, -1.0);
|
|
13474
|
+
oSaveCtx.imageSmoothingEnabled = true;
|
|
13475
|
+
oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, -iHeight);
|
|
13476
|
+
oSaveCtx.restore();
|
|
13477
|
+
} else {
|
|
13478
|
+
oSaveCtx.imageSmoothingEnabled = true;
|
|
13479
|
+
oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iHeight);
|
|
13480
|
+
}
|
|
13481
|
+
return oSaveCanvas;
|
|
13314
13482
|
}
|
|
13315
|
-
|
|
13483
|
+
return oCanvas;
|
|
13484
|
+
};
|
|
13316
13485
|
|
|
13317
|
-
|
|
13318
|
-
|
|
13319
|
-
|
|
13320
|
-
|
|
13321
|
-
|
|
13322
|
-
|
|
13323
|
-
|
|
13324
|
-
|
|
13486
|
+
return {
|
|
13487
|
+
saveAsPNG: function (oCanvas, bReturnImg, iWidth, iHeight, flipy) {
|
|
13488
|
+
if (!bHasDataURL) return false;
|
|
13489
|
+
const oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight, flipy);
|
|
13490
|
+
const strMime = "image/png";
|
|
13491
|
+
const strData = oScaledCanvas.toDataURL(strMime);
|
|
13492
|
+
if (bReturnImg) {
|
|
13493
|
+
return makeImageObject(strData);
|
|
13494
|
+
} else {
|
|
13495
|
+
saveFile(strData);
|
|
13496
|
+
}
|
|
13497
|
+
return true;
|
|
13498
|
+
},
|
|
13325
13499
|
|
|
13326
|
-
|
|
13327
|
-
|
|
13328
|
-
|
|
13329
|
-
|
|
13330
|
-
|
|
13331
|
-
|
|
13332
|
-
|
|
13333
|
-
|
|
13334
|
-
|
|
13335
|
-
|
|
13336
|
-
|
|
13337
|
-
|
|
13338
|
-
|
|
13339
|
-
|
|
13340
|
-
|
|
13341
|
-
/**
|
|
13342
|
-
* Picked triangle's vertex indices.
|
|
13343
|
-
* Only defined when an entity and triangle was picked.
|
|
13344
|
-
* @property indices
|
|
13345
|
-
* @type {Int32Array}
|
|
13346
|
-
*/
|
|
13347
|
-
get indices() {
|
|
13348
|
-
return this.entity && this._gotIndices ? this._indices : null;
|
|
13349
|
-
}
|
|
13500
|
+
saveAsJPEG: function (oCanvas, bReturnImg, iWidth, iHeight, flipy) {
|
|
13501
|
+
if (!bHasDataURL) return false;
|
|
13502
|
+
const oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight, flipy);
|
|
13503
|
+
const strMime = "image/jpeg";
|
|
13504
|
+
const strData = oScaledCanvas.toDataURL(strMime);
|
|
13505
|
+
// check if browser actually supports jpeg by looking for the mime type in the data uri. if not, return false
|
|
13506
|
+
if (strData.indexOf(strMime) != 5) return false;
|
|
13507
|
+
if (bReturnImg) {
|
|
13508
|
+
return makeImageObject(strData);
|
|
13509
|
+
} else {
|
|
13510
|
+
saveFile(strData);
|
|
13511
|
+
}
|
|
13512
|
+
return true;
|
|
13513
|
+
},
|
|
13350
13514
|
|
|
13351
|
-
|
|
13352
|
-
|
|
13353
|
-
|
|
13354
|
-
|
|
13355
|
-
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
|
|
13359
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
this._gotIndices = false;
|
|
13515
|
+
saveAsBMP: function (oCanvas, bReturnImg, iWidth, iHeight, flipy) {
|
|
13516
|
+
if (!(bHasDataURL && bHasImageData && bHasBase64)) return false;
|
|
13517
|
+
const oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight, flipy);
|
|
13518
|
+
const strMime = "image/bmp";
|
|
13519
|
+
const oData = readCanvasData(oScaledCanvas), strImgData = createBMP(oData);
|
|
13520
|
+
if (bReturnImg) {
|
|
13521
|
+
return makeImageObject(makeDataURI(strImgData, strMime));
|
|
13522
|
+
} else {
|
|
13523
|
+
saveFile(makeDataURI(strImgData, strMime));
|
|
13524
|
+
}
|
|
13525
|
+
return true;
|
|
13363
13526
|
}
|
|
13364
|
-
}
|
|
13527
|
+
};
|
|
13528
|
+
})();
|
|
13365
13529
|
|
|
13366
|
-
|
|
13367
|
-
|
|
13368
|
-
|
|
13369
|
-
|
|
13370
|
-
|
|
13371
|
-
|
|
13372
|
-
|
|
13373
|
-
|
|
13530
|
+
/**
|
|
13531
|
+
* @desc Represents a WebGL render buffer.
|
|
13532
|
+
* @private
|
|
13533
|
+
*/
|
|
13534
|
+
class RenderBuffer {
|
|
13535
|
+
|
|
13536
|
+
constructor(canvas, gl, options) {
|
|
13537
|
+
options = options || {};
|
|
13538
|
+
this.gl = gl;
|
|
13539
|
+
this.allocated = false;
|
|
13540
|
+
this.canvas = canvas;
|
|
13541
|
+
this.buffer = null;
|
|
13542
|
+
this.bound = false;
|
|
13543
|
+
this.size = options.size;
|
|
13544
|
+
this._hasDepthTexture = !!options.depthTexture;
|
|
13374
13545
|
}
|
|
13375
13546
|
|
|
13376
|
-
|
|
13377
|
-
|
|
13378
|
-
* @param value
|
|
13379
|
-
*/
|
|
13380
|
-
set localPos(value) {
|
|
13381
|
-
if (value) {
|
|
13382
|
-
this._localPos[0] = value[0];
|
|
13383
|
-
this._localPos[1] = value[1];
|
|
13384
|
-
this._localPos[2] = value[2];
|
|
13385
|
-
this._gotLocalPos = true;
|
|
13386
|
-
} else {
|
|
13387
|
-
this._gotLocalPos = false;
|
|
13388
|
-
}
|
|
13547
|
+
setSize(size) {
|
|
13548
|
+
this.size = size;
|
|
13389
13549
|
}
|
|
13390
13550
|
|
|
13391
|
-
|
|
13392
|
-
|
|
13393
|
-
|
|
13394
|
-
|
|
13395
|
-
|
|
13396
|
-
*/
|
|
13397
|
-
get worldPos() {
|
|
13398
|
-
return this.entity && this._gotWorldPos ? this._worldPos : null;
|
|
13551
|
+
webglContextRestored(gl) {
|
|
13552
|
+
this.gl = gl;
|
|
13553
|
+
this.buffer = null;
|
|
13554
|
+
this.allocated = false;
|
|
13555
|
+
this.bound = false;
|
|
13399
13556
|
}
|
|
13400
13557
|
|
|
13401
|
-
|
|
13402
|
-
|
|
13403
|
-
|
|
13404
|
-
|
|
13405
|
-
set worldPos(value) {
|
|
13406
|
-
if (value) {
|
|
13407
|
-
this._worldPos[0] = value[0];
|
|
13408
|
-
this._worldPos[1] = value[1];
|
|
13409
|
-
this._worldPos[2] = value[2];
|
|
13410
|
-
this._gotWorldPos = true;
|
|
13411
|
-
} else {
|
|
13412
|
-
this._gotWorldPos = false;
|
|
13558
|
+
bind() {
|
|
13559
|
+
this._touch();
|
|
13560
|
+
if (this.bound) {
|
|
13561
|
+
return;
|
|
13413
13562
|
}
|
|
13563
|
+
const gl = this.gl;
|
|
13564
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this.buffer.framebuf);
|
|
13565
|
+
this.bound = true;
|
|
13414
13566
|
}
|
|
13415
13567
|
|
|
13416
|
-
|
|
13417
|
-
|
|
13418
|
-
|
|
13419
|
-
|
|
13420
|
-
|
|
13421
|
-
|
|
13422
|
-
|
|
13423
|
-
|
|
13424
|
-
|
|
13568
|
+
_touch() {
|
|
13569
|
+
|
|
13570
|
+
let width;
|
|
13571
|
+
let height;
|
|
13572
|
+
const gl = this.gl;
|
|
13573
|
+
|
|
13574
|
+
if (this.size) {
|
|
13575
|
+
width = this.size[0];
|
|
13576
|
+
height = this.size[1];
|
|
13425
13577
|
|
|
13426
|
-
/**
|
|
13427
|
-
* @private
|
|
13428
|
-
* @param value
|
|
13429
|
-
*/
|
|
13430
|
-
set viewPos(value) {
|
|
13431
|
-
if (value) {
|
|
13432
|
-
this._viewPos[0] = value[0];
|
|
13433
|
-
this._viewPos[1] = value[1];
|
|
13434
|
-
this._viewPos[2] = value[2];
|
|
13435
|
-
this._gotViewPos = true;
|
|
13436
13578
|
} else {
|
|
13437
|
-
|
|
13579
|
+
width = gl.drawingBufferWidth;
|
|
13580
|
+
height = gl.drawingBufferHeight;
|
|
13438
13581
|
}
|
|
13439
|
-
}
|
|
13440
13582
|
|
|
13441
|
-
|
|
13442
|
-
* Barycentric coordinate within picked triangle.
|
|
13443
|
-
* Only defined when an entity and a point on its surface was picked.
|
|
13444
|
-
* @property bary
|
|
13445
|
-
* @type {Number[]}
|
|
13446
|
-
*/
|
|
13447
|
-
get bary() {
|
|
13448
|
-
return this.entity && this._gotBary ? this._bary : null;
|
|
13449
|
-
}
|
|
13583
|
+
if (this.buffer) {
|
|
13450
13584
|
|
|
13451
|
-
|
|
13452
|
-
|
|
13453
|
-
|
|
13454
|
-
|
|
13455
|
-
|
|
13456
|
-
|
|
13457
|
-
|
|
13458
|
-
|
|
13459
|
-
this._bary[2] = value[2];
|
|
13460
|
-
this._gotBary = true;
|
|
13461
|
-
} else {
|
|
13462
|
-
this._gotBary = false;
|
|
13585
|
+
if (this.buffer.width === width && this.buffer.height === height) {
|
|
13586
|
+
return;
|
|
13587
|
+
|
|
13588
|
+
} else {
|
|
13589
|
+
gl.deleteTexture(this.buffer.texture);
|
|
13590
|
+
gl.deleteFramebuffer(this.buffer.framebuf);
|
|
13591
|
+
gl.deleteRenderbuffer(this.buffer.renderbuf);
|
|
13592
|
+
}
|
|
13463
13593
|
}
|
|
13464
|
-
}
|
|
13465
13594
|
|
|
13466
|
-
|
|
13467
|
-
|
|
13468
|
-
|
|
13469
|
-
|
|
13470
|
-
|
|
13471
|
-
|
|
13472
|
-
|
|
13473
|
-
return this.entity && this._gotWorldNormal ? this._worldNormal : null;
|
|
13474
|
-
}
|
|
13595
|
+
const colorTexture = gl.createTexture();
|
|
13596
|
+
gl.bindTexture(gl.TEXTURE_2D, colorTexture);
|
|
13597
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
13598
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
13599
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
13600
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
13601
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
|
13475
13602
|
|
|
13476
|
-
|
|
13477
|
-
|
|
13478
|
-
|
|
13479
|
-
|
|
13480
|
-
|
|
13481
|
-
|
|
13482
|
-
|
|
13483
|
-
|
|
13484
|
-
|
|
13485
|
-
|
|
13486
|
-
} else {
|
|
13487
|
-
this._gotWorldNormal = false;
|
|
13603
|
+
let depthTexture;
|
|
13604
|
+
|
|
13605
|
+
if (this._hasDepthTexture) {
|
|
13606
|
+
depthTexture = gl.createTexture();
|
|
13607
|
+
gl.bindTexture(gl.TEXTURE_2D, depthTexture);
|
|
13608
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
13609
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
13610
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
13611
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
13612
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, width, height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null);
|
|
13488
13613
|
}
|
|
13489
|
-
}
|
|
13490
13614
|
|
|
13491
|
-
|
|
13492
|
-
|
|
13493
|
-
|
|
13494
|
-
* @property uv
|
|
13495
|
-
* @type {Number[]}
|
|
13496
|
-
*/
|
|
13497
|
-
get uv() {
|
|
13498
|
-
return this.entity && this._gotUV ? this._uv : null;
|
|
13499
|
-
}
|
|
13615
|
+
const renderbuf = gl.createRenderbuffer();
|
|
13616
|
+
gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuf);
|
|
13617
|
+
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
|
|
13500
13618
|
|
|
13501
|
-
|
|
13502
|
-
|
|
13503
|
-
|
|
13504
|
-
|
|
13505
|
-
|
|
13506
|
-
|
|
13507
|
-
this._uv[0] = value[0];
|
|
13508
|
-
this._uv[1] = value[1];
|
|
13509
|
-
this._gotUV = true;
|
|
13619
|
+
const framebuf = gl.createFramebuffer();
|
|
13620
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuf);
|
|
13621
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTexture, 0);
|
|
13622
|
+
|
|
13623
|
+
if (this._hasDepthTexture) {
|
|
13624
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTexture, 0);
|
|
13510
13625
|
} else {
|
|
13511
|
-
|
|
13626
|
+
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuf);
|
|
13512
13627
|
}
|
|
13513
|
-
}
|
|
13514
13628
|
|
|
13515
|
-
|
|
13516
|
-
|
|
13517
|
-
|
|
13518
|
-
reset() {
|
|
13519
|
-
this.entity = null;
|
|
13520
|
-
this.primIndex = -1;
|
|
13521
|
-
this.primitive = null;
|
|
13522
|
-
this.pickSurfacePrecision = false;
|
|
13523
|
-
this._gotCanvasPos = false;
|
|
13524
|
-
this._gotOrigin = false;
|
|
13525
|
-
this._gotDirection = false;
|
|
13526
|
-
this._gotIndices = false;
|
|
13527
|
-
this._gotLocalPos = false;
|
|
13528
|
-
this._gotWorldPos = false;
|
|
13529
|
-
this._gotViewPos = false;
|
|
13530
|
-
this._gotBary = false;
|
|
13531
|
-
this._gotWorldNormal = false;
|
|
13532
|
-
this._gotUV = false;
|
|
13533
|
-
}
|
|
13534
|
-
}
|
|
13629
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
13630
|
+
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
|
13631
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
13535
13632
|
|
|
13536
|
-
|
|
13537
|
-
* @desc Represents a vertex or fragment stage within a {@link Program}.
|
|
13538
|
-
* @private
|
|
13539
|
-
*/
|
|
13540
|
-
class Shader {
|
|
13633
|
+
// Verify framebuffer is OK
|
|
13541
13634
|
|
|
13542
|
-
|
|
13635
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuf);
|
|
13636
|
+
if (!gl.isFramebuffer(framebuf)) {
|
|
13637
|
+
throw "Invalid framebuffer";
|
|
13638
|
+
}
|
|
13639
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
13543
13640
|
|
|
13544
|
-
|
|
13545
|
-
this.compiled = false;
|
|
13546
|
-
this.handle = gl.createShader(type);
|
|
13641
|
+
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
|
13547
13642
|
|
|
13548
|
-
|
|
13549
|
-
this.errors = [
|
|
13550
|
-
"Failed to allocate"
|
|
13551
|
-
];
|
|
13552
|
-
return;
|
|
13553
|
-
}
|
|
13643
|
+
switch (status) {
|
|
13554
13644
|
|
|
13555
|
-
|
|
13645
|
+
case gl.FRAMEBUFFER_COMPLETE:
|
|
13646
|
+
break;
|
|
13556
13647
|
|
|
13557
|
-
|
|
13558
|
-
|
|
13648
|
+
case gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
|
|
13649
|
+
throw "Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
|
|
13559
13650
|
|
|
13560
|
-
|
|
13651
|
+
case gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
|
|
13652
|
+
throw "Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
|
|
13561
13653
|
|
|
13562
|
-
|
|
13654
|
+
case gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
|
|
13655
|
+
throw "Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
|
|
13563
13656
|
|
|
13564
|
-
|
|
13657
|
+
case gl.FRAMEBUFFER_UNSUPPORTED:
|
|
13658
|
+
throw "Incomplete framebuffer: FRAMEBUFFER_UNSUPPORTED";
|
|
13565
13659
|
|
|
13566
|
-
|
|
13567
|
-
|
|
13568
|
-
for (let i = 0; i < lines.length; i++) {
|
|
13569
|
-
numberedLines.push((i + 1) + ": " + lines[i] + "\n");
|
|
13570
|
-
}
|
|
13571
|
-
this.errors = [];
|
|
13572
|
-
this.errors.push("");
|
|
13573
|
-
this.errors.push(gl.getShaderInfoLog(this.handle));
|
|
13574
|
-
this.errors = this.errors.concat(numberedLines.join(""));
|
|
13575
|
-
}
|
|
13660
|
+
default:
|
|
13661
|
+
throw "Incomplete framebuffer: " + status;
|
|
13576
13662
|
}
|
|
13663
|
+
|
|
13664
|
+
this.buffer = {
|
|
13665
|
+
framebuf: framebuf,
|
|
13666
|
+
renderbuf: renderbuf,
|
|
13667
|
+
texture: colorTexture,
|
|
13668
|
+
depthTexture: depthTexture,
|
|
13669
|
+
width: width,
|
|
13670
|
+
height: height
|
|
13671
|
+
};
|
|
13672
|
+
|
|
13673
|
+
this.bound = false;
|
|
13577
13674
|
}
|
|
13578
13675
|
|
|
13579
|
-
|
|
13676
|
+
clear() {
|
|
13677
|
+
if (!this.bound) {
|
|
13678
|
+
throw "Render buffer not bound";
|
|
13679
|
+
}
|
|
13680
|
+
const gl = this.gl;
|
|
13681
|
+
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
13682
|
+
}
|
|
13580
13683
|
|
|
13684
|
+
read(pickX, pickY) {
|
|
13685
|
+
const x = pickX;
|
|
13686
|
+
const y = this.gl.drawingBufferHeight - pickY;
|
|
13687
|
+
const pix = new Uint8Array(4);
|
|
13688
|
+
const gl = this.gl;
|
|
13689
|
+
gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pix);
|
|
13690
|
+
return pix;
|
|
13581
13691
|
}
|
|
13582
|
-
}
|
|
13583
13692
|
|
|
13584
|
-
|
|
13585
|
-
* @desc A low-level component that represents a WebGL Sampler.
|
|
13586
|
-
* @private
|
|
13587
|
-
*/
|
|
13588
|
-
class Sampler {
|
|
13693
|
+
readImage(params) {
|
|
13589
13694
|
|
|
13590
|
-
|
|
13591
|
-
|
|
13592
|
-
|
|
13593
|
-
|
|
13594
|
-
|
|
13595
|
-
|
|
13596
|
-
return false;
|
|
13597
|
-
};
|
|
13598
|
-
}
|
|
13599
|
-
}
|
|
13695
|
+
const gl = this.gl;
|
|
13696
|
+
const imageDataCache = this._getImageDataCache();
|
|
13697
|
+
const pixelData = imageDataCache.pixelData;
|
|
13698
|
+
const canvas = imageDataCache.canvas;
|
|
13699
|
+
const imageData = imageDataCache.imageData;
|
|
13700
|
+
const context = imageDataCache.context;
|
|
13600
13701
|
|
|
13601
|
-
|
|
13602
|
-
* @desc Represents a WebGL vertex attribute buffer (VBO).
|
|
13603
|
-
* @private
|
|
13604
|
-
* @param gl {WebGLRenderingContext} The WebGL rendering context.
|
|
13605
|
-
*/
|
|
13606
|
-
class Attribute {
|
|
13702
|
+
gl.readPixels(0, 0, this.buffer.width, this.buffer.height, gl.RGBA, gl.UNSIGNED_BYTE, pixelData);
|
|
13607
13703
|
|
|
13608
|
-
|
|
13609
|
-
|
|
13610
|
-
this.location = location;
|
|
13611
|
-
}
|
|
13704
|
+
imageData.data.set(pixelData);
|
|
13705
|
+
context.putImageData(imageData, 0, 0);
|
|
13612
13706
|
|
|
13613
|
-
|
|
13614
|
-
|
|
13615
|
-
|
|
13616
|
-
|
|
13617
|
-
arrayBuf.bind();
|
|
13618
|
-
this._gl.enableVertexAttribArray(this.location);
|
|
13619
|
-
this._gl.vertexAttribPointer(this.location, arrayBuf.itemSize, arrayBuf.itemType, arrayBuf.normalized, arrayBuf.stride, arrayBuf.offset);
|
|
13620
|
-
}
|
|
13621
|
-
}
|
|
13707
|
+
const imageWidth = params.width || canvas.width;
|
|
13708
|
+
const imageHeight = params.height || canvas.height;
|
|
13709
|
+
const format = params.format || "jpeg";
|
|
13710
|
+
const flipy = true; // Account for WebGL texture flipping
|
|
13622
13711
|
|
|
13623
|
-
|
|
13712
|
+
let image;
|
|
13624
13713
|
|
|
13625
|
-
|
|
13626
|
-
|
|
13627
|
-
|
|
13628
|
-
|
|
13629
|
-
|
|
13630
|
-
|
|
13631
|
-
|
|
13632
|
-
|
|
13633
|
-
|
|
13634
|
-
|
|
13635
|
-
|
|
13714
|
+
switch (format) {
|
|
13715
|
+
case "jpeg":
|
|
13716
|
+
image = Canvas2Image.saveAsJPEG(canvas, true, imageWidth, imageHeight, flipy);
|
|
13717
|
+
break;
|
|
13718
|
+
case "png":
|
|
13719
|
+
image = Canvas2Image.saveAsPNG(canvas, true, imageWidth, imageHeight, flipy);
|
|
13720
|
+
break;
|
|
13721
|
+
case "bmp":
|
|
13722
|
+
image = Canvas2Image.saveAsBMP(canvas, true, imageWidth, imageHeight, flipy);
|
|
13723
|
+
break;
|
|
13724
|
+
default:
|
|
13725
|
+
console.error("Unsupported image format: '" + format + "' - supported types are 'jpeg', 'bmp' and 'png' - defaulting to 'jpeg'");
|
|
13726
|
+
image = Canvas2Image.saveAsJPEG(canvas, true, imageWidth, imageHeight, flipy);
|
|
13636
13727
|
}
|
|
13637
|
-
|
|
13728
|
+
|
|
13729
|
+
return image.src;
|
|
13638
13730
|
}
|
|
13639
|
-
return src.join("\n");
|
|
13640
|
-
}
|
|
13641
13731
|
|
|
13642
|
-
|
|
13643
|
-
console.error(errors.join("\n"));
|
|
13644
|
-
}
|
|
13732
|
+
_getImageDataCache() {
|
|
13645
13733
|
|
|
13646
|
-
|
|
13647
|
-
|
|
13648
|
-
* @private
|
|
13649
|
-
*/
|
|
13650
|
-
class Program {
|
|
13734
|
+
const bufferWidth = this.buffer.width;
|
|
13735
|
+
const bufferHeight = this.buffer.height;
|
|
13651
13736
|
|
|
13652
|
-
|
|
13653
|
-
this.id = ids$4.addItem({});
|
|
13654
|
-
this.source = shaderSource;
|
|
13655
|
-
this.init(gl);
|
|
13656
|
-
}
|
|
13737
|
+
let imageDataCache = this._imageDataCache;
|
|
13657
13738
|
|
|
13658
|
-
|
|
13659
|
-
|
|
13660
|
-
|
|
13661
|
-
|
|
13662
|
-
this.linked = false;
|
|
13663
|
-
this.validated = false;
|
|
13664
|
-
this.errors = null;
|
|
13665
|
-
this.uniforms = {};
|
|
13666
|
-
this.samplers = {};
|
|
13667
|
-
this.attributes = {};
|
|
13668
|
-
this._vertexShader = new Shader(gl, gl.VERTEX_SHADER, joinSansComments(this.source.vertex));
|
|
13669
|
-
this._fragmentShader = new Shader(gl, gl.FRAGMENT_SHADER, joinSansComments(this.source.fragment));
|
|
13670
|
-
if (!this._vertexShader.allocated) {
|
|
13671
|
-
this.errors = ["Vertex shader failed to allocate"].concat(this._vertexShader.errors);
|
|
13672
|
-
logErrors(this.errors);
|
|
13673
|
-
return;
|
|
13674
|
-
}
|
|
13675
|
-
if (!this._fragmentShader.allocated) {
|
|
13676
|
-
this.errors = ["Fragment shader failed to allocate"].concat(this._fragmentShader.errors);
|
|
13677
|
-
logErrors(this.errors);
|
|
13678
|
-
return;
|
|
13679
|
-
}
|
|
13680
|
-
this.allocated = true;
|
|
13681
|
-
if (!this._vertexShader.compiled) {
|
|
13682
|
-
this.errors = ["Vertex shader failed to compile"].concat(this._vertexShader.errors);
|
|
13683
|
-
logErrors(this.errors);
|
|
13684
|
-
return;
|
|
13685
|
-
}
|
|
13686
|
-
if (!this._fragmentShader.compiled) {
|
|
13687
|
-
this.errors = ["Fragment shader failed to compile"].concat(this._fragmentShader.errors);
|
|
13688
|
-
logErrors(this.errors);
|
|
13689
|
-
return;
|
|
13690
|
-
}
|
|
13691
|
-
this.compiled = true;
|
|
13692
|
-
let a;
|
|
13693
|
-
let i;
|
|
13694
|
-
let u;
|
|
13695
|
-
let uName;
|
|
13696
|
-
let location;
|
|
13697
|
-
this.handle = gl.createProgram();
|
|
13698
|
-
if (!this.handle) {
|
|
13699
|
-
this.errors = ["Failed to allocate program"];
|
|
13700
|
-
return;
|
|
13701
|
-
}
|
|
13702
|
-
gl.attachShader(this.handle, this._vertexShader.handle);
|
|
13703
|
-
gl.attachShader(this.handle, this._fragmentShader.handle);
|
|
13704
|
-
gl.linkProgram(this.handle);
|
|
13705
|
-
this.linked = gl.getProgramParameter(this.handle, gl.LINK_STATUS);
|
|
13706
|
-
// HACK: Disable validation temporarily: https://github.com/xeolabs/xeokit/issues/5
|
|
13707
|
-
// Perhaps we should defer validation until render-time, when the program has values set for all inputs?
|
|
13708
|
-
this.validated = true;
|
|
13709
|
-
if (!this.linked || !this.validated) {
|
|
13710
|
-
this.errors = [];
|
|
13711
|
-
this.errors.push("");
|
|
13712
|
-
this.errors.push(gl.getProgramInfoLog(this.handle));
|
|
13713
|
-
this.errors.push("\nVertex shader:\n");
|
|
13714
|
-
this.errors = this.errors.concat(this.source.vertex);
|
|
13715
|
-
this.errors.push("\nFragment shader:\n");
|
|
13716
|
-
this.errors = this.errors.concat(this.source.fragment);
|
|
13717
|
-
logErrors(this.errors);
|
|
13718
|
-
return;
|
|
13719
|
-
}
|
|
13720
|
-
const numUniforms = gl.getProgramParameter(this.handle, gl.ACTIVE_UNIFORMS);
|
|
13721
|
-
for (i = 0; i < numUniforms; ++i) {
|
|
13722
|
-
u = gl.getActiveUniform(this.handle, i);
|
|
13723
|
-
if (u) {
|
|
13724
|
-
uName = u.name;
|
|
13725
|
-
if (uName[uName.length - 1] === "\u0000") {
|
|
13726
|
-
uName = uName.substr(0, uName.length - 1);
|
|
13727
|
-
}
|
|
13728
|
-
location = gl.getUniformLocation(this.handle, uName);
|
|
13729
|
-
if ((u.type === gl.SAMPLER_2D) || (u.type === gl.SAMPLER_CUBE) || (u.type === 35682)) {
|
|
13730
|
-
this.samplers[uName] = new Sampler(gl, location);
|
|
13731
|
-
} else {
|
|
13732
|
-
this.uniforms[uName] = location;
|
|
13733
|
-
}
|
|
13739
|
+
if (imageDataCache) {
|
|
13740
|
+
if (imageDataCache.width !== bufferWidth || imageDataCache.height !== bufferHeight) {
|
|
13741
|
+
this._imageDataCache = null;
|
|
13742
|
+
imageDataCache = null;
|
|
13734
13743
|
}
|
|
13735
13744
|
}
|
|
13736
|
-
|
|
13737
|
-
|
|
13738
|
-
|
|
13739
|
-
|
|
13740
|
-
|
|
13741
|
-
|
|
13742
|
-
|
|
13745
|
+
|
|
13746
|
+
if (!imageDataCache) {
|
|
13747
|
+
|
|
13748
|
+
const canvas = document.createElement('canvas');
|
|
13749
|
+
canvas.width = bufferWidth;
|
|
13750
|
+
canvas.height = bufferHeight;
|
|
13751
|
+
|
|
13752
|
+
const context = canvas.getContext('2d');
|
|
13753
|
+
const imageData = context.createImageData(bufferWidth, bufferHeight);
|
|
13754
|
+
|
|
13755
|
+
imageDataCache = {
|
|
13756
|
+
pixelData: new Uint8Array(bufferWidth * bufferHeight * 4),
|
|
13757
|
+
canvas: canvas,
|
|
13758
|
+
context: context,
|
|
13759
|
+
imageData: imageData,
|
|
13760
|
+
width: bufferWidth,
|
|
13761
|
+
height: bufferHeight
|
|
13762
|
+
};
|
|
13763
|
+
|
|
13764
|
+
this._imageDataCache = imageDataCache;
|
|
13743
13765
|
}
|
|
13744
|
-
|
|
13766
|
+
|
|
13767
|
+
return imageDataCache;
|
|
13745
13768
|
}
|
|
13746
13769
|
|
|
13747
|
-
|
|
13748
|
-
|
|
13749
|
-
|
|
13750
|
-
|
|
13751
|
-
this.gl.useProgram(this.handle);
|
|
13770
|
+
unbind() {
|
|
13771
|
+
const gl = this.gl;
|
|
13772
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
13773
|
+
this.bound = false;
|
|
13752
13774
|
}
|
|
13753
13775
|
|
|
13754
|
-
|
|
13755
|
-
|
|
13756
|
-
|
|
13757
|
-
|
|
13758
|
-
|
|
13776
|
+
getTexture() {
|
|
13777
|
+
const self = this;
|
|
13778
|
+
return this._texture || (this._texture = {
|
|
13779
|
+
renderBuffer: this,
|
|
13780
|
+
bind: function (unit) {
|
|
13781
|
+
if (self.buffer && self.buffer.texture) {
|
|
13782
|
+
self.gl.activeTexture(self.gl["TEXTURE" + unit]);
|
|
13783
|
+
self.gl.bindTexture(self.gl.TEXTURE_2D, self.buffer.texture);
|
|
13784
|
+
return true;
|
|
13785
|
+
}
|
|
13786
|
+
return false;
|
|
13787
|
+
},
|
|
13788
|
+
unbind: function (unit) {
|
|
13789
|
+
if (self.buffer && self.buffer.texture) {
|
|
13790
|
+
self.gl.activeTexture(self.gl["TEXTURE" + unit]);
|
|
13791
|
+
self.gl.bindTexture(self.gl.TEXTURE_2D, null);
|
|
13792
|
+
}
|
|
13793
|
+
}
|
|
13794
|
+
});
|
|
13759
13795
|
}
|
|
13760
13796
|
|
|
13761
|
-
|
|
13762
|
-
|
|
13763
|
-
return;
|
|
13764
|
-
}
|
|
13765
|
-
return this.attributes[name];
|
|
13797
|
+
hasDepthTexture() {
|
|
13798
|
+
return this._hasDepthTexture;
|
|
13766
13799
|
}
|
|
13767
13800
|
|
|
13768
|
-
|
|
13769
|
-
if (!this.
|
|
13770
|
-
return
|
|
13771
|
-
}
|
|
13772
|
-
const sampler = this.samplers[name];
|
|
13773
|
-
if (sampler) {
|
|
13774
|
-
return sampler.bindTexture(texture, unit);
|
|
13775
|
-
} else {
|
|
13776
|
-
return false;
|
|
13801
|
+
getDepthTexture() {
|
|
13802
|
+
if (!this._hasDepthTexture) {
|
|
13803
|
+
return null;
|
|
13777
13804
|
}
|
|
13805
|
+
const self = this;
|
|
13806
|
+
return this._depthTexture || (this._dethTexture = {
|
|
13807
|
+
renderBuffer: this,
|
|
13808
|
+
bind: function (unit) {
|
|
13809
|
+
if (self.buffer && self.buffer.depthTexture) {
|
|
13810
|
+
self.gl.activeTexture(self.gl["TEXTURE" + unit]);
|
|
13811
|
+
self.gl.bindTexture(self.gl.TEXTURE_2D, self.buffer.depthTexture);
|
|
13812
|
+
return true;
|
|
13813
|
+
}
|
|
13814
|
+
return false;
|
|
13815
|
+
},
|
|
13816
|
+
unbind: function (unit) {
|
|
13817
|
+
if (self.buffer && self.buffer.depthTexture) {
|
|
13818
|
+
self.gl.activeTexture(self.gl["TEXTURE" + unit]);
|
|
13819
|
+
self.gl.bindTexture(self.gl.TEXTURE_2D, null);
|
|
13820
|
+
}
|
|
13821
|
+
}
|
|
13822
|
+
});
|
|
13778
13823
|
}
|
|
13779
13824
|
|
|
13780
13825
|
destroy() {
|
|
13781
|
-
if (
|
|
13782
|
-
|
|
13826
|
+
if (this.allocated) {
|
|
13827
|
+
const gl = this.gl;
|
|
13828
|
+
gl.deleteTexture(this.buffer.texture);
|
|
13829
|
+
gl.deleteTexture(this.buffer.depthTexture);
|
|
13830
|
+
gl.deleteFramebuffer(this.buffer.framebuf);
|
|
13831
|
+
gl.deleteRenderbuffer(this.buffer.renderbuf);
|
|
13832
|
+
this.allocated = false;
|
|
13833
|
+
this.buffer = null;
|
|
13834
|
+
this.bound = false;
|
|
13783
13835
|
}
|
|
13784
|
-
|
|
13785
|
-
this.
|
|
13786
|
-
this.
|
|
13787
|
-
this.gl.deleteShader(this._fragmentShader.handle);
|
|
13788
|
-
this.handle = null;
|
|
13789
|
-
this.attributes = null;
|
|
13790
|
-
this.uniforms = null;
|
|
13791
|
-
this.samplers = null;
|
|
13792
|
-
this.allocated = false;
|
|
13836
|
+
this._imageDataCache = null;
|
|
13837
|
+
this._texture = null;
|
|
13838
|
+
this._depthTexture = null;
|
|
13793
13839
|
}
|
|
13794
13840
|
}
|
|
13795
13841
|
|
|
@@ -14132,10 +14178,12 @@ const tempVec3a$_ = math.vec3();
|
|
|
14132
14178
|
*/
|
|
14133
14179
|
class OcclusionTester {
|
|
14134
14180
|
|
|
14135
|
-
constructor(scene) {
|
|
14181
|
+
constructor(scene, renderBufferManager) {
|
|
14136
14182
|
|
|
14137
14183
|
this._scene = scene;
|
|
14138
14184
|
|
|
14185
|
+
this._renderBufferManager = renderBufferManager;
|
|
14186
|
+
|
|
14139
14187
|
this._occlusionLayers = {};
|
|
14140
14188
|
this._occlusionLayersList = [];
|
|
14141
14189
|
this._occlusionLayersListDirty = false;
|
|
@@ -14280,7 +14328,7 @@ class OcclusionTester {
|
|
|
14280
14328
|
}
|
|
14281
14329
|
|
|
14282
14330
|
{
|
|
14283
|
-
this._readPixelBuf = this.
|
|
14331
|
+
this._readPixelBuf = this._renderBufferManager.getRenderBuffer("occlusionReadPix");
|
|
14284
14332
|
this._readPixelBuf.bind();
|
|
14285
14333
|
this._readPixelBuf.clear();
|
|
14286
14334
|
}
|
|
@@ -14492,6 +14540,8 @@ class OcclusionTester {
|
|
|
14492
14540
|
|
|
14493
14541
|
{
|
|
14494
14542
|
|
|
14543
|
+
const resolutionScale = this._scene.canvas.resolutionScale;
|
|
14544
|
+
|
|
14495
14545
|
const markerR = MARKER_COLOR[0] * 255;
|
|
14496
14546
|
const markerG = MARKER_COLOR[1] * 255;
|
|
14497
14547
|
const markerB = MARKER_COLOR[2] * 255;
|
|
@@ -14504,7 +14554,7 @@ class OcclusionTester {
|
|
|
14504
14554
|
|
|
14505
14555
|
const marker = occlusionLayer.occlusionTestList[i];
|
|
14506
14556
|
const j = i * 2;
|
|
14507
|
-
const color = this._readPixelBuf.read(occlusionLayer.pixels[j], occlusionLayer.pixels[j + 1]);
|
|
14557
|
+
const color = this._readPixelBuf.read(Math.round(occlusionLayer.pixels[j] * resolutionScale), Math.round(occlusionLayer.pixels[j + 1] * resolutionScale));
|
|
14508
14558
|
const visible = (color[0] === markerR) && (color[1] === markerG) && (color[2] === markerB);
|
|
14509
14559
|
|
|
14510
14560
|
marker._setVisible(visible);
|
|
@@ -15234,6 +15284,37 @@ function createSampleOffsets(kernelRadius, uvIncrement) {
|
|
|
15234
15284
|
return offsets;
|
|
15235
15285
|
}
|
|
15236
15286
|
|
|
15287
|
+
/**
|
|
15288
|
+
* @private
|
|
15289
|
+
*/
|
|
15290
|
+
class RenderBufferManager {
|
|
15291
|
+
|
|
15292
|
+
constructor(scene) {
|
|
15293
|
+
this.scene = scene;
|
|
15294
|
+
this._renderBuffersBasic = {};
|
|
15295
|
+
this._renderBuffersScaled = {};
|
|
15296
|
+
}
|
|
15297
|
+
|
|
15298
|
+
getRenderBuffer(id, options) {
|
|
15299
|
+
const renderBuffers = (this.scene.canvas.resolutionScale === 1.0) ? this._renderBuffersBasic : this._renderBuffersScaled;
|
|
15300
|
+
let renderBuffer = renderBuffers[id];
|
|
15301
|
+
if (!renderBuffer) {
|
|
15302
|
+
renderBuffer = new RenderBuffer(this.scene.canvas.canvas, this.scene.canvas.gl, options);
|
|
15303
|
+
renderBuffers[id] = renderBuffer;
|
|
15304
|
+
}
|
|
15305
|
+
return renderBuffer;
|
|
15306
|
+
}
|
|
15307
|
+
|
|
15308
|
+
destroy() {
|
|
15309
|
+
for (let id in this._renderBuffersBasic) {
|
|
15310
|
+
this._renderBuffersBasic[id].destroy();
|
|
15311
|
+
}
|
|
15312
|
+
for (let id in this._renderBuffersScaled) {
|
|
15313
|
+
this._renderBuffersScaled[id].destroy();
|
|
15314
|
+
}
|
|
15315
|
+
}
|
|
15316
|
+
}
|
|
15317
|
+
|
|
15237
15318
|
/**
|
|
15238
15319
|
* @private
|
|
15239
15320
|
*/
|
|
@@ -15256,14 +15337,12 @@ const Renderer = function (scene, options) {
|
|
|
15256
15337
|
let stateSortDirty = true;
|
|
15257
15338
|
let imageDirty = true;
|
|
15258
15339
|
|
|
15259
|
-
|
|
15260
|
-
|
|
15261
|
-
|
|
15262
|
-
|
|
15263
|
-
const occlusionRenderBuffer2 = new RenderBuffer(canvas, gl);
|
|
15340
|
+
let transparentEnabled = true;
|
|
15341
|
+
let edgesEnabled = true;
|
|
15342
|
+
let saoEnabled = true;
|
|
15343
|
+
let pbrEnabled = true;
|
|
15264
15344
|
|
|
15265
|
-
const
|
|
15266
|
-
const snapshotBuffer = new RenderBuffer(canvas, gl);
|
|
15345
|
+
const renderBufferManager = new RenderBufferManager(scene);
|
|
15267
15346
|
|
|
15268
15347
|
let snapshotBound = false;
|
|
15269
15348
|
|
|
@@ -15272,6 +15351,26 @@ const Renderer = function (scene, options) {
|
|
|
15272
15351
|
|
|
15273
15352
|
this._occlusionTester = null; // Lazy-created in #addMarker()
|
|
15274
15353
|
|
|
15354
|
+
this.setTransparentEnabled = function (enabled) {
|
|
15355
|
+
transparentEnabled = enabled;
|
|
15356
|
+
imageDirty = true;
|
|
15357
|
+
};
|
|
15358
|
+
|
|
15359
|
+
this.setEdgesEnabled = function (enabled) {
|
|
15360
|
+
edgesEnabled = enabled;
|
|
15361
|
+
imageDirty = true;
|
|
15362
|
+
};
|
|
15363
|
+
|
|
15364
|
+
this.setSAOEnabled = function (enabled) {
|
|
15365
|
+
saoEnabled = enabled;
|
|
15366
|
+
imageDirty = true;
|
|
15367
|
+
};
|
|
15368
|
+
|
|
15369
|
+
this.setPBREnabled = function (enabled) {
|
|
15370
|
+
pbrEnabled = enabled;
|
|
15371
|
+
imageDirty = true;
|
|
15372
|
+
};
|
|
15373
|
+
|
|
15275
15374
|
this.needStateSort = function () {
|
|
15276
15375
|
stateSortDirty = true;
|
|
15277
15376
|
};
|
|
@@ -15288,11 +15387,7 @@ const Renderer = function (scene, options) {
|
|
|
15288
15387
|
|
|
15289
15388
|
this.webglContextRestored = function (gl) {
|
|
15290
15389
|
|
|
15291
|
-
|
|
15292
|
-
snapshotBuffer.webglContextRestored(gl);
|
|
15293
|
-
saoDepthRenderBuffer.webglContextRestored(gl);
|
|
15294
|
-
occlusionRenderBuffer1.webglContextRestored(gl);
|
|
15295
|
-
occlusionRenderBuffer2.webglContextRestored(gl);
|
|
15390
|
+
// renderBufferManager.webglContextRestored(gl);
|
|
15296
15391
|
|
|
15297
15392
|
saoOcclusionRenderer.init();
|
|
15298
15393
|
saoDepthLimitedBlurRenderer.init();
|
|
@@ -15477,7 +15572,7 @@ const Renderer = function (scene, options) {
|
|
|
15477
15572
|
|
|
15478
15573
|
const sao = scene.sao;
|
|
15479
15574
|
|
|
15480
|
-
if (sao.possible) {
|
|
15575
|
+
if (saoEnabled && sao.possible) {
|
|
15481
15576
|
drawSAOBuffers(params);
|
|
15482
15577
|
}
|
|
15483
15578
|
|
|
@@ -15492,6 +15587,10 @@ const Renderer = function (scene, options) {
|
|
|
15492
15587
|
|
|
15493
15588
|
// Render depth buffer
|
|
15494
15589
|
|
|
15590
|
+
const saoDepthRenderBuffer = renderBufferManager.getRenderBuffer("saoDepth", {
|
|
15591
|
+
depthTexture: WEBGL_INFO$1.SUPPORTED_EXTENSIONS["WEBGL_depth_texture"]
|
|
15592
|
+
});
|
|
15593
|
+
|
|
15495
15594
|
saoDepthRenderBuffer.bind();
|
|
15496
15595
|
saoDepthRenderBuffer.clear();
|
|
15497
15596
|
drawDepth(params);
|
|
@@ -15499,6 +15598,8 @@ const Renderer = function (scene, options) {
|
|
|
15499
15598
|
|
|
15500
15599
|
// Render occlusion buffer
|
|
15501
15600
|
|
|
15601
|
+
const occlusionRenderBuffer1 = renderBufferManager.getRenderBuffer("saoOcclusion");
|
|
15602
|
+
|
|
15502
15603
|
occlusionRenderBuffer1.bind();
|
|
15503
15604
|
occlusionRenderBuffer1.clear();
|
|
15504
15605
|
saoOcclusionRenderer.render(saoDepthRenderBuffer);
|
|
@@ -15508,6 +15609,8 @@ const Renderer = function (scene, options) {
|
|
|
15508
15609
|
|
|
15509
15610
|
// Horizontally blur occlusion buffer 1 into occlusion buffer 2
|
|
15510
15611
|
|
|
15612
|
+
const occlusionRenderBuffer2 = renderBufferManager.getRenderBuffer("saoOcclusion2");
|
|
15613
|
+
|
|
15511
15614
|
occlusionRenderBuffer2.bind();
|
|
15512
15615
|
occlusionRenderBuffer2.clear();
|
|
15513
15616
|
saoDepthLimitedBlurRenderer.render(saoDepthRenderBuffer, occlusionRenderBuffer1, 0);
|
|
@@ -15665,7 +15768,7 @@ const Renderer = function (scene, options) {
|
|
|
15665
15768
|
frameCtx.reset();
|
|
15666
15769
|
frameCtx.pass = params.pass;
|
|
15667
15770
|
frameCtx.withSAO = false;
|
|
15668
|
-
frameCtx.pbrEnabled = !!scene.pbrEnabled;
|
|
15771
|
+
frameCtx.pbrEnabled = pbrEnabled && !!scene.pbrEnabled;
|
|
15669
15772
|
|
|
15670
15773
|
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
|
15671
15774
|
|
|
@@ -15685,7 +15788,14 @@ const Renderer = function (scene, options) {
|
|
|
15685
15788
|
frameCtx.lineWidth = 1;
|
|
15686
15789
|
|
|
15687
15790
|
const saoPossible = scene.sao.possible;
|
|
15688
|
-
|
|
15791
|
+
|
|
15792
|
+
if (saoEnabled && saoPossible) {
|
|
15793
|
+
const occlusionRenderBuffer1 = renderBufferManager.getRenderBuffer("saoOcclusion");
|
|
15794
|
+
frameCtx.occlusionTexture = occlusionRenderBuffer1 ? occlusionRenderBuffer1.getTexture() : null;
|
|
15795
|
+
} else {
|
|
15796
|
+
frameCtx.occlusionTexture = null;
|
|
15797
|
+
|
|
15798
|
+
}
|
|
15689
15799
|
|
|
15690
15800
|
let i;
|
|
15691
15801
|
let len;
|
|
@@ -15738,15 +15848,17 @@ const Renderer = function (scene, options) {
|
|
|
15738
15848
|
const renderFlags = drawable.renderFlags;
|
|
15739
15849
|
|
|
15740
15850
|
if (renderFlags.colorOpaque) {
|
|
15741
|
-
if (saoPossible && drawable.saoEnabled) {
|
|
15851
|
+
if (saoEnabled && saoPossible && drawable.saoEnabled) {
|
|
15742
15852
|
normalDrawSAOBin[normalDrawSAOBinLen++] = drawable;
|
|
15743
15853
|
} else {
|
|
15744
15854
|
drawable.drawColorOpaque(frameCtx);
|
|
15745
15855
|
}
|
|
15746
15856
|
}
|
|
15747
15857
|
|
|
15748
|
-
if (
|
|
15749
|
-
|
|
15858
|
+
if (transparentEnabled) {
|
|
15859
|
+
if (renderFlags.colorTransparent) {
|
|
15860
|
+
normalFillTransparentBin[normalFillTransparentBinLen++] = drawable;
|
|
15861
|
+
}
|
|
15750
15862
|
}
|
|
15751
15863
|
|
|
15752
15864
|
if (renderFlags.xrayedSilhouetteTransparent) {
|
|
@@ -15773,36 +15885,38 @@ const Renderer = function (scene, options) {
|
|
|
15773
15885
|
selectedFillOpaqueBin[selectedFillOpaqueBinLen++] = drawable;
|
|
15774
15886
|
}
|
|
15775
15887
|
|
|
15776
|
-
if (
|
|
15777
|
-
|
|
15778
|
-
|
|
15888
|
+
if (edgesEnabled) {
|
|
15889
|
+
if (renderFlags.edgesOpaque) {
|
|
15890
|
+
normalEdgesOpaqueBin[normalEdgesOpaqueBinLen++] = drawable;
|
|
15891
|
+
}
|
|
15779
15892
|
|
|
15780
|
-
|
|
15781
|
-
|
|
15782
|
-
|
|
15893
|
+
if (renderFlags.edgesTransparent) {
|
|
15894
|
+
normalEdgesTransparentBin[normalEdgesTransparentBinLen++] = drawable;
|
|
15895
|
+
}
|
|
15783
15896
|
|
|
15784
|
-
|
|
15785
|
-
|
|
15786
|
-
|
|
15897
|
+
if (renderFlags.selectedEdgesTransparent) {
|
|
15898
|
+
selectedEdgesTransparentBin[selectedEdgesTransparentBinLen++] = drawable;
|
|
15899
|
+
}
|
|
15787
15900
|
|
|
15788
|
-
|
|
15789
|
-
|
|
15790
|
-
|
|
15901
|
+
if (renderFlags.selectedEdgesOpaque) {
|
|
15902
|
+
selectedEdgesOpaqueBin[selectedEdgesOpaqueBinLen++] = drawable;
|
|
15903
|
+
}
|
|
15791
15904
|
|
|
15792
|
-
|
|
15793
|
-
|
|
15794
|
-
|
|
15905
|
+
if (renderFlags.xrayedEdgesTransparent) {
|
|
15906
|
+
xrayEdgesTransparentBin[xrayEdgesTransparentBinLen++] = drawable;
|
|
15907
|
+
}
|
|
15795
15908
|
|
|
15796
|
-
|
|
15797
|
-
|
|
15798
|
-
|
|
15909
|
+
if (renderFlags.xrayedEdgesOpaque) {
|
|
15910
|
+
xrayEdgesOpaqueBin[xrayEdgesOpaqueBinLen++] = drawable;
|
|
15911
|
+
}
|
|
15799
15912
|
|
|
15800
|
-
|
|
15801
|
-
|
|
15802
|
-
|
|
15913
|
+
if (renderFlags.highlightedEdgesTransparent) {
|
|
15914
|
+
highlightedEdgesTransparentBin[highlightedEdgesTransparentBinLen++] = drawable;
|
|
15915
|
+
}
|
|
15803
15916
|
|
|
15804
|
-
|
|
15805
|
-
|
|
15917
|
+
if (renderFlags.highlightedEdgesOpaque) {
|
|
15918
|
+
highlightedEdgesOpaqueBin[highlightedEdgesOpaqueBinLen++] = drawable;
|
|
15919
|
+
}
|
|
15806
15920
|
}
|
|
15807
15921
|
}
|
|
15808
15922
|
}
|
|
@@ -16083,9 +16197,11 @@ const Renderer = function (scene, options) {
|
|
|
16083
16197
|
canvasPos[1] = canvas.clientHeight * 0.5;
|
|
16084
16198
|
}
|
|
16085
16199
|
|
|
16200
|
+
const pickBuffer = renderBufferManager.getRenderBuffer("pick");
|
|
16201
|
+
|
|
16086
16202
|
pickBuffer.bind();
|
|
16087
16203
|
|
|
16088
|
-
const pickable = gpuPickPickable(canvasPos, pickViewMatrix, pickProjMatrix, params);
|
|
16204
|
+
const pickable = gpuPickPickable(pickBuffer, canvasPos, pickViewMatrix, pickProjMatrix, params);
|
|
16089
16205
|
|
|
16090
16206
|
if (!pickable) {
|
|
16091
16207
|
pickBuffer.unbind();
|
|
@@ -16118,7 +16234,7 @@ const Renderer = function (scene, options) {
|
|
|
16118
16234
|
}
|
|
16119
16235
|
|
|
16120
16236
|
// if (params.pickSurfaceNormal !== false) {
|
|
16121
|
-
// gpuPickWorldNormal(pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult);
|
|
16237
|
+
// gpuPickWorldNormal(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult);
|
|
16122
16238
|
// }
|
|
16123
16239
|
|
|
16124
16240
|
pickResult.pickSurfacePrecision = true;
|
|
@@ -16130,7 +16246,7 @@ const Renderer = function (scene, options) {
|
|
|
16130
16246
|
|
|
16131
16247
|
if (pickable.canPickTriangle && pickable.canPickTriangle()) {
|
|
16132
16248
|
|
|
16133
|
-
gpuPickTriangle(pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult);
|
|
16249
|
+
gpuPickTriangle(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult);
|
|
16134
16250
|
|
|
16135
16251
|
pickable.pickTriangleSurface(pickViewMatrix, pickProjMatrix, pickResult);
|
|
16136
16252
|
|
|
@@ -16143,10 +16259,10 @@ const Renderer = function (scene, options) {
|
|
|
16143
16259
|
nearAndFar[0] = scene.camera.project.near;
|
|
16144
16260
|
nearAndFar[1] = scene.camera.project.far;
|
|
16145
16261
|
|
|
16146
|
-
gpuPickWorldPos(pickable, canvasPos, pickViewMatrix, pickProjMatrix, nearAndFar, pickResult);
|
|
16262
|
+
gpuPickWorldPos(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, nearAndFar, pickResult);
|
|
16147
16263
|
|
|
16148
16264
|
if (params.pickSurfaceNormal !== false) {
|
|
16149
|
-
gpuPickWorldNormal(pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult);
|
|
16265
|
+
gpuPickWorldNormal(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult);
|
|
16150
16266
|
}
|
|
16151
16267
|
|
|
16152
16268
|
pickResult.pickSurfacePrecision = false;
|
|
@@ -16163,7 +16279,7 @@ const Renderer = function (scene, options) {
|
|
|
16163
16279
|
};
|
|
16164
16280
|
})();
|
|
16165
16281
|
|
|
16166
|
-
function gpuPickPickable(canvasPos, pickViewMatrix, pickProjMatrix, params) {
|
|
16282
|
+
function gpuPickPickable(pickBuffer, canvasPos, pickViewMatrix, pickProjMatrix, params) {
|
|
16167
16283
|
|
|
16168
16284
|
frameCtx.reset();
|
|
16169
16285
|
frameCtx.backfaces = true;
|
|
@@ -16207,8 +16323,8 @@ const Renderer = function (scene, options) {
|
|
|
16207
16323
|
}
|
|
16208
16324
|
}
|
|
16209
16325
|
}
|
|
16210
|
-
|
|
16211
|
-
const pix = pickBuffer.read(Math.round(canvasPos[0]), Math.round(canvasPos[1]));
|
|
16326
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
16327
|
+
const pix = pickBuffer.read(Math.round(canvasPos[0] * resolutionScale), Math.round(canvasPos[1] * resolutionScale));
|
|
16212
16328
|
let pickID = pix[0] + (pix[1] * 256) + (pix[2] * 256 * 256) + (pix[3] * 256 * 256 * 256);
|
|
16213
16329
|
|
|
16214
16330
|
if (pickID < 0) {
|
|
@@ -16220,7 +16336,7 @@ const Renderer = function (scene, options) {
|
|
|
16220
16336
|
return pickable;
|
|
16221
16337
|
}
|
|
16222
16338
|
|
|
16223
|
-
function gpuPickTriangle(pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult) {
|
|
16339
|
+
function gpuPickTriangle(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult) {
|
|
16224
16340
|
|
|
16225
16341
|
if (!pickable.drawPickTriangles) {
|
|
16226
16342
|
return;
|
|
@@ -16243,7 +16359,8 @@ const Renderer = function (scene, options) {
|
|
|
16243
16359
|
|
|
16244
16360
|
pickable.drawPickTriangles(frameCtx);
|
|
16245
16361
|
|
|
16246
|
-
const
|
|
16362
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
16363
|
+
const pix = pickBuffer.read(Math.round(canvasPos[0] * resolutionScale), Math.round(canvasPos[1] * resolutionScale));
|
|
16247
16364
|
|
|
16248
16365
|
let primIndex = pix[0] + (pix[1] * 256) + (pix[2] * 256 * 256) + (pix[3] * 256 * 256 * 256);
|
|
16249
16366
|
|
|
@@ -16263,7 +16380,7 @@ const Renderer = function (scene, options) {
|
|
|
16263
16380
|
const tempMat4b = math.mat4();
|
|
16264
16381
|
const tempMat4c = math.mat4();
|
|
16265
16382
|
|
|
16266
|
-
return function (pickable, canvasPos, pickViewMatrix, pickProjMatrix, nearAndFar, pickResult) {
|
|
16383
|
+
return function (pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, nearAndFar, pickResult) {
|
|
16267
16384
|
|
|
16268
16385
|
frameCtx.reset();
|
|
16269
16386
|
frameCtx.backfaces = true;
|
|
@@ -16283,13 +16400,14 @@ const Renderer = function (scene, options) {
|
|
|
16283
16400
|
|
|
16284
16401
|
pickable.drawPickDepths(frameCtx); // Draw color-encoded fragment screen-space depths
|
|
16285
16402
|
|
|
16286
|
-
const
|
|
16403
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
16404
|
+
const pix = pickBuffer.read(Math.round(canvasPos[0] * resolutionScale), Math.round(canvasPos[1] * resolutionScale));
|
|
16287
16405
|
|
|
16288
16406
|
const screenZ = unpackDepth(pix); // Get screen-space Z at the given canvas coords
|
|
16289
16407
|
|
|
16290
16408
|
// Calculate clip space coordinates, which will be in range of x=[-1..1] and y=[-1..1], with y=(+1) at top
|
|
16291
|
-
const x = (canvasPos[0] - canvas.
|
|
16292
|
-
const y = -(canvasPos[1] - canvas.
|
|
16409
|
+
const x = (canvasPos[0] - canvas.clientWidth / 2) / (canvas.clientWidth / 2);
|
|
16410
|
+
const y = -(canvasPos[1] - canvas.clientHeight / 2) / (canvas.clientHeight / 2);
|
|
16293
16411
|
|
|
16294
16412
|
const origin = pickable.origin;
|
|
16295
16413
|
let pvMat;
|
|
@@ -16337,7 +16455,7 @@ const Renderer = function (scene, options) {
|
|
|
16337
16455
|
return math.dotVec4(vec, bitShift);
|
|
16338
16456
|
}
|
|
16339
16457
|
|
|
16340
|
-
function gpuPickWorldNormal(pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult) {
|
|
16458
|
+
function gpuPickWorldNormal(pickBuffer, pickable, canvasPos, pickViewMatrix, pickProjMatrix, pickResult) {
|
|
16341
16459
|
|
|
16342
16460
|
frameCtx.reset();
|
|
16343
16461
|
frameCtx.backfaces = true;
|
|
@@ -16355,7 +16473,8 @@ const Renderer = function (scene, options) {
|
|
|
16355
16473
|
|
|
16356
16474
|
pickable.drawPickNormals(frameCtx); // Draw color-encoded fragment World-space normals
|
|
16357
16475
|
|
|
16358
|
-
const
|
|
16476
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
16477
|
+
const pix = pickBuffer.read(Math.round(canvasPos[0] * resolutionScale), Math.round(canvasPos[1] * resolutionScale));
|
|
16359
16478
|
|
|
16360
16479
|
const worldNormal = [(pix[0] / 256.0) - 0.5, (pix[1] / 256.0) - 0.5, (pix[2] / 256.0) - 0.5];
|
|
16361
16480
|
|
|
@@ -16369,7 +16488,7 @@ const Renderer = function (scene, options) {
|
|
|
16369
16488
|
* @param marker
|
|
16370
16489
|
*/
|
|
16371
16490
|
this.addMarker = function (marker) {
|
|
16372
|
-
this._occlusionTester = this._occlusionTester || new OcclusionTester(scene);
|
|
16491
|
+
this._occlusionTester = this._occlusionTester || new OcclusionTester(scene, renderBufferManager);
|
|
16373
16492
|
this._occlusionTester.addMarker(marker);
|
|
16374
16493
|
scene.occlusionTestCountdown = 0;
|
|
16375
16494
|
};
|
|
@@ -16443,6 +16562,7 @@ const Renderer = function (scene, options) {
|
|
|
16443
16562
|
* @private
|
|
16444
16563
|
*/
|
|
16445
16564
|
this.readPixels = function (pixels, colors, len, opaqueOnly) {
|
|
16565
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
16446
16566
|
snapshotBuffer.bind();
|
|
16447
16567
|
snapshotBuffer.clear();
|
|
16448
16568
|
this.render({force: true, opaqueOnly: opaqueOnly});
|
|
@@ -16471,6 +16591,7 @@ const Renderer = function (scene, options) {
|
|
|
16471
16591
|
* Exit snapshot mode using endSnapshot().
|
|
16472
16592
|
*/
|
|
16473
16593
|
this.beginSnapshot = function () {
|
|
16594
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
16474
16595
|
snapshotBuffer.bind();
|
|
16475
16596
|
snapshotBuffer.clear();
|
|
16476
16597
|
snapshotBound = true;
|
|
@@ -16483,6 +16604,7 @@ const Renderer = function (scene, options) {
|
|
|
16483
16604
|
if (!snapshotBound) {
|
|
16484
16605
|
return;
|
|
16485
16606
|
}
|
|
16607
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
16486
16608
|
snapshotBuffer.clear();
|
|
16487
16609
|
this.render({force: true, opaqueOnly: false});
|
|
16488
16610
|
imageDirty = true;
|
|
@@ -16495,6 +16617,7 @@ const Renderer = function (scene, options) {
|
|
|
16495
16617
|
* @returns {String} The image data URI.
|
|
16496
16618
|
*/
|
|
16497
16619
|
this.readSnapshot = function (params) {
|
|
16620
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
16498
16621
|
const imageDataURI = snapshotBuffer.readImage(params);
|
|
16499
16622
|
return imageDataURI;
|
|
16500
16623
|
};
|
|
@@ -16508,6 +16631,7 @@ const Renderer = function (scene, options) {
|
|
|
16508
16631
|
if (!snapshotBound) {
|
|
16509
16632
|
return;
|
|
16510
16633
|
}
|
|
16634
|
+
const snapshotBuffer = renderBufferManager.getRenderBuffer("snapshot");
|
|
16511
16635
|
snapshotBuffer.unbind();
|
|
16512
16636
|
snapshotBound = false;
|
|
16513
16637
|
};
|
|
@@ -16521,11 +16645,7 @@ const Renderer = function (scene, options) {
|
|
|
16521
16645
|
drawableTypeInfo = {};
|
|
16522
16646
|
drawables = {};
|
|
16523
16647
|
|
|
16524
|
-
|
|
16525
|
-
snapshotBuffer.destroy();
|
|
16526
|
-
saoDepthRenderBuffer.destroy();
|
|
16527
|
-
occlusionRenderBuffer1.destroy();
|
|
16528
|
-
occlusionRenderBuffer2.destroy();
|
|
16648
|
+
renderBufferManager.destroy();
|
|
16529
16649
|
|
|
16530
16650
|
saoOcclusionRenderer.destroy();
|
|
16531
16651
|
saoDepthLimitedBlurRenderer.destroy();
|
|
@@ -39283,47 +39403,75 @@ class DistanceMeasurementsPlugin extends Plugin {
|
|
|
39283
39403
|
}
|
|
39284
39404
|
|
|
39285
39405
|
/**
|
|
39286
|
-
* {@link Viewer} plugin that improves interactivity by
|
|
39406
|
+
* {@link Viewer} plugin that improves interactivity by temporarily switching to fast and simple rendering while the
|
|
39407
|
+
* {@link Camera} is moving or the {@link Canvas} is resizing.
|
|
39408
|
+
*
|
|
39409
|
+
* FastNavPlugin works by disabling specified rendering features, and optionally down-scaling the canvas, whenever we
|
|
39410
|
+
* move the Camera or resize the Canvas. Then, once the Camera or Canvas has been at rest after a certain time, FastNavPlugin
|
|
39411
|
+
* restores those rendering features and original canvas scale again.
|
|
39412
|
+
*
|
|
39413
|
+
* The effect we experience is a low-quality view while moving, then a high-quality view
|
|
39414
|
+
* after we stop, following an optional delay.
|
|
39415
|
+
*
|
|
39416
|
+
* Down-scaling the canvas resolution gives particularly good results. For example, scaling by ````0.5````
|
|
39417
|
+
* means that we're rendering a quarter of the pixels while moving, which makes the Viewer noticeably smoother
|
|
39418
|
+
* with big models.
|
|
39287
39419
|
*
|
|
39288
39420
|
* # Usage
|
|
39289
39421
|
*
|
|
39290
39422
|
* In the example below, we'll create a {@link Viewer}, add a {@link FastNavPlugin}, then use an {@link XKTLoaderPlugin} to load a model.
|
|
39291
39423
|
*
|
|
39292
|
-
*
|
|
39293
|
-
*
|
|
39424
|
+
* Whenever our Camera moves, the FastNavPlugin will:
|
|
39425
|
+
*
|
|
39426
|
+
* * disable edges,
|
|
39427
|
+
* * disable ambient shadows,
|
|
39428
|
+
* * disable physically-based materials (switching to non-PBR),
|
|
39429
|
+
* * hide transparent objects, and
|
|
39430
|
+
* * down-scale the canvas by 0.5, causing 75% less pixels to render.
|
|
39294
39431
|
*
|
|
39295
|
-
*
|
|
39432
|
+
* We'll also configure a 0.5 second delay before we transition back to high-quality each time we stop moving, so that we're
|
|
39433
|
+
* not continually flipping between low and high quality as we interact.
|
|
39296
39434
|
*
|
|
39297
39435
|
* * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#performance_FastNavPlugin)]
|
|
39298
39436
|
*
|
|
39299
39437
|
* ````javascript
|
|
39300
39438
|
* import {Viewer, XKTLoaderPlugin, FastNavPlugin} from "xeokit-sdk.es.js";
|
|
39301
39439
|
*
|
|
39440
|
+
* // Create a Viewer with PBR and SAO enabled
|
|
39441
|
+
*
|
|
39302
39442
|
* const viewer = new Viewer({
|
|
39303
39443
|
* canvasId: "myCanvas",
|
|
39304
39444
|
* transparent: true,
|
|
39305
|
-
*
|
|
39306
|
-
*
|
|
39445
|
+
* pbr: true, // Enable physically-based rendering for Viewer
|
|
39446
|
+
* sao: true // Enable ambient shadows for Viewer
|
|
39307
39447
|
* });
|
|
39308
39448
|
*
|
|
39309
39449
|
* viewer.scene.camera.eye = [-66.26, 105.84, -281.92];
|
|
39310
39450
|
* viewer.scene.camera.look = [42.45, 49.62, -43.59];
|
|
39311
39451
|
* viewer.scene.camera.up = [0.05, 0.95, 0.15];
|
|
39312
39452
|
*
|
|
39453
|
+
* // Install a FastNavPlugin
|
|
39454
|
+
*
|
|
39313
39455
|
* new FastNavPlugin(viewer, {
|
|
39314
|
-
*
|
|
39315
|
-
*
|
|
39316
|
-
*
|
|
39456
|
+
* dynamicEdges: false, // Don't show edges while moving (default is false)
|
|
39457
|
+
* dynamicSAO: false, // Don't show ambient shadows while moving (default is false)
|
|
39458
|
+
* dynamicPBR: false, // Non-physically-based rendering while moving (default is false)
|
|
39459
|
+
* dynamicTransparent: false, // Hide transparent objects while moving (default is false)
|
|
39460
|
+
* dynamicCanvasResolution: true, // Reduce canvas resolution while moving (default is false)
|
|
39461
|
+
* dynamicCanvasResolutionScale: 0.5, // Factor by which we reduce canvas resolution when moving (default is 0.6)
|
|
39462
|
+
* delayBeforeStatic: true, // When we stop, delay before returning to quality static render (default is true)
|
|
39463
|
+
* delayBeforeStaticDuration: 0.5 // The delay duration, in seconds (default is 0.5)
|
|
39317
39464
|
* });
|
|
39318
39465
|
*
|
|
39466
|
+
* // Load a BIM model from XKT
|
|
39467
|
+
*
|
|
39319
39468
|
* const xktLoader = new XKTLoaderPlugin(viewer);
|
|
39320
39469
|
*
|
|
39321
39470
|
* const model = xktLoader.load({
|
|
39322
39471
|
* id: "myModel",
|
|
39323
39472
|
* src: "./models/xkt/HolterTower.xkt",
|
|
39324
|
-
*
|
|
39325
|
-
*
|
|
39326
|
-
* pbrEnabled: true
|
|
39473
|
+
* sao: true, // Enable ambient shadows for this model
|
|
39474
|
+
* pbr: true // Enable physically-based rendering for this model
|
|
39327
39475
|
* });
|
|
39328
39476
|
* ````
|
|
39329
39477
|
*
|
|
@@ -39336,63 +39484,66 @@ class FastNavPlugin extends Plugin {
|
|
|
39336
39484
|
* @param {Viewer} viewer The Viewer.
|
|
39337
39485
|
* @param {Object} cfg FastNavPlugin configuration.
|
|
39338
39486
|
* @param {String} [cfg.id="FastNav"] Optional ID for this plugin, so that we can find it within {@link Viewer#plugins}.
|
|
39339
|
-
* @param {Boolean} [cfg.
|
|
39340
|
-
* @param {Boolean} [cfg.
|
|
39341
|
-
* @param {Boolean} [cfg.
|
|
39487
|
+
* @param {Boolean} [cfg.dynamicPBR=false] Whether to enable physically-based rendering (PBR) while the camera is moving.
|
|
39488
|
+
* @param {Boolean} [cfg.dynamicSAO=false] Whether to enable scalable ambient occlusion (SAO) while the camera is moving.
|
|
39489
|
+
* @param {Boolean} [cfg.dynamicEdges=false] Whether to enable enhanced edges while the camera is moving.
|
|
39490
|
+
* @param {Boolean} [cfg.dynamicTransparent=true] Whether to show transparent objects when the camera is moving.
|
|
39491
|
+
* @param {Number} [cfg.dynamicCanvasResolution=false] Whether to down-scale the canvas resolution while the camera is moving.
|
|
39492
|
+
* @param {Number} [cfg.dynamicCanvasResolutionScale=0.6] The factor by which we downscale the canvas resolution while the camera is moving.
|
|
39493
|
+
* @param {Boolean} [cfg.delayBeforeStatic=true] Once the camera stops moving, whether to have a delay before transitioning back to normal rendering.
|
|
39494
|
+
* @param {Number} [cfg.delayBeforeStaticDuration=0.5] Delay in seconds before transitioning back to normal rendering when camera stops moving. Only works when ````delayBeforeStatic```` is ````true````.
|
|
39342
39495
|
*/
|
|
39343
39496
|
constructor(viewer, cfg = {}) {
|
|
39344
39497
|
|
|
39345
39498
|
super("FastNav", viewer);
|
|
39346
39499
|
|
|
39347
|
-
this.
|
|
39348
|
-
this.
|
|
39349
|
-
this.
|
|
39350
|
-
|
|
39351
|
-
this.
|
|
39352
|
-
this.
|
|
39500
|
+
this._dynamicPBR = !!cfg.dynamicPBR;
|
|
39501
|
+
this._dynamicSAO = !!cfg.dynamicSAO;
|
|
39502
|
+
this._dynamicEdges = !!cfg.dynamicEdges;
|
|
39503
|
+
this._dynamicTransparent = (cfg.dynamicTransparent !== false);
|
|
39504
|
+
this._dynamicCanvasResolution = !!cfg.dynamicCanvasResolution;
|
|
39505
|
+
this._dynamicCanvasResolutionScale = cfg.dynamicCanvasResolutionScale || 0.6;
|
|
39506
|
+
this._delayBeforeStatic = (cfg.delayBeforeStatic !== false);
|
|
39507
|
+
this._delayBeforeStaticDuration = cfg.delayBeforeStaticDuration || 0.5;
|
|
39353
39508
|
|
|
39354
|
-
let
|
|
39355
|
-
let timer = timeoutDuration;
|
|
39509
|
+
let timer = this._delayBeforeStaticDuration * 1000;
|
|
39356
39510
|
let fastMode = false;
|
|
39357
39511
|
|
|
39358
|
-
|
|
39359
|
-
timer =
|
|
39512
|
+
const switchToLowQuality = () => {
|
|
39513
|
+
timer = (this._delayBeforeStaticDuration * 1000);
|
|
39360
39514
|
if (!fastMode) {
|
|
39361
|
-
this.
|
|
39362
|
-
viewer.scene.
|
|
39363
|
-
viewer.scene.
|
|
39364
|
-
viewer.scene.
|
|
39515
|
+
viewer.scene._renderer.setPBREnabled(this._dynamicPBR);
|
|
39516
|
+
viewer.scene._renderer.setSAOEnabled(this._dynamicSAO);
|
|
39517
|
+
viewer.scene._renderer.setTransparentEnabled(this._dynamicTransparent);
|
|
39518
|
+
viewer.scene._renderer.setEdgesEnabled(this._dynamicEdges);
|
|
39519
|
+
if (this._dynamicCanvasResolution) {
|
|
39520
|
+
viewer.scene.canvas.resolutionScale = this._dynamicCanvasResolutionScale;
|
|
39521
|
+
} else {
|
|
39522
|
+
viewer.scene.canvas.resolutionScale = 1;
|
|
39523
|
+
}
|
|
39365
39524
|
fastMode = true;
|
|
39366
39525
|
}
|
|
39367
|
-
}
|
|
39526
|
+
};
|
|
39368
39527
|
|
|
39369
|
-
|
|
39370
|
-
|
|
39371
|
-
|
|
39372
|
-
|
|
39373
|
-
|
|
39374
|
-
|
|
39375
|
-
|
|
39376
|
-
|
|
39377
|
-
|
|
39378
|
-
|
|
39528
|
+
const switchToHighQuality = () => {
|
|
39529
|
+
viewer.scene.canvas.resolutionScale = 1;
|
|
39530
|
+
viewer.scene._renderer.setEdgesEnabled(true);
|
|
39531
|
+
viewer.scene._renderer.setPBREnabled(true);
|
|
39532
|
+
viewer.scene._renderer.setSAOEnabled(true);
|
|
39533
|
+
viewer.scene._renderer.setTransparentEnabled(true);
|
|
39534
|
+
fastMode = false;
|
|
39535
|
+
};
|
|
39536
|
+
|
|
39537
|
+
this._onCanvasBoundary = viewer.scene.canvas.on("boundary", switchToLowQuality);
|
|
39538
|
+
this._onCameraMatrix = viewer.scene.camera.on("matrix", switchToLowQuality);
|
|
39379
39539
|
|
|
39380
|
-
this._onSceneTick = viewer.scene.on("tick", (tickEvent) => {
|
|
39540
|
+
this._onSceneTick = viewer.scene.on("tick", (tickEvent) => {
|
|
39381
39541
|
if (!fastMode) {
|
|
39382
39542
|
return;
|
|
39383
39543
|
}
|
|
39384
39544
|
timer -= tickEvent.deltaTime;
|
|
39385
|
-
if (timer <= 0) {
|
|
39386
|
-
|
|
39387
|
-
this._startFade();
|
|
39388
|
-
this._pInterval2 = setTimeout(() => { // Needed by Firefox - https://github.com/xeokit/xeokit-sdk/issues/624
|
|
39389
|
-
viewer.scene.pbrEnabled = this._pbrEnabled;
|
|
39390
|
-
viewer.scene.sao.enabled = this._saoEnabled;
|
|
39391
|
-
viewer.scene.edgeMaterial.edges = this._edgesEnabled;
|
|
39392
|
-
}, 100);
|
|
39393
|
-
|
|
39394
|
-
fastMode = false;
|
|
39395
|
-
}
|
|
39545
|
+
if ((!this._delayBeforeStatic) || timer <= 0) {
|
|
39546
|
+
switchToHighQuality();
|
|
39396
39547
|
}
|
|
39397
39548
|
});
|
|
39398
39549
|
|
|
@@ -39410,184 +39561,216 @@ class FastNavPlugin extends Plugin {
|
|
|
39410
39561
|
if (!down) {
|
|
39411
39562
|
return;
|
|
39412
39563
|
}
|
|
39413
|
-
|
|
39414
|
-
if (!fastMode) {
|
|
39415
|
-
this._cancelFade();
|
|
39416
|
-
viewer.scene.pbrEnabled = false;
|
|
39417
|
-
viewer.scene.sao.enabled = false;
|
|
39418
|
-
viewer.scene.edgeMaterial.edges = false;
|
|
39419
|
-
fastMode = true;
|
|
39420
|
-
}
|
|
39564
|
+
switchToLowQuality();
|
|
39421
39565
|
});
|
|
39422
39566
|
}
|
|
39423
39567
|
|
|
39424
|
-
|
|
39568
|
+
/**
|
|
39569
|
+
* Gets whether to enable physically-based rendering (PBR) while the camera is moving.
|
|
39570
|
+
*
|
|
39571
|
+
* Default is ````false````.
|
|
39572
|
+
*
|
|
39573
|
+
* @return {Boolean} Whether PBR will be enabled while the camera is moving.
|
|
39574
|
+
*/
|
|
39575
|
+
get dynamicPBR() {
|
|
39576
|
+
return this._dynamicPBR;
|
|
39577
|
+
}
|
|
39425
39578
|
|
|
39426
|
-
|
|
39427
|
-
|
|
39428
|
-
|
|
39579
|
+
/**
|
|
39580
|
+
* Sets whether to enable physically-based rendering (PBR) while the camera is moving.
|
|
39581
|
+
*
|
|
39582
|
+
* Default is ````false````.
|
|
39583
|
+
*
|
|
39584
|
+
* @param {Boolean} dynamicPBR Whether PBR will be enabled while the camera is moving.
|
|
39585
|
+
*/
|
|
39586
|
+
set dynamicPBR(dynamicPBR) {
|
|
39587
|
+
this._dynamicPBR = dynamicPBR;
|
|
39588
|
+
}
|
|
39429
39589
|
|
|
39430
|
-
|
|
39431
|
-
|
|
39590
|
+
/**
|
|
39591
|
+
* Gets whether to enable Scalable Ambient Obscurrance (SAO) while the camera is moving.
|
|
39592
|
+
*
|
|
39593
|
+
* Default is ````false````.
|
|
39594
|
+
*
|
|
39595
|
+
* @return {Boolean} Whether SAO will be enabled.
|
|
39596
|
+
*/
|
|
39597
|
+
get dynamicSAO() {
|
|
39598
|
+
return this._dynamicSAO;
|
|
39599
|
+
}
|
|
39432
39600
|
|
|
39433
|
-
|
|
39434
|
-
|
|
39435
|
-
|
|
39436
|
-
|
|
39601
|
+
/**
|
|
39602
|
+
* Sets whether to enable Scalable Ambient Obscurrance (SAO) while the camera is moving.
|
|
39603
|
+
*
|
|
39604
|
+
* Default is ````false````.
|
|
39605
|
+
*
|
|
39606
|
+
* @param {Boolean} dynamicSAO Whether SAO will be enabled while the camera is moving.
|
|
39607
|
+
*/
|
|
39608
|
+
set dynamicSAO(dynamicSAO) {
|
|
39609
|
+
this._dynamicSAO = dynamicSAO;
|
|
39610
|
+
}
|
|
39437
39611
|
|
|
39438
|
-
|
|
39612
|
+
/**
|
|
39613
|
+
* Gets whether to enable enhanced edges while the camera is moving.
|
|
39614
|
+
*
|
|
39615
|
+
* Default is ````false````.
|
|
39616
|
+
*
|
|
39617
|
+
* @return {Boolean} Whether edges will be enabled while the camera is moving.
|
|
39618
|
+
*/
|
|
39619
|
+
get dynamicEdges() {
|
|
39620
|
+
return this._dynamicEdges;
|
|
39621
|
+
}
|
|
39439
39622
|
|
|
39440
|
-
|
|
39441
|
-
|
|
39442
|
-
|
|
39443
|
-
|
|
39444
|
-
|
|
39445
|
-
|
|
39446
|
-
|
|
39447
|
-
|
|
39448
|
-
this.
|
|
39449
|
-
|
|
39450
|
-
this._img.style.height = canvas.height + "px";
|
|
39451
|
-
this._img.width = canvas.width;
|
|
39452
|
-
this._img.height = canvas.height;
|
|
39453
|
-
this._img.src = ""; // Needed by Firefox - https://github.com/xeokit/xeokit-sdk/issues/624
|
|
39454
|
-
this._img.src = viewer.getSnapshot({
|
|
39455
|
-
format: "png",
|
|
39456
|
-
includeGizmos: true
|
|
39457
|
-
});
|
|
39458
|
-
this._img.style.visibility = "visible";
|
|
39459
|
-
this._img.style.opacity = 1;
|
|
39460
|
-
|
|
39461
|
-
let opacity = 1;
|
|
39462
|
-
this._pInterval = setInterval(() => {
|
|
39463
|
-
opacity -= inc;
|
|
39464
|
-
if (opacity > 0) {
|
|
39465
|
-
this._img.style.opacity = opacity;
|
|
39466
|
-
const canvasOffset = cumulativeOffset(canvas);
|
|
39467
|
-
this._img.style.left = canvasOffset.left + "px";
|
|
39468
|
-
this._img.style.top = canvasOffset.top + "px";
|
|
39469
|
-
this._img.style.width = canvas.width + "px";
|
|
39470
|
-
this._img.style.height = canvas.height + "px";
|
|
39471
|
-
this._img.style.opacity = opacity;
|
|
39472
|
-
this._img.width = canvas.width;
|
|
39473
|
-
this._img.height = canvas.height;
|
|
39623
|
+
/**
|
|
39624
|
+
* Sets whether to enable enhanced edges while the camera is moving.
|
|
39625
|
+
*
|
|
39626
|
+
* Default is ````false````.
|
|
39627
|
+
*
|
|
39628
|
+
* @param {Boolean} dynamicEdges Whether edge enhancement will be enabled while the camera is moving.
|
|
39629
|
+
*/
|
|
39630
|
+
set dynamicEdges(dynamicEdges) {
|
|
39631
|
+
this._dynamicEdges = dynamicEdges;
|
|
39632
|
+
}
|
|
39474
39633
|
|
|
39475
|
-
|
|
39476
|
-
|
|
39477
|
-
|
|
39478
|
-
|
|
39479
|
-
|
|
39480
|
-
|
|
39481
|
-
|
|
39482
|
-
|
|
39483
|
-
|
|
39484
|
-
_initFade() {
|
|
39485
|
-
this._img = document.createElement('img');
|
|
39486
|
-
const canvas = this.viewer.scene.canvas.canvas;
|
|
39487
|
-
const canvasOffset = cumulativeOffset(canvas);
|
|
39488
|
-
(parseInt(canvas.style["z-index"]) || 0) + 1;
|
|
39489
|
-
this._img.style.position = "absolute";
|
|
39490
|
-
this._img.style.visibility = "hidden";
|
|
39491
|
-
this._img.style["pointer-events"] = "none";
|
|
39492
|
-
this._img.style["z-index"] = 5;
|
|
39493
|
-
this._img.style.left = canvasOffset.left + "px";
|
|
39494
|
-
this._img.style.top = canvasOffset.top + "px";
|
|
39495
|
-
this._img.style.width = canvas.width + "px";
|
|
39496
|
-
this._img.style.height = canvas.height + "px";
|
|
39497
|
-
this._img.style.opacity = 1;
|
|
39498
|
-
this._img.width = canvas.width;
|
|
39499
|
-
this._img.height = canvas.height;
|
|
39500
|
-
this._img.left = canvasOffset.left;
|
|
39501
|
-
this._img.top = canvasOffset.top;
|
|
39502
|
-
canvas.parentNode.insertBefore(this._img, canvas.nextSibling);
|
|
39503
|
-
}
|
|
39504
|
-
|
|
39505
|
-
_cancelFade() {
|
|
39506
|
-
if (!this._img) {
|
|
39507
|
-
return;
|
|
39508
|
-
}
|
|
39509
|
-
if (this._pInterval) {
|
|
39510
|
-
clearInterval(this._pInterval);
|
|
39511
|
-
this._pInterval = null;
|
|
39512
|
-
}
|
|
39513
|
-
if (this._pInterval2) {
|
|
39514
|
-
clearInterval(this._pInterval2);
|
|
39515
|
-
this._pInterval2 = null;
|
|
39516
|
-
}
|
|
39517
|
-
this._img.style.opacity = 0;
|
|
39518
|
-
this._img.style.visibility = "hidden";
|
|
39634
|
+
/**
|
|
39635
|
+
* Gets whether to show transparent objects while the camera is moving.
|
|
39636
|
+
*
|
|
39637
|
+
* Default is ````true````.
|
|
39638
|
+
*
|
|
39639
|
+
* @return {Boolean} Whether to show transparent objects while the camera is moving.
|
|
39640
|
+
*/
|
|
39641
|
+
get dynamicTransparent() {
|
|
39642
|
+
return this._dynamicTransparent
|
|
39519
39643
|
}
|
|
39520
39644
|
|
|
39521
39645
|
/**
|
|
39522
|
-
* Sets whether to
|
|
39646
|
+
* Sets whether to show transparent objects while the camera is moving.
|
|
39647
|
+
*
|
|
39648
|
+
* Default is ````true````.
|
|
39523
39649
|
*
|
|
39524
|
-
* @
|
|
39650
|
+
* @param {Boolean} dynamicTransparent Whether to show transparent objects while the camera is moving.
|
|
39525
39651
|
*/
|
|
39526
|
-
set
|
|
39527
|
-
this.
|
|
39652
|
+
set dynamicTransparent(dynamicTransparent) {
|
|
39653
|
+
this._dynamicTransparent = (dynamicTransparent !== false);
|
|
39528
39654
|
}
|
|
39529
39655
|
|
|
39530
39656
|
/**
|
|
39531
|
-
* Gets whether to
|
|
39657
|
+
* Gets whether to down-scale the canvas resolution while the camera is moving.
|
|
39658
|
+
*
|
|
39659
|
+
* Default is ````true````.
|
|
39660
|
+
*
|
|
39661
|
+
* The down-scaling factor is configured via {@link FastNavPlugin#dynamicCanvasResolutionScale}.
|
|
39532
39662
|
*
|
|
39533
|
-
* @return {Boolean} Whether
|
|
39663
|
+
* @return {Boolean} Whether to down-scale the canvas resolution while the camera is moving.
|
|
39534
39664
|
*/
|
|
39535
|
-
get
|
|
39536
|
-
return this.
|
|
39665
|
+
get dynamicCanvasResolution() {
|
|
39666
|
+
return this._dynamicCanvasResolution;
|
|
39537
39667
|
}
|
|
39538
39668
|
|
|
39539
39669
|
/**
|
|
39540
|
-
* Sets whether to
|
|
39670
|
+
* Sets whether to down-scale the canvas resolution while the camera is moving.
|
|
39541
39671
|
*
|
|
39542
|
-
*
|
|
39672
|
+
* Default is ````true````.
|
|
39673
|
+
*
|
|
39674
|
+
* The down-scaling factor is configured via {@link FastNavPlugin#dynamicCanvasResolutionScale}.
|
|
39675
|
+
*
|
|
39676
|
+
* @param {Boolean} dynamicCanvasResolution Whether to down-scale the canvas resolution while the camera is moving.
|
|
39543
39677
|
*/
|
|
39544
|
-
set
|
|
39545
|
-
this.
|
|
39678
|
+
set dynamicCanvasResolution(dynamicCanvasResolution) {
|
|
39679
|
+
this._dynamicCanvasResolution = dynamicCanvasResolution;
|
|
39546
39680
|
}
|
|
39547
39681
|
|
|
39548
39682
|
/**
|
|
39549
|
-
* Gets
|
|
39683
|
+
* Gets the factor by which we downscale the canvas resolution while the camera is moving.
|
|
39550
39684
|
*
|
|
39551
|
-
*
|
|
39685
|
+
* This allows us to render a low-resolution image to the canvas while we're moving the camera.
|
|
39686
|
+
*
|
|
39687
|
+
* Accepted range is ````[0.0 .. 1.0]````.
|
|
39688
|
+
*
|
|
39689
|
+
* Default is ````0.6````.
|
|
39690
|
+
*
|
|
39691
|
+
* @return {Number} Factor by which we downscale the canvas resolution while the camera is moving.
|
|
39552
39692
|
*/
|
|
39553
|
-
get
|
|
39554
|
-
return this.
|
|
39693
|
+
get dynamicCanvasResolutionScale() {
|
|
39694
|
+
return this._dynamicCanvasResolutionScale;
|
|
39695
|
+
}
|
|
39696
|
+
|
|
39697
|
+
/**
|
|
39698
|
+
* Sets the factor by which we downscale the canvas resolution while the camera is moving.
|
|
39699
|
+
*
|
|
39700
|
+
* This allows us to render a low-resolution image to the canvas while we're moving the camera.
|
|
39701
|
+
*
|
|
39702
|
+
* Accepted range is ````[0.0 .. 1.0]````.
|
|
39703
|
+
*
|
|
39704
|
+
* Default is ````0.6````.
|
|
39705
|
+
*
|
|
39706
|
+
* @param {Number} dynamicCanvasResolutionScale Factor by which we downscale the canvas resolution while the camera is moving.
|
|
39707
|
+
*/
|
|
39708
|
+
set dynamicCanvasResolutionScale(dynamicCanvasResolutionScale) {
|
|
39709
|
+
this._dynamicCanvasResolutionScale = dynamicCanvasResolutionScale || 0.6;
|
|
39710
|
+
}
|
|
39711
|
+
|
|
39712
|
+
/**
|
|
39713
|
+
* Gets whether to have a delay before transitioning back to normal static rendering after the camera stops moving.
|
|
39714
|
+
*
|
|
39715
|
+
* The delay duration is configured via {@link FastNavPlugin#delayBeforeStaticDuration}.
|
|
39716
|
+
*
|
|
39717
|
+
* Default is ````true````.
|
|
39718
|
+
*
|
|
39719
|
+
* @return {Boolean} Whether to have a delay.
|
|
39720
|
+
*/
|
|
39721
|
+
get delayBeforeStatic() {
|
|
39722
|
+
return this._delayBeforeStatic;
|
|
39723
|
+
}
|
|
39724
|
+
|
|
39725
|
+
/**
|
|
39726
|
+
* Sets whether to have a delay before transitioning back to normal static rendering after the camera stops moving.
|
|
39727
|
+
*
|
|
39728
|
+
* The delay duration is configured via {@link FastNavPlugin#delayBeforeStaticDuration}.
|
|
39729
|
+
*
|
|
39730
|
+
* Default is ````true````.
|
|
39731
|
+
*
|
|
39732
|
+
* @param {Boolean} delayBeforeStatic Whether to have a delay.
|
|
39733
|
+
*/
|
|
39734
|
+
set delayBeforeStatic(delayBeforeStatic) {
|
|
39735
|
+
this._delayBeforeStatic = delayBeforeStatic;
|
|
39555
39736
|
}
|
|
39556
39737
|
|
|
39557
39738
|
/**
|
|
39558
|
-
*
|
|
39739
|
+
* Gets the delay in seconds before transitioning back to normal static rendering when camera stops moving.
|
|
39740
|
+
*
|
|
39741
|
+
* The delay is enabled when {@link FastNavPlugin#delayBeforeStatic} is ````true````.
|
|
39742
|
+
*
|
|
39743
|
+
* Default is ````0.5```` seconds.
|
|
39559
39744
|
*
|
|
39560
|
-
* @return {
|
|
39745
|
+
* @return {Number} Timeout duration in seconds.
|
|
39561
39746
|
*/
|
|
39562
|
-
|
|
39563
|
-
this.
|
|
39747
|
+
get delayBeforeStaticDuration() {
|
|
39748
|
+
return this._delayBeforeStaticDuration;
|
|
39564
39749
|
}
|
|
39565
39750
|
|
|
39566
39751
|
/**
|
|
39567
|
-
*
|
|
39752
|
+
* Sets the delay in seconds before transitioning back to normal static rendering when camera stops moving.
|
|
39568
39753
|
*
|
|
39569
|
-
*
|
|
39754
|
+
* The delay is enabled when {@link FastNavPlugin#delayBeforeStatic} is ````true````.
|
|
39755
|
+
*
|
|
39756
|
+
* Default is ````0.5```` seconds.
|
|
39757
|
+
*
|
|
39758
|
+
* @param {Number} delayBeforeStaticDuration Timeout duration in seconds.
|
|
39570
39759
|
*/
|
|
39571
|
-
|
|
39572
|
-
|
|
39760
|
+
set delayBeforeStaticDuration(delayBeforeStaticDuration) {
|
|
39761
|
+
this._delayBeforeStaticDuration = delayBeforeStaticDuration !== null && delayBeforeStaticDuration !== undefined ? delayBeforeStaticDuration : 0.5;
|
|
39573
39762
|
}
|
|
39574
39763
|
|
|
39575
39764
|
/**
|
|
39576
39765
|
* @private
|
|
39577
39766
|
*/
|
|
39578
39767
|
send(name, value) {
|
|
39579
|
-
switch (name) {
|
|
39580
|
-
case "clear":
|
|
39581
|
-
this._cancelFade();
|
|
39582
|
-
break;
|
|
39583
|
-
}
|
|
39584
39768
|
}
|
|
39585
39769
|
|
|
39586
39770
|
/**
|
|
39587
39771
|
* Destroys this plugin.
|
|
39588
39772
|
*/
|
|
39589
39773
|
destroy() {
|
|
39590
|
-
this._cancelFade();
|
|
39591
39774
|
this.viewer.scene.camera.off(this._onCameraMatrix);
|
|
39592
39775
|
this.viewer.scene.canvas.off(this._onCanvasBoundary);
|
|
39593
39776
|
this.viewer.scene.input.off(this._onSceneMouseDown);
|
|
@@ -39595,27 +39778,9 @@ class FastNavPlugin extends Plugin {
|
|
|
39595
39778
|
this.viewer.scene.input.off(this._onSceneMouseMove);
|
|
39596
39779
|
this.viewer.scene.off(this._onSceneTick);
|
|
39597
39780
|
super.destroy();
|
|
39598
|
-
if (this._img) {
|
|
39599
|
-
this._img.parentNode.removeChild(this._img);
|
|
39600
|
-
this._img = null;
|
|
39601
|
-
}
|
|
39602
39781
|
}
|
|
39603
39782
|
}
|
|
39604
39783
|
|
|
39605
|
-
function cumulativeOffset(element) {
|
|
39606
|
-
let top = 0, left = 0;
|
|
39607
|
-
do {
|
|
39608
|
-
top += element.offsetTop || 0;
|
|
39609
|
-
left += element.offsetLeft || 0;
|
|
39610
|
-
element = element.offsetParent;
|
|
39611
|
-
} while (element);
|
|
39612
|
-
|
|
39613
|
-
return {
|
|
39614
|
-
top: top,
|
|
39615
|
-
left: left
|
|
39616
|
-
};
|
|
39617
|
-
}
|
|
39618
|
-
|
|
39619
39784
|
/**
|
|
39620
39785
|
* Default data access strategy for {@link GLTFLoaderPlugin}.
|
|
39621
39786
|
*
|