diff --git a/examples/Configs_disableDoublePrecisionAndRAF.html b/examples/Configs_disableDoublePrecisionAndRAF.html
new file mode 100644
index 0000000000..8aab23bc76
--- /dev/null
+++ b/examples/Configs_disableDoublePrecisionAndRAF.html
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+ xeokit Example
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/index.html b/examples/index.html
index ad7677a419..95dbad7532 100644
--- a/examples/index.html
+++ b/examples/index.html
@@ -679,6 +679,11 @@
// ["DimensionsFootprintModel_example2", "Dimensions footprint experiment #2"]
],
+ "Configs": [
+ "#Configuring the xeokit-sdk",
+ ["Configs_disableDoublePrecisionAndRAF", "Disable double precision (and RAF) for extra performance"]
+ ],
+
"Viewer": [
"#General viewer techniques",
["viewer_createDestroyRepeat", "Testing repeated viewer creation and deletion"],
diff --git a/src/viewer/Configs.js b/src/viewer/Configs.js
new file mode 100644
index 0000000000..538c773626
--- /dev/null
+++ b/src/viewer/Configs.js
@@ -0,0 +1,115 @@
+import {math} from "./scene/math/math.js";
+import {core} from "./scene/core";
+
+/**
+ * Manages global configurations for all {@link Viewer}s.
+ *
+ * ## Usage
+ *
+ * In the example below, we'll disable xeokit's double-precision support, which gives a performance and memory boost
+ * on low-power devices, but means that we can no longer render double-precision models without jittering.
+ *
+ * We'll also switch from window.requestAnimationFrame to window.setInterval for xeokit's animations, which can also give a
+ * performance boost in some cases.
+ *
+ * [[Run this example](http://xeokit.github.io/xeokit-sdk/examples/#Configs_disableDoublePrecisionAndRAF)]
+ *
+ * ````javascript
+ * import {Configs, Viewer, XKTLoaderPlugin} from "../dist/xeokit-sdk.min.es.js";
+ *
+ * // Access xeoit-sdk global configs.
+ * // We typically set configs only before we create any Viewers.
+ * const configs = new Configs();
+ *
+ * // Disable 64-bit precision for extra speed.
+ * // Only set this config once, before you create any Viewers.
+ * configs.doublePrecisionEnabled = false;
+ *
+ * // Disable window.requestAnimationFrame (RAF) and use
+ * // window.setInterval for Viewer render loops.
+ * // This config can be switched dynamically, if needed.
+ * configs.rafEnabled = false;
+ *
+ * const viewer = new Viewer({
+ * canvasId: "myCanvas"
+ * });
+ *
+ * viewer.camera.eye = [-3.933, 2.855, 27.018];
+ * viewer.camera.look = [4.400, 3.724, 8.899];
+ * viewer.camera.up = [-0.018, 0.999, 0.039];
+ *
+ * const xktLoader = new XKTLoaderPlugin(viewer);
+ *
+ * const model = xktLoader.load({
+ * src: "../assets/models/xkt/v8/ifc/Duplex.ifc.xkt"
+ * });
+ * ````
+ */
+class Configs {
+
+ /**
+ * Creates a Configs.
+ */
+ constructor() {
+
+ }
+
+ /**
+ * Sets whether double precision mode is enabled for {@link Viewer}s.
+ *
+ * When double precision mode is enabled (default), {@link Viewer}s will accurately render models that contain
+ * double-precision coordinates, without jittering.
+ *
+ * Internally, double precision incurs extra performance and memory overhead, so if we're certain that
+ * we're not going to render models that rely on double-precision coordinates, then it's a good idea to disable
+ * it, especially on low-power devices.
+ *
+ * This should only be set once, before creating any {@link Viewer}s.
+ *
+ * @returns {boolean}
+ */
+ set doublePrecisionEnabled(doublePrecision) {
+ math.setDoublePrecisionEnabled(doublePrecision);
+ }
+
+ /**
+ * Gets whether double precision mode is enabled for all {@link Viewer}s.
+ *
+ * @returns {boolean}
+ */
+ get doublePrecisionEnabled() {
+ return math.getDoublePrecisionEnabled();
+ }
+
+
+
+ /**
+ * Sets whether Viewers currently use window.requestAnimationFrame (RAF) or window.setInterval for animations.
+ *
+ * With RAF, the render loop is suspended whenever we switch away from the browser tab that
+ * contains our application. With setInterval, the render loop will continue running. Since a {@link Viewer} only
+ * renders frames when the view has actually updated, disabling RAF can actually give a performance boost.
+ *
+ * This is ````true```` by default, to use RAF.
+ *
+ * This can be dynamically set at any time.
+ *
+ * @returns {boolean}
+ */
+ set rafEnabled(rafEnabled) {
+ core.setRAFEnabled(rafEnabled);
+ }
+
+ /**
+ * Gets whether {@link Viewer}s currently use window.requestAnimationFrame (RAF) or window.setInterval for animations.
+ *
+ * @returns {boolean}
+ */
+ get rafEnabled() {
+ return core.getRAFEnabled();
+ }
+
+
+}
+
+export {Configs};
\ No newline at end of file
diff --git a/src/viewer/index.js b/src/viewer/index.js
index eb0e5dad6d..c3d8373006 100644
--- a/src/viewer/index.js
+++ b/src/viewer/index.js
@@ -1,4 +1,5 @@
export * from "./localization/LocaleService.js";
export * from "./scene/index.js";
export * from "./Plugin.js";
-export * from "./Viewer.js";
\ No newline at end of file
+export * from "./Viewer.js";
+export * from "./Configs.js";
\ No newline at end of file
diff --git a/src/viewer/scene/core.js b/src/viewer/scene/core.js
index 7cde72a842..e5b6b1800d 100644
--- a/src/viewer/scene/core.js
+++ b/src/viewer/scene/core.js
@@ -3,6 +3,9 @@ import {Map} from './utils/Map.js';
import {stats} from './stats.js';
import {utils} from './utils.js';
+let rafEnabled = true;
+let interval = null;
+
const scenesRenderInfo = {}; // Used for throttling FPS for each Scene
const sceneIDMap = new Map(); // Ensures unique scene IDs
const taskQueue = new Queue(); // Task queue, which is pumped on each frame; tasks are pushed to it with calls to xeokit.schedule
@@ -11,7 +14,6 @@ const taskBudget = 10; // Millisecs we're allowed to spend on tasks in each fram
const fpsSamples = [];
const numFPSSamples = 30;
-let defaultScene = null;// Default singleton Scene, lazy-initialized in getter
let lastTime = 0;
let elapsedTime;
let totalFPS = 0;
@@ -71,6 +73,32 @@ function Core() {
});
};
+ /**
+ * @private
+ */
+ this.setRAFEnabled = function(value) {
+ if (value === rafEnabled) {
+ return;
+ }
+ rafEnabled = value;
+ if (rafEnabled) {
+ if (interval !== null) {
+ clearInterval(interval);
+ interval = null;
+ }
+ window.requestAnimationFrame(frame);
+ } else {
+ interval = setInterval(frame, 16);
+ }
+ };
+
+ /**
+ * @private
+ */
+ this.getRAFEnabled = function() {
+ return rafEnabled;
+ }
+
/**
* @private
*/
@@ -153,7 +181,9 @@ const frame = function () {
fireTickEvents(time);
renderScenes();
lastTime = time;
- window.requestAnimationFrame(frame);
+ if (rafEnabled) {
+ window.requestAnimationFrame(frame);
+ }
};
function runTasks(time) { // Process as many enqueued tasks as we can within the per-frame task budget
@@ -229,6 +259,10 @@ function renderScenes() {
}
}
-window.requestAnimationFrame(frame);
+if (rafEnabled) {
+ window.requestAnimationFrame(frame);
+} else {
+ interval = setInterval(frame, 16);
+}
export {core};
\ No newline at end of file
diff --git a/src/viewer/scene/math/math.js b/src/viewer/scene/math/math.js
index d194d53b76..350ef4510d 100644
--- a/src/viewer/scene/math/math.js
+++ b/src/viewer/scene/math/math.js
@@ -1,7 +1,7 @@
// Some temporary vars to help avoid garbage collection
-const doublePrecision = true;
-const FloatArrayType = doublePrecision ? Float64Array : Float32Array;
+let doublePrecision = true;
+let FloatArrayType = doublePrecision ? Float64Array : Float32Array;
const tempMat1 = new FloatArrayType(16);
const tempMat2 = new FloatArrayType(16);
@@ -13,6 +13,15 @@ const tempVec4 = new FloatArrayType(4);
*/
const math = {
+ setDoublePrecisionEnabled(enable) {
+ doublePrecision = enable;
+ FloatArrayType = doublePrecision ? Float64Array : Float32Array;
+ },
+
+ getDoublePrecisionEnabled() {
+ return doublePrecision;
+ },
+
MIN_DOUBLE: -Number.MAX_SAFE_INTEGER,
MAX_DOUBLE: Number.MAX_SAFE_INTEGER,