将动态加载的模型移动到查看器中

Posted

技术标签:

【中文标题】将动态加载的模型移动到查看器中【英文标题】:Moving dynamically loaded model into viewer 【发布时间】:2021-05-21 03:36:07 【问题描述】:

我正在尝试在 Forge 查看器中移动动态加载的模型,但出现以下错误:

未捕获的类型错误:secondModel.getPlacementTransform 不是函数

我正在努力实现:

    通过单击左侧窗格中的缩略图动态加载模型。 通过选择单个模型并在查看器中移动它来移动它。

当用户从右侧点击任何缩略图时,它会使用下面的代码添加到查看器中(在图片点击时调用此函数launchViewer(urn))。

var viewer;
var ModelArray = [];

function launchViewer(urn) 
    var options = 
        env: 'AutodeskProduction',
        getAccessToken: getForgeToken
    ;
    Autodesk.Viewing.Initializer(options, () => 

        if (viewer == undefined) 
            viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer'));
            viewer.start();
        
        var documentId = 'urn:' + urn;

        Autodesk.Viewing.Document.load(documentId, (doc) => 

            var viewables = doc.getRoot().getDefaultGeometry();
            let tr = new THREE.Matrix4();
            tr.set(0, 0, .005, 0, .005, 0, 0, 0, 0, .005, 0, 0, 0, 0, 0, 1);
            viewer.loadDocumentNode(doc, viewables, 
                placementTransform: (new THREE.Matrix4()).setPosition( x: 60, y: 0, z: 0 ),
                keepCurrentModels: true,
                globalOffset:  x: 0, y: 0, z: 0 
            ).then(function (model1) 
                ModelArray.push(model1);
            );
            document.onmousemove = event => 
                if (!event.ctrlKey)
                    return;
                var secondModel = ModelArray[1].getModelId();
                let res = viewer.impl.hitTest(event.clientX, event.clientY, true, null, [ModelArray[0].getModelId()]);
                let pt = null;

                if (res) 
                    pt = res.intersectPoint;
                 else 
                    pt = viewer.impl.intersectGround(event.clientX, event.clientY);
                

                let tr = secondModel.getPlacementTransform();
                tr.elements[12] = pt.x;
                tr.elements[13] = pt.y;
                tr.elements[14] = pt.z + extraZ;
                secondModel.setPlacementTransform(tr);
                viewer.impl.invalidate(true, true, true);
            
        );
    );

function onDocumentLoadFailure(viewerErrorCode) 
    console.error('onDocumentLoadFailure() - errorCode:' + viewerErrorCode);

function getForgeToken(callback) 
    fetch('http://localhost:59045/api/forge/oauth/token').then(res => 
        res.json().then(data => 
            callback(data.access_token, data.expires_in);
        );
    );

我在下一行遇到错误。

 let tr = secondModel.getPlacementTransform();

参考这篇文章 https://forge.autodesk.com/blog/dynamic-model-placement

【问题讨论】:

我没有使用过 autodesk-viewer 或 webgl 或相关的 javascript 框架,但 var secondModel = ModelArray[1].getModelId() 这一行表明 secondModel 只是一个 id,不是吗?好吧,一个 id,但名称令人困惑,因为它似乎是一个模型(按其名称)。顺便说一句,我们是人类,我们会阅读所有字面上有意义的内容(通过文字),因此命名对于避免愚蠢的错误非常重要。 @KingKing 感谢您指出错误 :) 实际上它是一个模型,所以它不应该是 var secondModel = ModelArray[1].getModelId() 而应该是 var secondModel = ModelArray[1] 那现在可以正常工作了吗? @AdamNagy 我稍微修改了它,它现在可以工作了。我将其作为答案,但我可以通过鼠标选择移动吗?还有什么链接可以告诉我模型的定位吗? 开始拖动时,首先可以使用 hitTest() 找出鼠标下的模型,然后可以根据鼠标移动开始更改模型的placementTransform。 【参考方案1】:

添加每个模型的解决方案如下所示,我为该模型显示了一个按钮,当您单击该模型时,该模型被选中并且工作正常。以下是我在查看器中添加的三个模型。

上面的代码如下

var viewer;
var ModelArray = [];
var selectedModel;
function ChangeModel(totalModels) 
    selectedModel = ModelArray[totalModels - 1];

function launchViewer(urn) 
    var options = 
        env: 'AutodeskProduction',
        getAccessToken: getForgeToken
    ;
    Autodesk.Viewing.Initializer(options, () => 
        if (viewer == undefined) 
            viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer'));
            viewer.start();
        
        var documentId = 'urn:' + urn;

        Autodesk.Viewing.Document.load(documentId, (doc) => 

            var viewables = doc.getRoot().getDefaultGeometry();
            let tr = new THREE.Matrix4();
            tr.set(0, 0, .005, 0, .005, 0, 0, 0, 0, .005, 0, 0, 0, 0, 0, 1);
            viewer.loadDocumentNode(doc, viewables, 
                // placementTransform: (new THREE.Matrix4()).setPosition( x: 60, y: 0, z: 0 ),
                keepCurrentModels: true,
                globalOffset:  x: 0, y: 0, z: 0 
            ).then(function (model) 
                //   console.log("Model1: " + model1)
                ModelArray.push(model);
                var totalModel = ModelArray.length;
                if (totalModel == 1)
                    selectedModel = ModelArray[0];
                var cssClass = "cursor: pointer; color: #fff; background-color: #007bff; border-color: #007bff; margin: 10px;";
                $("#modelList").append("<button type='button' class='btn btn - primary' onclick=\"ChangeModel('" + totalModel + "')\" value='" + totalModel + "' onclick='ChangeModel()' style ='" + cssClass + "'>Model " + totalModel + "</button>");
            );
       

            document.onmousemove = event => 
                if (!event.ctrlKey)
                    return;
                let bb = selectedModel.getBoundingBox();
                var extraZ = bb.max.z;
                let res = viewer.impl.hitTest(event.clientX, event.clientY, true, null, [selectedModel.getModelId()]);
                let pt = null;

                if (res) 
                    pt = res.intersectPoint;
                 else 
                    pt = viewer.impl.intersectGround(event.clientX, event.clientY);
                

                let tr = selectedModel.getPlacementTransform();
                tr.elements[12] = pt.x;
                tr.elements[13] = pt.y;
                tr.elements[14] = pt.z + extraZ;
                selectedModel.setPlacementTransform(tr);
                viewer.impl.invalidate(true, true, true);
            
            document.onkeydown = event => 
                if (!event.shiftKey)
                    return;

                if (event.code === "ArrowRight") 
                    let tr = selectedModel.getPlacementTransform();
                    tr.elements[12] += 1;
                    selectedModel.setPlacementTransform(tr);
                

                if (event.code === "ArrowLeft") 
                    let tr = selectedModel.getPlacementTransform();
                    tr.elements[12] -= 1;
                    selectedModel.setPlacementTransform(tr);
                
            ;

        );
        // Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
        //this.viewer.addEventListener(Autodesk.Viewing.AGGREGATE_SELECTION_CHANGED_EVENT, this.onSelectionBinded);
    );

function onDocumentLoadFailure(viewerErrorCode) 
    console.error('onDocumentLoadFailure() - errorCode:' + viewerErrorCode);


function getForgeToken(callback) 
    fetch('http://localhost:59045/api/forge/oauth/token').then(res => 
        res.json().then(data => 
            callback(data.access_token, data.expires_in);
        );
    );

【讨论】:

以上是关于将动态加载的模型移动到查看器中的主要内容,如果未能解决你的问题,请参考以下文章

将模型加载到 2D/3D 查看器中 - Autodesk Forge

vue.js 一次只能将一个动态数据对象加载到组件中

从云cms动态加载移动应用程序本地化资源

azure devops vsts 扩展动态上下文菜单,子菜单未正确加载

无法将短裤复制到动态数组 C++

如何在模块化的 java 11 应用程序中动态加载 Libreoffice jar,而不从自定义类加载器中获取 ClassCastException