资讯专栏INFORMATION COLUMN

在 Revit 里重现 Forge Viewer相机的状态

刘福 / 2023人阅读

摘要:最近,我收到一个客户的需求,希望可以把的相机状态通过还原到里。因为没有直接的方法可以修改相机的值。的相机视角比的相机视角宽。调用以取得焦距。因此,裁剪区域的范围计算为宽度视图的相机焦距。高度常规相机片幅的比例。

最近,我收到一个客户的需求,希望可以把Viewer的相机状态通过Revit API还原到Revit里。所以我们来看看要如何实现这个要求。在开始之前,你要先知道一些有关于Revit相机的事情:

Revit预设的相机FOV值大约为50度,焦距为38.6mm,片幅尺寸为36mm。

Revit默认的渲染图片尺寸为6英吋。

为了调整Revit相机的FOV值,我们必须利用修改3D视图的裁剪尺寸来完成。因为Revit API没有直接的方法可以修改相机的FOV值。

Viewer的相机视角比Revit的相机视角宽。

注意:上述关于Revit的相机参数皆为我反复测试得出,Revit没有确切的值,即皆为近似值。

好的,我们转换过程的总思路如下(注意:接下来的步骤适用透视相机模式):

Forge Viewer的部分:

从当前视图的 Viewer 相机获取焦距,目标,位置和上向量。

调用 Viewer3D#getFocalLength 以取得焦距。

调用 Viewer3D#getState({ viewport: true }) 以取得当前视图必要的相机状态,例如:

{
  "viewport": {
    "name": "",
    "eye": [
      -14.870469093323,
      36.571562767029,
      -1.2129259109497
    ],
    "target": [
      -14.770469665527,
      36.571967124939,
      -1.2129259109497
    ],
    "up": [
      0,
      0,
      1
    ],
    "worldUpVector": [
      0,
      0,
      1
    ],
    "pivotPoint": [
      -14.770469665527,
      36.571967124939,
      -1.2129259109497
    ],
    "distanceToOrbit": 0.10000024532334,
    "aspectRatio": 3.1789297658863,
    "projection": "perspective",
    "isOrthographic": false,
    "fieldOfView": 90.68087674208
  }
}

获取当前加载模型的 global offset(注意:Viewer 默认使用 global offset 来调整加载模型的位置,以避免浮点运算精度和 z-buffer fighting的问题):

调用 viewer.model.getData().globalOffset取得global offset的值,例如:

{
  "x": -0.253891,
  "y": -45.556179,
  "z": 6.134186
}

从Viewer相机的目标和位置减去 globalOffset:

const state = viewer.getState({ viewport: true });
const globalOffset = viewer.model.getData().globalOffset

const currentTarget = new THREE.Vector3().fromArray( state.viewport.target );
// {x: -14.770469665527344, y: 36.571967124938965, z: -1.212925910949707}

const currentPosition = new THREE.Vector3().fromArray( state.viewport.eye );
// {x: -14.870469093322754, y: 36.57156276702881, z: -1.212925910949707}

const originTarget = currentTarget.clone().add( globalOffset );
// {x: -15.02436066552734, y: -8.984211875061035, z: 4.921260089050291}

const originPosition = currentPosition.clone().add( globalOffset );
// {x: -15.12436009332275, y: -8.984616232971192, z: 4.921260089050291}

Revit的部分:

在这个部分,我们将利用Revit中的裁剪区域和3D透视图来完成我们的目标。

使用Viewer的相机状态计算Revit 3D视图方向并创建透视3D视图:

// From Forge Viewer

//const currentTarget = new THREE.Vector3().fromArray( state.viewport.target );
// {x: -14.770469665527344, y: 36.571967124938965, z: -1.212925910949707}

//const currentPosition = new THREE.Vector3().fromArray( state.viewport.eye );
// {x: -14.870469093322754, y: 36.57156276702881, z: -1.212925910949707}

//const originTarget = currentTarget.clone().add( globalOffset );
// {x: -15.02436066552734, y: -8.984211875061035, z: 4.921260089050291}

//const originPosition = currentPosition.clone().add( globalOffset );
// {x: -15.12436009332275, y: -8.984616232971192, z: 4.921260089050291}

//const up = new THREE.Vector3().fromArray( state.viewport.up );
// {x: 0, y: 0, z: 1}

using(var trans = new Transaction(this.Document, "Map LMV Camera"))
{
    try
    {
            if(trans.Start() == TransactionStatus.Started)
            {
                IEnumerable viewFamilyTypes = from elem in new FilteredElementCollector(this.Document).OfClass(typeof(ViewFamilyType))
                                    let type = elem as ViewFamilyType
                                    where type.ViewFamily == ViewFamily.ThreeDimensional
                                    select type;
            
                // Create a new Perspective View3D
                View3D view3D = View3D.CreatePerspective(this.Document, viewFamilyTypes.First().Id);
                Random rnd = new Random();
               view3D.Name = string.Format("Camera{0}", rnd.Next()) ;
               // By default, the 3D view uses a default orientation.
               // Change the orientation by creating and setting a ViewOrientation3D 
               var position = new XYZ(-15.12436009332275, -8.984616232971192, 4.921260089050291);
               var up = new XYZ(0,0,1);
               var target = new XYZ(-15.02436066552734, -8.984211875061035, 4.921260089050291);
               var sightDir = target.Subtract( position ).Normalize();
            
               var orientation = new ViewOrientation3D( position, up, sightDir );
               view3D.SetOrientation( orientation );
        
               // turn off the far clip plane with standard parameter API
               Parameter farClip = view3D.LookupParameter("Far Clip Active");
               farClip.Set(0);
            
              Parameter cropRegionVisible = view3D.LookupParameter("Crop Region Visible");
              cropRegionVisible.Set(1);
            
              Parameter cropView = view3D.LookupParameter("Crop View");
              cropView.Set(1);
            
              trans.Commit();
            }    
    }
    catch(Exception ex)
    {
        trans.RollBack();
        TaskDialog.Show("Revit", ex.Message);
    }
}

上述程序代码的结果:

使用上述提到经过反复测试而来的相机参数来计算裁剪区域的范围:

Revit 相机预设的 FOV 值近似50度,焦距为38.6mm,片幅尺寸为36mm。

Revit 默认的渲染图片尺寸近似值为6吋。

因此,裁剪区域的范围计算为:

宽度:6" x 38.6 /视图的相机焦距。6" x 38.6 / 12 = 19.3" = 490.22 mm

高度:19.3" x 常规相机片幅的比例。19.3" x 2/3 = 12.87" = 326.898 mm

透过 Revit UI 设定 Revit 裁切区域并记住在裁剪区域的对话框中选择 Field of view:

这是最终结果:

此篇文章同步发布于 Forge 官方博客 https://forge.autodesk.com/bl...,希望有帮助!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105547.html

相关文章

  • Forge Viewer 显示 Revit 格子线 (grids)

    最近一些Forge客户都在询问我同一个的问题,他们希望将Revit的网格呈现在viewer中,藉此让我有机会来完成这件事,并将它记录在本文章里,就让我们开始吧! 在开始之前,有件事你必须先知道: 由于在Revit里格子线只能在2D视图(例如平面图、立面图、表单等等)中显示,并不会在3D视图中被看见。因此,我们也无法在ForgeViewer的3D视图中看到这些格子线,网格会在模型转文件时被忽略。据我...

    Yangyang 评论0 收藏0
  • 「翻译」Forge Viewer上实作简易模型版本比较

    摘要:现在让我们修改这个示例让他可以展示两个同项目但不同版号的模型及。示例执行结果如下这边是这个比较模型的括展代码英文原文 showImg(https://segmentfault.com/img/bVOmjp?w=1542&h=925); 熟悉 BIM360 Team 的朋友可能知道他有一个很牛的模型文档版本比较的功能,但如果模型是放在 Google 云盘或是百度云盘上有可能做到吗? Au...

    JowayYoung 评论0 收藏0
  • Forge Viewer 切换模型视图(Viewables)

    摘要:有提供类似的功能,但这并不包含在里头。条列清单或是切换视图是非常容易的,你主要是要建立一个使用者介面让使用者去选取他们想观看的内容。我使用了来确保当前载入模型占用的内存可以都被释出。 此篇文章原作是 Autodesk ADN Philippe Leefsma,以下以我简称。 这有一个简易的博客用来说明一个我刚加入 https://forge-rcdb.autodesk.io 的一个新功...

    BlackHole1 评论0 收藏0
  • 「翻译」使用 Autodesk.Viewing.MarkupsCore 括展

    摘要:让我们来体验的功能。在来我们就可以将刚刚取得的和传送到自己的服务器上,同时储存到数据库里面。将来要回复的话,就可以先从数据库获取和,并透过下面的方法来回复开启涂丫工具回复先前制作涂丫时的画面的状态在图层上重现涂丫原文 让我们来体验 Viewer v2.16 Autodesk.Viewing.MarkupsCore 的功能。首先要先确保你使用的 viewer 版号是正确的: 你知道...

    alighters 评论0 收藏0
  • Forge Viewer 展示/隐藏构件材质

    摘要:对于大多数的模型文档都可以透过服务提取转换在里渲染构件外观时所需的材质及贴图。所以我们可以透过它遍历所有材质,找出我们想隐藏贴图的那些材质,将它的颜色设置为灰色,同时也可以透过它将隐藏贴图的材质回复。 这篇文章来自 Autodesk ADN 的梁晓冬,以下以我简称。 对于大多数的模型文档都可以透过 Autodesk Forge Model Derivative 服务提取、转换在 Vie...

    Dean 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<