Skip to content

Instantly share code, notes, and snippets.

@yiskang
Last active April 1, 2024 08:37
Show Gist options
  • Save yiskang/cedbe270765fdb33925a914c383e2346 to your computer and use it in GitHub Desktop.
Save yiskang/cedbe270765fdb33925a914c383e2346 to your computer and use it in GitHub Desktop.
Sample: Show Revit rooms from master view with a general Revit 3D view by model aggregation (Loading Multiple Models).
<html>
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=no" />
<meta charset="utf-8">
<link rel="stylesheet" href="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.88.*/style.min.css"
type="text/css">
<script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.88.*/viewer3D.min.js"></script>
<style>
body {
margin: 0;
}
#forgeViewer {
width: 100%;
height: 100%;
margin: 0;
background-color: #F0F8FF;
}
</style>
</head>
<body>
<div id="forgeViewer"></div>
<script>
function fetchForgeToken(callback) {
fetch('http://localhost/api/oauth/token', {
method: 'get',
headers: new Headers({ 'Content-Type': 'application/json' })
})
.then((response) => {
if (response.status === 200) {
return response.json();
} else {
return Promise.reject(
new Error(`Failed to fetch token from server (status: ${response.status}, message: ${response.statusText})`)
);
}
})
.then((data) => {
if (!data) return Promise.reject(new Error('Empty token response'));
callback(data.access_token, data.expires_in);
})
.catch((error) => console.error(error));
}
async function loadMainViewAsync(viewer, urn, viewableId) {
return new Promise((resolve, reject) => {
async function onDocumentLoadSuccess(doc) {
await doc.downloadAecModelData();
let viewable = (viewableId ? doc.getRoot().findByGuid(viewableId) : doc.getRoot().getDefaultGeometry());
let model = await viewer.loadDocumentNode(doc, viewable, { loadAsHidden: false });
await viewer.waitForLoadDone();
resolve(model);
}
function onDocumentLoadFailure() {
reject(new Error('Failed fetching Forge manifest'));
}
Autodesk.Viewing.Document.load(urn, onDocumentLoadSuccess, onDocumentLoadFailure);
});
}
async function getRoomDbIdsAsync(model, roomCategoryName = 'Revit Rooms') {
return new Promise((resolve, reject) => {
model.search(
`${roomCategoryName}`,
(dbIds) => resolve(dbIds),
(error) => reject(error),
['Category'],
{ searchHidden: true }
);
});
};
async function getBulkPropertiesAsync(model, dbIds) {
return new Promise((resolve, reject) => {
model.getBulkProperties2(
dbIds,
{
ignoreHidden: false,
propFilter: ['viewable_in', 'externalId'],
needsExternalId: true,
},
(result) => resolve(result),
(error) => reject(error),
);
});
}
async function getRoomViewableInfoAsync(model) {
const doc = model.getDocumentNode().getDocument();
let roomDbIds = await getRoomDbIdsAsync(model);
if (roomDbIds.length <= 0)
roomDbIds = await getRoomDbIdsAsync(model, 'Revit Ambientes');
let result = await getBulkPropertiesAsync(model, roomDbIds);
let roomInfoMap = {};
result.forEach(r => {
let roomDbId = r.dbId;
let viewableIds = r.properties.map(prop => prop.displayValue);
for (let i = 0; i < viewableIds.length; i++) {
const viewableId = viewableIds[i];
const bubble = doc.getRoot().findByGuid(viewableId);
if (bubble.is2D())
continue;
if (roomInfoMap[viewableId]) {
roomInfoMap[viewableId].dbIds.push(roomDbId);
} else {
roomInfoMap[viewableId] = {
bubble,
dbIds: [roomDbId]
};
}
}
});
return roomInfoMap;
}
async function loadRoomsAsync(viewer, mainModel) {
const doc = mainModel.getDocumentNode().getDocument();
let roomInfo = await getRoomViewableInfoAsync(mainModel);
if (!roomInfo) return Promise.resolve();
let data = Object.values(roomInfo);
for (let i = 0; i < data.length; i++) {
await viewer.loadDocumentNode(
doc,
data[i].bubble,
{
ids: data[i].dbIds,
modelNameOverride: `Room Phase \`${data[i].bubble.name()}\``,
keepCurrentModels: true,
globalOffset: new THREE.Vector3(),//mainModel.getGlobalOffset(),
placementTransform: mainModel.getModelToViewerTransform()
}
);
await viewer.waitForLoadDone();
}
return Promise.resolve();
}
const options = {
env: 'AutodeskProduction',
getAccessToken: fetchForgeToken
};
Autodesk.Viewing.Initializer(options, async function () {
const config3d = {
modelBrowserStartCollapsed: true,
modelBrowserExcludeRoot: false,
};
let viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer'), config3d);
let startedCode = viewer.start();
if (startedCode > 0) {
console.error('Failed to create a Viewer: WebGL not supported.');
return;
}
const profileSettings = Autodesk.Viewing.ProfileSettings.clone(Autodesk.Viewing.ProfileSettings.AEC);
profileSettings.settings.bimWalkToolPopup = false;
const profile = new Autodesk.Viewing.Profile(profileSettings);
viewer.setProfile(profile);
let documentId = 'urn:dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6c2FuZG94L3JhY19iYXNpY19zYW1wbGVfcHJvamVjdC5ydnQ';
let mainModel = await loadMainViewAsync(viewer, documentId);
await loadRoomsAsync(viewer, mainModel);
viewer.showAll();
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment