我正在尝试根据BCF文件的BIM主题 - 审视数据正确初始化Autodesk Forge 3D查看器。
我已将3D模型(IFC)上传到Autodesk API,已处理过,我可以使用Autodesk Forge 3D Viewer可视化/导航该模型。
我在Nemetschek solibri中使用了相同的3D模型(IFC)来创建一个主题并使用BIM BCF 2.1标准(请参阅https://github.com/buildingsmart/bcf-xml)。
xml-data来自Visualization Info:
<PerspectiveCamera>
<CameraViewPoint>
<X>2.803843040759871</X>
<Y>14.568845808384443</Y>
<Z>0.8249055320631105</Z>
</CameraViewPoint>
<CameraDirection>
<X>0.4898262677194313</X>
<Y>-0.8652456579090667</Y>
<Z>0.1068652371988122</Z>
</CameraDirection>
<CameraUpVector>
<X>-0.05264688190667085</X>
<Y>0.09299722978166312</Y>
<Z>0.9942735142195238</Z>
</CameraUpVector>
<FieldOfView>60.0</FieldOfView>
</PerspectiveCamera>
我尝试在Autodesk Forge 3D查看器上设置相同的相机/视图:
viewer.restoreState(JSON.parse(`{
"viewport": {
"eye": [2.803843040759871, 14.568845808384443, 0.8249055320631105],
"target": [0.4898262677194313, -0.8652456579090667, 0.1068652371988122],
"up": [-0.05264688190667085, 0.09299722978166312, 0.9942735142195238],
"projection": "perspective",
"isOrthographic": false,
"fieldOfView": 60.0
}
}`));
结果:伪造的3D查看器视图,该视图与solibri中所看到的不匹配,也不匹配一个在BCF文件中保存为快照png的镜头。
也许yibri和autodesk-processed-ifc模型中的IFC模型具有不同的坐标系统,或者可能是什么?
CameraDirection
值不是Forge Viewer的目标参数。您必须使用以下公式自己进行计算。
{Target} = {CameraViewPoint} + {CameraDirection} * {CurrentFocalLength}
您的问题视图的完整相机映射将是:
var lengthScale = 1000; //! Use viwer.model.getUnitString(), the model I loaded is in `mm`, and BCF camera definition is in `m`
// or var lengthScale = Autodesk.Viewing.Private.convertUnits('m', viewer.model.getUnitString(), 1, 1);
var eye = new THREE.Vector3( 2.803843040759871 * lengthScale, 14.568845808384443 * lengthScale, 0.8249055320631105 * lengthScale );
var sightVec = new THREE.Vector3( 0.4898262677194313, -0.8652456579090667, 0.1068652371988122 ).multiplyScalar( viewer.navigation.getFocalLength() );
var target = eye.clone().add( sightVec )
var up = new THREE.Vector3( -0.05264688190667085, 0.09299722978166312, 0.9942735142195238 );
//Since Forge Viewer will apply a global offset to the whole model
//var offsetMatrix = viewer.model.getData().placementWithOffset;
var offsetMatrix = viewer.model.getModelToViewerTransform();
var offsetEye = eye.applyMatrix4(offsetMatrix);
var offsetTarget = target.applyMatrix4(offsetMatrix);
var fov = 60; //!<< from BCF
var cameraView = {
aspect: viewer.getCamera().aspect,
isPerspective: true,
fov: fov,
position: offsetEye,
target: offsetTarget,
up: up,
orthoScale: 1
};
viwer.impl.setViewFromCamera( cameraView );
附录将查看器摄像机转换回BCF viewpoint
let scale = Autodesk.Viewing.Private.convertUnits(viewer.model.getUnitString(), 'm', 1, 1);
let invOffsetMatrix = viewer.model.getInverseModelToViewerTransform();
let eye = viewer.navigation.getPosition().clone();
let sightDir = viewer.navigation.getEyeVector().clone().normalize();
let upVec = viewer.navigation.getCameraUpVector().clone();
let offsetEye = eye.applyMatrix4(invOffsetMatrix).multiplyScalar(scale);
let fov = viewer.navigation.getCamera().fov;
let bcfDoc = document.implementation.createDocument('', '', null);
let bcfDocPI = bcfDoc.createProcessingInstruction('xml', 'version="1.0" encoding="UTF-8"');
bcfDoc.insertBefore(bcfDocPI, bcfDoc.firstChild);
let visualizationInfoElem = bcfDoc.createElement('VisualizationInfo');
bcfDoc.appendChild(visualizationInfoElem);
let perspectiveCameraElem = bcfDoc.createElement('PerspectiveCamera');
visualizationInfoElem.appendChild(perspectiveCameraElem);
let cameraViewPointElem = bcfDoc.createElement('CameraViewPoint');
perspectiveCameraElem.appendChild(cameraViewPointElem);
let cameraViewPointXElem = bcfDoc.createElement('X');
cameraViewPointXElem.textContent = offsetEye.x.toFixed(14);
cameraViewPointElem.appendChild(cameraViewPointXElem);
let cameraViewPointYElem = bcfDoc.createElement('Y');
cameraViewPointYElem.textContent = offsetEye.y.toFixed(14);
cameraViewPointElem.appendChild(cameraViewPointYElem);
let cameraViewPointZElem = bcfDoc.createElement('Z');
cameraViewPointZElem.textContent = offsetEye.z.toFixed(14);
cameraViewPointElem.appendChild(cameraViewPointZElem);
let cameraDirectionElem = bcfDoc.createElement('CameraDirection');
perspectiveCameraElem.appendChild(cameraDirectionElem);
let cameraDirectionXElem = bcfDoc.createElement('X');
cameraDirectionXElem.textContent = sightDir.x.toFixed(14);
cameraDirectionElem.appendChild(cameraDirectionXElem);
let cameraDirectionYElem = bcfDoc.createElement('Y');
cameraDirectionYElem.textContent = sightDir.y.toFixed(14);
cameraDirectionElem.appendChild(cameraDirectionYElem);
let cameraDirectionZElem = bcfDoc.createElement('Z');
cameraDirectionZElem.textContent = sightDir.z.toFixed(14);
cameraDirectionElem.appendChild(cameraDirectionZElem);
let cameraUpVectorElem = bcfDoc.createElement('CameraUpVector');
perspectiveCameraElem.appendChild(cameraUpVectorElem);
let cameraUpVectorXElem = bcfDoc.createElement('X');
cameraUpVectorXElem.textContent = upVec.x.toFixed(14);
cameraUpVectorElem.appendChild(cameraUpVectorXElem);
let cameraUpVectorYElem = bcfDoc.createElement('Y');
cameraUpVectorYElem.textContent = upVec.y.toFixed(14);
cameraUpVectorElem.appendChild(cameraUpVectorYElem);
let cameraUpVectorZElem = bcfDoc.createElement('Z');
cameraUpVectorZElem.textContent = upVec.z.toFixed(14);
cameraUpVectorElem.appendChild(cameraUpVectorZElem);
let fieldOfViewElem = bcfDoc.createElement('FieldOfView');
perspectiveCameraElem.appendChild(fieldOfViewElem);
fieldOfViewElem.textContent = fov.toFixed(14);
let bcfVpConents = new XMLSerializer().serializeToString(bcfDoc);
享受它!