three.js - 选择对象,获取对象材质

时间:2016-07-20 04:43:27

标签: javascript three.js

我正在尝试使用three.js可视化汽车的3D模型,我有几个问题(我的代码如下):

1) 3d模型在Maya 2016中制作,然后导出为.obj和.mtl文件。我希望汽车的部件可以选择(我的意思是当你选择它时,它会以绿色突出显示,当你再次点击所选部分时,它会恢复正常颜色。 我已经做到了,但问题是光线投射选择光线路径中的所有物体,我的意思是当我选择门时,它背后的一切都被选中,我只想选择门。

2) 第二个问题是渲染器没有为透明材料可视化。窗户和头灯。我已经看到一些可以显示透明材料的3D汽车可视化器。

3) 第三个问题可以追溯到第一个问题。当我选择一个部件时,我想存储它以前的材料颜色(在应用高亮颜色之前),所以当我取消选择它时,它可以恢复正常颜色,我已经把汽车油漆的颜色,这是错的,因为当我取消选择窗户时,它们会变红。

所以,这是我的index.html代码:

<code><html>
    <head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=0.1">

    <script src="JavaScript/three.js"></script>
    <script src="JavaScript/Detector.js"></script>
    <script src="JavaScript/OrbitControls.js"></script>
    <script src="JavaScript/OBJLoader.js"></script>
    <script src="JavaScript/MTLLoader.js"></script>
    <script src="JavaScript/Projector.js"></script>

    <link rel="stylesheet" type="text/css" href="css/site.css">

    </head>
    <body>

    <div class="left">
        <p>Low-Poly Croupière<p>
        <p><a href="https://manu.ninja/" target="_top">manu.ninja</a></p>
    </div>

        <div id="test" class="left" hidden="true">
         <p>xaxaxaxaxaaxaaxx<p>
         </div>

    <a class="right" href="https://github.com/Lorti/webgl-3d-model-viewer-using-three.js" target="_top">
        <img src="https://camo.githubusercontent.com/652c5b9acfaddf3a9c326fa6bde407b87f7be0f4/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67">
    </a>
<script>

        if (!Detector.webgl) {
            Detector.addGetWebGLMessage();
        }

        var container;

        var camera, controls, scene, renderer;
        var lighting, ambient, keyLight, fillLight, backLight;

        var windowHalfX = window.innerWidth / 2;
        var windowHalfY = window.innerHeight / 2;
        var objects = [];

        init();
        animate();

        function init() {

            container = document.createElement('div');
            document.body.appendChild(container);
            document.addEventListener( 'mousedown', onDocumentMouseDown, false );


            /* Camera */

            camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
            camera.position.z = 140;

            /* Scene */

            scene = new THREE.Scene();
            lighting = true;

            ambient = new THREE.AmbientLight(0xefefff, 1.0);
            scene.add(ambient);

            keyLight = new THREE.DirectionalLight(new THREE.Color('hsl(60, 100%, 75%)'), 3.0);
            keyLight.position.set(-100, 0, 100);

            fillLight = new THREE.DirectionalLight(new THREE.Color('hsl(540, 100%, 75%)'), 1.75);
            fillLight.position.set(100, 0, 100);

            backLight = new THREE.DirectionalLight(0xe3ffef, 1.0);
            backLight.position.set(100, 0, -100).normalize();

            /* Model */

            var mtlLoader = new THREE.MTLLoader();
            mtlLoader.setBaseUrl('assets/');
            mtlLoader.setPath('assets/');
            mtlLoader.load('e46_red_5.mtl', function (materials) {

                materials.preload();

                //materials.materials.default.map.magFilter = THREE.NearestFilter;
               // materials.materials.default.map.minFilter = THREE.LinearFilter;

                var objLoader = new THREE.OBJLoader();
                objLoader.setMaterials(materials);
                objLoader.setPath('assets/');
                objLoader.load('e46_red_5.obj', function (object) {



                    scene.add(object);
                    objects.push(object);

                });

            });

            /* Renderer */

            renderer = new THREE.WebGLRenderer();
            renderer.setPixelRatio(window.devicePixelRatio);
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.setClearColor(new THREE.Color("hsl(0, 0%, 10%)"));

            container.appendChild(renderer.domElement);

            /* Controls */

            controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.enableDamping = true;
            controls.dampingFactor = 0.25;
            controls.enableZoom = false;

            /* Events */

            window.addEventListener('resize', onWindowResize, false);
            window.addEventListener('keydown', onKeyboardEvent, false);
            //window.addEventListener( 'mousemove', onMouseMove, false );

        }

        function onWindowResize() {

            windowHalfX = window.innerWidth / 2;
            windowHalfY = window.innerHeight / 2;

            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();

            renderer.setSize(window.innerWidth, window.innerHeight);

        }

        function onKeyboardEvent(e) {

            if (e.code === 'KeyL') {

                lighting = !lighting;

                if (lighting) {

                    ambient.intensity = 0.25;
                    scene.add(keyLight);
                    scene.add(fillLight);
                    scene.add(backLight);

                } else {

                    ambient.intensity = 1.0;
                    scene.remove(keyLight);
                    scene.remove(fillLight);
                    scene.remove(backLight);

                }

            }

        }

        function animate() {

            requestAnimationFrame(animate);

            controls.update();

            render();

        }

        function render() {

            renderer.render(scene, camera);

        }

    var already_selected = false;

        function onDocumentMouseDown( event ) {
   event.preventDefault();

            var projector = new THREE.Projector();
            mouseVector = new THREE.Vector3();
            mouseVector.x = 2 * (event.clientX / window.innerWidth) - 1;
            mouseVector.y = 1 - 2 * ( event.clientY / window.innerHeight );

            //var mouse3D = new THREE.Vector3( ( event.clientX / window.innerWidth ) * 2 - 1,   
            //                        -( event.clientY / window.innerHeight ) * 2 + 1,  
            //                        0.5 );     
            //var raycaster = projector.pickingRay( mouseVector.clone(), camera );
            var raycaster =  new THREE.Raycaster();                                        
           raycaster.setFromCamera( mouseVector, camera );

            var intersects = raycaster.intersectObjects( objects[0].children );
console.log(intersects)
            if ( intersects.length > 0 ) {
                var door = document.getElementById("test");
                door.hidden =false;
                for (var i = 0; i < intersects.length; i++) {

    //intersects[i].object.material.color.setHex( Math.random() * 0xffffff );


    //var currentColor = new THREE.Color(intersects[i].object.material.color);
    var currentColor = +'0x' + intersects[i].object.material.color.getHex().toString( 16 );

    if (already_selected == true) {
        intersects[i].object.material.color.setHex( 0x380000 );
        //intersects[i].object.material.color.setHex( currentColor );
        already_selected = false;
    }
    else {
    intersects[i].object.material.color.setHex( 0xccffcc );
    already_selected = true;
    }
}

            }
  }

    </script>

    </body>
</html></code>

1 个答案:

答案 0 :(得分:2)

1)对于raycaster问题,在intersects数组中,您只想访问intersects[0],因为这是光线投影相交的第一个对象。如果您不想选择第一个项目背后的项目,我不会看到整个阵列的重点

2)为了看透明度,你必须设置
(object here).material.transparent = true;
我必须这样做,以便在您点击它们时查看对象,但我还必须设置不透明度。假设您的对象已经分配了不透明度,那么它只需要透明度标志,否则您也可以设置
(object here).material.opacity = some number;

3)当我想突出显示&#39;一个材料是我实际改变intersects[0].object.material.emissive.set('#(insert color)'); 然后,当鼠标移动对象时,您将自发光重置为#000000。 自发光是更好的,因为你实际上并没有改变颜色,只是外观。