如何在Autodesk Forge Viewer中无需重复加载模型实现多视角展示?
基于Autodesk Forge Viewer实现多视角同模型展示(低内存方案)
不要初始化两个独立Viewer实例——这会重复加载模型资源,直接导致内存占用翻倍,大模型场景下极易触发WebGL上下文崩溃。正确的做法是利用Viewer的多视口渲染能力,共享同一模型数据,仅为不同视角创建独立的相机和渲染画布。
核心思路
单个Viewer实例加载模型后,创建额外的Canvas作为副视角的渲染目标,为每个副视角配置独立相机(比如透视主视角/正交顶视角),然后在Viewer的渲染循环中手动触发副视角的渲染逻辑,全程共享模型的几何数据、纹理、材质等资源,内存占用仅为单个Viewer的1.2-1.5倍左右。
实现步骤
- 初始化主Viewer并加载目标模型
- 创建副视角的Canvas元素,设置好尺寸与样式
- 为副视角创建独立相机(例如正交顶视相机),根据模型包围盒配置相机参数
- 监听Viewer的
AGGREGATE_END事件,在主视图渲染完成后,手动渲染副视角
代码示例
// 初始化主Viewer const mainViewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('main-viewer')); mainViewer.start(); Autodesk.Viewing.Document.load( 'urn:dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6bXktZnJvZ290L215LW1vZGVsLmR3Zg==', (doc) => { const viewables = doc.getRoot().getDefaultGeometry(); mainViewer.loadDocumentNode(doc, viewables).then(() => { // 模型加载完成后初始化副视角 initTopOrthographicView(mainViewer); }); }, (err) => console.error('模型加载失败:', err) ); // 初始化正交顶视副视角 function initTopOrthographicView(mainViewer) { const secondaryCanvas = document.getElementById('secondary-viewer'); const secondaryCamera = new THREE.OrthographicCamera(); // 根据模型包围盒配置正交相机参数 const modelBounds = mainViewer.model.getBoundingBox(); const size = modelBounds.getSize(new THREE.Vector3()); const aspectRatio = secondaryCanvas.clientWidth / secondaryCanvas.clientHeight; secondaryCamera.left = -size.x * 0.5; secondaryCamera.right = size.x * 0.5; secondaryCamera.top = size.y * 0.5 * aspectRatio; secondaryCamera.bottom = -size.y * 0.5 * aspectRatio; secondaryCamera.near = modelBounds.min.z - 100; secondaryCamera.far = modelBounds.max.z + 100; secondaryCamera.updateProjectionMatrix(); // 设置相机为顶视视角 secondaryCamera.position.set(modelBounds.center.x, modelBounds.center.y, modelBounds.max.z + 50); secondaryCamera.lookAt(modelBounds.center); // 监听主视图渲染完成事件,同步渲染副视角 mainViewer.addEventListener(Autodesk.Viewing.AGGREGATE_END, () => { const renderer = mainViewer.impl.renderer; // 保存主视图WebGL状态 renderer.saveState(); // 配置副视口参数并渲染 renderer.setViewport(0, 0, secondaryCanvas.clientWidth, secondaryCanvas.clientHeight); renderer.setScissor(0, 0, secondaryCanvas.clientWidth, secondaryCanvas.clientHeight); renderer.setScissorTest(true); renderer.setClearColor(0xf0f0f0); renderer.clear(); mainViewer.impl.scene.setRenderCamera(secondaryCamera); renderer.render(mainViewer.impl.scene, secondaryCamera); // 恢复主视图状态 renderer.restoreState(); mainViewer.impl.scene.setRenderCamera(mainViewer.impl.camera); }); }
注意事项
- 副视角的Canvas必须复用主Viewer的WebGL上下文,避免创建额外上下文导致内存浪费
- 若需要为副视角添加交互(平移、缩放),需单独实现相机控制逻辑,不要干扰主Viewer的相机状态
- 大模型场景下,可限制副视角的渲染分辨率,或在窗口 resize 时同步更新相机参数与视口尺寸
内容的提问来源于stack exchange,提问作者Björn Wahle
相关产品推荐
相关产品推荐

