Skip to content

Instantly share code, notes, and snippets.

@AlexanderMelde
Last active June 14, 2024 13:14
Show Gist options
  • Save AlexanderMelde/b61cbeeb139acbb870362eac15a568da to your computer and use it in GitHub Desktop.
Save AlexanderMelde/b61cbeeb139acbb870362eac15a568da to your computer and use it in GitHub Desktop.
xeokit glb viewer
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>xeokit BIM Viewer</title>
<link rel="stylesheet" href="./lib/fontawesome-free-5.11.2-web/css/all.min.css" type="text/css" />
<link rel="stylesheet" href="../dist/xeokit-bim-viewer.css" type="text/css" />
<link rel="stylesheet" href="./css/style.css" />
</head>
<body>
<input type="checkbox" id="explorer_toggle" />
<label for="explorer_toggle" class="xeokit-i18n explorer_toggle_label xeokit-btn fas fa-2x fa-sitemap"
data-xeokit-i18ntip="toolbar.toggleExplorer" data-tippy-content="Toggle explorer"></label>
<input type="checkbox" id="inspector_toggle" />
<label id="inspector_toggle_label" for="inspector_toggle"
class="xeokit-i18n inspector_toggle_label xeokit-btn fas fa-info-circle fa-2x"
data-xeokit-i18ntip="toolbar.toggleProperties" data-tippy-content="Toggle properties"></label>
<div id="myExplorer"></div>
<div id="myToolbar"></div>
<div id="myInspector"></div>
<div id="myViewer">
<canvas id="myCanvas"></canvas>
<canvas id="myNavCubeCanvas"></canvas>
</div>
</body>
<!-- Tooltips libraries -->
<script src="./lib/popper.js"></script>
<script src="./lib/tippy.js"></script>
<script type="module">
import { Server, BIMViewer, LocaleService } from "../dist/xeokit-bim-viewer.es.js";
import { Viewer, GLTFLoaderPlugin} from "../node_modules/@xeokit/xeokit-sdk/dist/xeokit-sdk.es.js";
import { messages as localeMessages } from "../dist/messages.js";
window.onload = function () {
const requestParams = getRequestParams();
const locale = requestParams.locale || "en";
const projectId = requestParams.projectId;
if (!projectId) {
return;
}
const openExplorer = requestParams.openExplorer;
setExplorerOpen(openExplorer === "true");
const enableEditModels = (requestParams.enableEditModels === "true");
const server = new Server({
dataDir: requestParams.dataDir || "./data"
});
function loadGlbOrGltf(src, viewer) {
viewer.camera.eye = [0,0,0];
viewer.camera.look = [1391.46, 0.89, -244.24];
viewer.camera.up = [-0.41, 0.81, 0.40];
const gltfLoader = new GLTFLoaderPlugin(viewer);
const model = gltfLoader.load({
src: src,
edges: false
});
console.log("--------------------------------------------------------------");
console.log(model.params);
console.log("--------------------------------------------------------------");
}
const bimViewer = new BIMViewer(server, {
localeService: new LocaleService({
messages: localeMessages,
locale: locale
}),
enableMeasurements: true,
canvasElement: document.getElementById("myCanvas"), // WebGL canvas
keyboardEventsElement: document, // Optional, defaults to document
explorerElement: document.getElementById("myExplorer"), // Left panel
toolbarElement: document.getElementById("myToolbar"), // Toolbar
inspectorElement: document.getElementById("myInspector"), // Right panel
navCubeCanvasElement: document.getElementById("myNavCubeCanvas"),
busyModelBackdropElement: document.getElementById("myViewer"),
enableEditModels: enableEditModels
});
bimViewer.localeService.on("updated", () => {
const localizedElements = document.querySelectorAll('.xeokit-i18n');
localizedElements.forEach((localizedElement) => {
if (localizedElement.dataset.xeokitI18n) {
localizedElement.innerText = bimViewer.localeService.translate(localizedElement.dataset.xeokitI18n);
}
if (localizedElement.dataset.xeokitI18ntip) {
const translation = bimViewer.localeService.translate(localizedElement.dataset.xeokitI18ntip);
if (translation) {
localizedElement.dataset.tippyContent = bimViewer.localeService.translate(localizedElement.dataset.xeokitI18ntip);
}
}
if (localizedElement.dataset.tippyContent) {
if (localizedElement._tippy) {
localizedElement._tippy.setContent(localizedElement.dataset.tippyContent);
} else {
tippy(localizedElement, {
appendTo: "parent",
zIndex: 1000000,
allowHTML: true
});
}
}
});
});
bimViewer.setConfigs({
"showSpaces": false, // Default
"selectedGlowThrough": true,
"highlightGlowThrough": true,
"dtxEnabled": true // Enable data texture scene representation for models - may be slow on low-spec GPUs
});
bimViewer.on("openExplorer", () => {
setExplorerOpen(true);
});
bimViewer.on("openInspector", () => {
setInspectorOpen(true);
});
bimViewer.on("addModel", (event) => { // "Add" selected in Models tab's context menu
console.log("addModel: " + JSON.stringify(event, null, "\t"));
});
bimViewer.on("editModel", (event) => { // "Edit" selected in Models tab's context menu
console.log("editModel: " + JSON.stringify(event, null, "\t"));
});
bimViewer.on("deleteModel", (event) => { // "Delete" selected in Models tab's context menu
console.log("deleteModel: " + JSON.stringify(event, null, "\t"));
});
const viewerConfigs = requestParams.configs;
if (viewerConfigs) {
const configNameVals = viewerConfigs.split(",");
for (let i = 0, len = configNameVals.length; i < len; i++) {
const configNameValStr = configNameVals[i];
const configNameVal = configNameValStr.split(":");
const configName = configNameVal[0];
const configVal = configNameVal[1];
bimViewer.setConfig(configName, configVal);
}
}
loadGlbOrGltf('/mypath/test1.glb', bimViewer.viewer);
bimViewer.loadProject(projectId, () => {
console.log("Project loaded: " + projectId);
/*const modelId = requestParams.modelId;
console.log("Model ID: " + modelId);
if (modelId) {
bimViewer.loadModel(modelId);
}
const tab = requestParams.tab;
if (tab) {
bimViewer.openTab(tab);
}*/
watchHashParams();
},
(errorMsg) => {
console.error(errorMsg);
});
function watchHashParams() {
let lastHash = "";
window.setInterval(() => {
const currentHash = window.location.hash;
if (currentHash !== lastHash) {
parseHashParams();
lastHash = currentHash;
}
}, 400);
}
function parseHashParams() {
const params = getHashParams();
const actionsStr = params.actions;
if (!actionsStr) {
return;
}
const actions = actionsStr.split(",");
if (actions.length === 0) {
return;
}
for (let i = 0, len = actions.length; i < len; i++) {
const action = actions[i];
switch (action) {
case "focusObject":
const objectId = params.objectId;
if (!objectId) {
console.error("Param expected for `focusObject` action: 'objectId'");
break;
}
bimViewer.setAllObjectsSelected(false);
bimViewer.setObjectsSelected([objectId], true);
bimViewer.flyToObject(objectId, () => {
// FIXME: Showing objects in tabs involves scrolling the HTML within the tabs - disable until we know how to scroll the correct DOM element. Otherwise, that function works OK
// bimViewer.showObjectInObjectsTab(objectId);
// bimViewer.showObjectInClassesTab(objectId);
// bimViewer.showObjectInStoreysTab(objectId);
});
break;
case "focusObjects":
const objectIds = params.objectIds;
if (!objectIds) {
console.error("Param expected for `focusObjects` action: 'objectIds'");
break;
}
const objectIdArray = objectIds.split(",");
bimViewer.setAllObjectsSelected(false);
bimViewer.setObjectsSelected(objectIdArray, true);
bimViewer.viewFitObjects(objectIdArray, () => {
});
break;
case "clearFocusObjects":
bimViewer.setAllObjectsSelected(false);
bimViewer.viewFitAll();
// TODO: view fit nothing?
break;
case "openTab":
const tabId = params.tabId;
if (!tabId) {
console.error("Param expected for `openTab` action: 'tabId'");
break;
}
bimViewer.openTab(tabId);
break;
default:
console.error("Action not supported: '" + action + "'");
break;
}
}
}
function setExplorerOpen(explorerOpen) {
const toggle = document.getElementById("explorer_toggle");
if (toggle) {
toggle.checked = explorerOpen;
}
}
function setInspectorOpen(inspectorOpen) {
const toggle = document.getElementById("inspector_toggle");
if (toggle) {
toggle.checked = inspectorOpen;
}
}
function getRequestParams() {
const vars = {};
window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, (m, key, value) => {
vars[key] = value;
});
return vars;
}
function getHashParams() {
const hashParams = {};
let e;
const a = /\+/g; // Regex for replacing addition symbol with a space
const r = /([^&;=]+)=?([^&;]*)/g;
const d = function (s) {
return decodeURIComponent(s.replace(a, " "));
};
const q = window.location.hash.substring(1);
while (e = r.exec(q)) {
hashParams[d(e[1])] = d(e[2]);
}
return hashParams;
}
window.bimViewer = bimViewer;
}
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment