在Autodesk Forge Viewer中的元素下进行拾取 [英] Picking under elements of an element in Autodesk Forge viewer

查看:161
本文介绍了在Autodesk Forge Viewer中的元素下进行拾取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想完成一个功能,该功能可以在Three.js中实现,但不能在Autodesk Forge Viewer中实现.这是要测试的链接: http://app.netonapp.com/JavaScript/Three.js/select_inner_objects.html

I would like to accomplish a feature that I can do in Three.js but cannot in Autodesk Forge viewer. Here is the link to test: http://app.netonapp.com/JavaScript/Three.js/select_inner_objects.html

要求是在对象内部选择对象.可以在上面的演示中使用THREE.Raycaster来完成此工作,以使用光线投射器来检测光线穿过的所有元素.然后我可以将物体放在另一个物体的后面或内部.

The requirement is to select objects inside an object. This job can be done with THREE.Raycaster in the above demo, to use a raycaster to detect all elements which are on the line the ray going through. Then I can get objects behind or inner another object.

我在Autodesk Forge Viewer中尝试了此概念,但没有成功.这是代码:

I tried this concept in Autodesk Forge viewer but having no success. Here is the code:

// Change this to:
// true to use original Three.js
// false to use Autodesk Forge Viewer API
var useThreeJS = true;

var container = $('div.canvas-wrap')[0];

container.addEventListener('mousedown', function (event) {
    if (useThreeJS) {
        var canvas = _viewer.impl.canvas;
        var containerWidth = canvas.clientWidth;
        var containerHeight = canvas.clientHeight;

        var camera = _viewer.getCamera();

        var mouse = mouse || new THREE.Vector3();
        var raycaster = raycaster || new THREE.Raycaster();

        mouse.x = 2 * (event.clientX / containerWidth) - 1;
        mouse.y = 1 - 2 * (event.clientY / containerHeight);
        mouse.unproject(camera);

        raycaster.set(camera.position, mouse.sub(camera.position).normalize());
        var intersects = raycaster.intersectObjects(objects);

        if (intersects.length == 1) {
            var obj = intersects[0].object;
            obj.material.color.setRGB(1.0 - i / intersects.length, 0, 0);
        } else if (intersects.length > 1) {
            // Exclude the first which is the outer object (i == 0)
            for (var i = 1; i < intersects.length; i++) {
                var obj = intersects[i].object;
                obj.material.color.setRGB(1.0 - i / intersects.length, 0, 0);
            }
        }
    } else {
        var vp = _viewer.impl.clientToViewport(event.canvasX, event.canvasY);
        var renderer = _viewer.impl.renderer();

        var dbId = renderer.idAtPixel(vp.x, vp.y);
        if (dbId) {
            console.debug("Selected Id: " + dbId);
            _viewer.select(dbId);
            _viewer.impl.invalidate(true);
        }
    }
}, false);

我发现Forge查看器具有viewer.impl.renderer().idAtPixel方法,对于在拾取像素处获取元素非常有用.但是,我希望它做得更多,以选择拾取像素处的所有元素(在下面或嵌套在其中).如何使用Forge Viewer API?

I found the Forge viewer has viewer.impl.renderer().idAtPixel method which is great to get an element at the picking pixel. However, I want it to do more, to select all elements (which are under or nested) at the picking pixel. How I can do it with the Forge Viewer API?

推荐答案

基于Zhong Wu在另一个

Based on the suggestion of Zhong Wu in another post, here is the final solution to select element which is under or inside another element. I created an Autodesk Forge viewer extension to use it easily.

///////////////////////////////////////////////////////////////////////////////
// InnerSelection viewer extension
// by Khoa Ho, December 2016
//
///////////////////////////////////////////////////////////////////////////////
AutodeskNamespace("Autodesk.ADN.Viewing.Extension");

Autodesk.ADN.Viewing.Extension.InnerSelection = function (viewer, options) {

    Autodesk.Viewing.Extension.call(this, viewer, options);

    var _self = this;

    var _container = viewer.canvas.parentElement;
    var _renderer = viewer.impl.renderer();
    var _instanceTree = viewer.model.getData().instanceTree;
    var _fragmentList = viewer.model.getFragmentList();
    var _eventSelectionChanged = false;
    var _viewport;
    var _outerDbId;

    _self.load = function () {

        _container.addEventListener('mousedown',
            onMouseDown);

        viewer.addEventListener(
            Autodesk.Viewing.SELECTION_CHANGED_EVENT,
            onItemSelected);

        console.log('Autodesk.ADN.Viewing.Extension.InnerSelection loaded');

        return true;
    };

    _self.unload = function () {

        _container.removeEventListener('mousedown',
            onMouseDown);

        viewer.removeEventListener(
            Autodesk.Viewing.SELECTION_CHANGED_EVENT,
            onItemSelected);

        console.log('Autodesk.ADN.Viewing.Extension.InnerSelection unloaded');

        return true;
    };

    function onMouseDown(e) {

        var viewport = viewer.impl.clientToViewport(e.canvasX, e.canvasY);
        _viewport = viewport; // Keep this viewport to use in onItemSelected()

        var dbId = _renderer.idAtPixel(viewport.x, viewport.y);

        if (_outerDbId == dbId) {
            _outerDbId = -1;

            // Deselect everything
            viewer.select();
        } else {
            _outerDbId = dbId;

            // Hide outer element temporarily to allow picking its behind element
            viewer.hideById(dbId);

            _eventSelectionChanged = true;
        }

        viewer.impl.sceneUpdated(true);
    }

    function onItemSelected(e) {

        if (_eventSelectionChanged) {

            // Prevent self looping on selection
            _eventSelectionChanged = false;

            // Show outer element back
            viewer.show(_outerDbId);

            // Get inner element Id after the outer element
            // was just hidden on mouse down event
            var innerDbId = _renderer.idAtPixel(_viewport.x, _viewport.y);

            if (innerDbId > -1) {
                // Select the inner element when it is found
                viewer.select(innerDbId);

                console.debug("Selected inner Id: " + innerDbId);

            } else if (_outerDbId > -1) {
                // Select the outer element if the inner element is not found
                viewer.select(_outerDbId);

                console.debug("Selected outer Id: " + _outerDbId);

            }
        }
    }

};

Autodesk.ADN.Viewing.Extension.InnerSelection.prototype =
    Object.create(Autodesk.Viewing.Extension.prototype);

Autodesk.ADN.Viewing.Extension.InnerSelection.prototype.constructor =
    Autodesk.ADN.Viewing.Extension.InnerSelection;

Autodesk.Viewing.theExtensionManager.registerExtension(
    'Autodesk.ADN.Viewing.Extension.InnerSelection',
    Autodesk.ADN.Viewing.Extension.InnerSelection);

这篇关于在Autodesk Forge Viewer中的元素下进行拾取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆