Skip to content

Commit

Permalink
Merge pull request #348 from xeokit/concurrent-xkt-loading
Browse files Browse the repository at this point in the history
Concurrent model loading
  • Loading branch information
xeolabs authored Jun 15, 2020
2 parents 0481c4c + b9b69e2 commit 9c743e4
Show file tree
Hide file tree
Showing 5 changed files with 263 additions and 122 deletions.
3 changes: 2 additions & 1 deletion examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ <h1><a href="http://xeokit.io">xeokit</a> / Examples</h1>
"loading_XKT_dataSource",
"loading_XKT_GearboxPropellorTurbine",
"loading_XKT_APHS",
"loading_XKT_concurrently",

"#Loading models from 3DXML",
"loading_3DXML_Widget",
Expand Down Expand Up @@ -443,4 +444,4 @@ <h1><a href="http://xeokit.io">xeokit</a> / Examples</h1>
</script>

</body>
</html>
</html>
171 changes: 171 additions & 0 deletions examples/loading_XKT_concurrently.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>XKTLoaderPlugin - Loading Seven BIM Models Concurrently from the File System</title>
<link href="css/styles.css" type="text/css" rel="stylesheet"/>

<style>
#myCanvas {
width: 100%;
height: 100%;
background: lightBlue;
}

#myNavCubeCanvas {
position: absolute;
width: 250px;
height: 250px;
bottom: 50px;
right: 10px;
z-index: 200000;
}
</style>

</head>

<body>

<canvas id="myCanvas"></canvas>

<canvas id="myNavCubeCanvas"></canvas>

<div id="info">
<h1>XKTLoaderPlugin - Loading Seven BIM Models Concurrently from the File System</h1><br>
<ul>
<li>
<div id="time">Loading JavaScript modules...</div>
</li>
<li>
Architectural, Structure, Electrical, Fire Alarms, Sprinklers, Plumbing and Mechanical models are from the
Autodesk <a target="_other"
href="http://openifcmodel.cs.auckland.ac.nz/Model/Details/305">West
RiverSide
Hospital</a> example
</li>
<li>
<a target="_other"
href="./../docs/class/src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js~XKTLoaderPlugin.html">XKTLoaderPlugin</a>
docs
</li>
<li>
<a target="_other" href="https://github.com/xeokit/xeokit-sdk/wiki/Importing-Models">User Guide</a>
</li>
</ul>
</div>
</body>
<script type="module">

//------------------------------------------------------------------------------------------------------------------
// Import the modules we need for this example
//------------------------------------------------------------------------------------------------------------------

import {Viewer} from "../src/viewer/Viewer.js";
import {XKTLoaderPlugin} from "../src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js";
import {NavCubePlugin} from "../src/plugins/NavCubePlugin/NavCubePlugin.js";

//------------------------------------------------------------------------------------------------------------------
// Create a Viewer and arrange camera
//------------------------------------------------------------------------------------------------------------------

const viewer = new Viewer({
canvasId: "myCanvas",
transparent: true
});

viewer.camera.eye = [110.27, 172.88, -6.49];
viewer.camera.look = [33.88, 177.99, -101.79];
viewer.camera.up = [0.02, 0.99, 0.03];

//------------------------------------------------------------------------------------------------------------------
// Create a NavCube
//------------------------------------------------------------------------------------------------------------------

new NavCubePlugin(viewer, {
canvasId: "myNavCubeCanvas",
visible: true,
size: 250,
alignment: "bottomRight",
bottomMargin: 100,
rightMargin: 10
});

//----------------------------------------------------------------------------------------------------------------------
// Load seven models and fit it to view
//----------------------------------------------------------------------------------------------------------------------

const xktLoader = new XKTLoaderPlugin(viewer);

var t0 = performance.now();
var numModels = 0;
var numModelsToLoad = 0;

document.getElementById("time").innerHTML = "Loading 7 models concurrently";

function load(params) {

numModels++;
numModelsToLoad++;

const model = xktLoader.load(params);

model.on("loaded", () => {
if (--numModelsToLoad <= 0) {
const t1 = performance.now();
document.getElementById("time").innerHTML = numModels + " models loaded in " + Math.floor(t1 - t0) / 1000.0 + " seconds<br>Objects: " + model.numEntities;
}
});
}

load({
id: "mechanical",
src: "./models/xkt/WestRiverSideHospital/mechanical.xkt",
metaModelSrc: "./metaModels/WestRiverSideHospital/mechanical.json",
edges: true
});

load({
id: "plumbing",
src: "./models/xkt/WestRiverSideHospital/plumbing.xkt",
metaModelSrc: "./metaModels/WestRiverSideHospital/plumbing.json",
edges: true
});

load({
id: "electrical",
src: "./models/xkt/WestRiverSideHospital/electrical.xkt",
metaModelSrc: "./metaModels/WestRiverSideHospital/electrical.json",
edges: true
});

load({
id: "fireAlarms",
src: "./models/xkt/WestRiverSideHospital/fireAlarms.xkt",
metaModelSrc: "./metaModels/WestRiverSideHospital/fireAlarms.json",
edges: true
});

load({
id: "sprinklers",
src: "./models/xkt/WestRiverSideHospital/sprinklers.xkt",
metaModelSrc: "./metaModels/WestRiverSideHospital/sprinklers.json",
edges: true
});

load({
id: "structure",
src: "./models/xkt/WestRiverSideHospital/structure.xkt",
metaModelSrc: "./metaModels/WestRiverSideHospital/structure.json",
edges: true,
Zxrayed: true
});

load({
id: "architectural",
src: "./models/xkt/WestRiverSideHospital/architectural.xkt",
metaModelSrc: "./metaModels/WestRiverSideHospital/architectural.json",
edges: true
});

</script>
</html>
11 changes: 0 additions & 11 deletions src/viewer/scene/PerformanceModel/PerformanceModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {buildEdgeIndices} from '../math/buildEdgeIndices.js';
import {WEBGL_INFO} from '../webglInfo.js';
import {PerformanceMesh} from './lib/PerformanceMesh.js';
import {PerformanceNode} from './lib/PerformanceNode.js';
import {getBatchingBuffer, putBatchingBuffer} from "./lib/batching/BatchingBuffer.js";
import {getBatchingLayerScratchMemory} from "./lib/batching/BatchingLayerScratchMemory.js";
import {BatchingLayer} from './lib/batching/BatchingLayer.js';
import {InstancingLayer} from './lib/instancing/InstancingLayer.js';
Expand Down Expand Up @@ -71,7 +70,6 @@ class PerformanceModel extends Component {

this._instancingLayers = {};
this._currentBatchingLayer = null;
this._batchingBuffer = getBatchingBuffer();
this._batchingScratchMemory = getBatchingLayerScratchMemory(this);

this._meshes = {};
Expand Down Expand Up @@ -528,7 +526,6 @@ class PerformanceModel extends Component {
// console.log("New batching layer");
this._currentBatchingLayer = new BatchingLayer(this, {
primitive: "triangles",
buffer: this._batchingBuffer,
scratchMemory: this._batchingScratchMemory,
positionsDecodeMatrix: cfg.positionsDecodeMatrix,
});
Expand Down Expand Up @@ -689,10 +686,6 @@ class PerformanceModel extends Component {
this._currentBatchingLayer.finalize();
this._currentBatchingLayer = null;
}
if (this._batchingBuffer) {
putBatchingBuffer(this._batchingBuffer);
this._batchingBuffer = null;
}
for (const geometryId in this._instancingLayers) {
if (this._instancingLayers.hasOwnProperty(geometryId)) {
this._instancingLayers[geometryId].finalize();
Expand Down Expand Up @@ -1510,10 +1503,6 @@ class PerformanceModel extends Component {
this._currentBatchingLayer.destroy();
this._currentBatchingLayer = null;
}
if (this._batchingBuffer) {
putBatchingBuffer(this._batchingBuffer);
this._batchingBuffer = null;
}
this.scene.camera.off(this._onCameraViewMatrix);
for (let i = 0, len = this._layerList.length; i < len; i++) {
this._layerList[i].destroy();
Expand Down
47 changes: 11 additions & 36 deletions src/viewer/scene/PerformanceModel/lib/batching/BatchingBuffer.js
Original file line number Diff line number Diff line change
@@ -1,51 +1,26 @@
import {WEBGL_INFO} from "../../../webglInfo.js";

const bigIndicesSupported = WEBGL_INFO.SUPPORTED_EXTENSIONS["OES_element_index_uint"];
const SLICING = true;
const MAX_VERTS = SLICING ? (bigIndicesSupported ? 5000000 : 65530) : 5000000;
const MAX_VERTS = bigIndicesSupported ? 5000000 : 65530;
const MAX_INDICES = MAX_VERTS * 3; // Rough rule-of-thumb

/**
* @private
*/
class BatchingBuffer {
constructor() {
this.slicing = SLICING;
this.maxVerts = MAX_VERTS;
this.maxIndices = MAX_INDICES;
this.positions = new Float32Array(MAX_VERTS * 3); // Uncompressed
this.colors = new Uint8Array(MAX_VERTS * 4); // Compressed
this.quantizedPositions = new Uint16Array(MAX_VERTS * 3); // Compressed
this.normals = new Int8Array(MAX_VERTS * 3); // Compressed
this.pickColors = new Uint8Array(MAX_VERTS * 4); // Compressed
this.flags = new Uint8Array(MAX_VERTS * 4);
this.flags2 = new Uint8Array(MAX_VERTS * 4);
this.indices = bigIndicesSupported ? new Uint32Array(MAX_INDICES) : new Uint16Array(MAX_INDICES);
this.edgeIndices = bigIndicesSupported ? new Uint32Array(MAX_INDICES) : new Uint16Array(MAX_INDICES);
this.lenPositions = 0;
this.lenColors = 0;
this.lenNormals = 0;
this.lenPickColors = 0;
this.lenFlags = 0;
this.lenIndices = 0;
this.lenEdgeIndices = 0;
this.positions = []; // Uncompressed
this.colors = []; // Compressed
this.quantizedPositions = []; // Compressed
this.normals = []; // Compressed
this.pickColors = []; // Compressed
this.flags = [];
this.flags2 = [];
this.indices = [];
this.edgeIndices = [];
}
}

const freeBuffers = [];

/**
* @private
*/
function getBatchingBuffer() {
return freeBuffers.length > 0 ? freeBuffers.pop() : new BatchingBuffer();
}

/**
* @private
*/
function putBatchingBuffer(buffer) {
freeBuffers.push(buffer);
}

export {getBatchingBuffer, putBatchingBuffer};
export {BatchingBuffer};
Loading

0 comments on commit 9c743e4

Please sign in to comment.