物体网格与渲染图像的方向相反

问题描述

我正在尝试使用Three.JS重新创建Flash网站,但是尝试创建某些功能时遇到了麻烦。

应该发生的是,我想让一些按钮图像围绕屏幕中心旋转。如果将鼠标悬停在它们上方,然后单击以打开网站上的其他位置,则应该能够将其停止。

我一切正常,直到鼠标悬停在按钮上时要求按钮停止。我试图使用光线投射来实现这一点,但是当我在场景中移动鼠标时,似乎网格与渲染的纹理不在同一位置。实际上,似乎网格物体和渲染的图像的旋转方向彼此相反。

这是我的代码,我将您链接到我的网站上的一个页面,在此页面上我将测试此改进,以便您可以找到真实的示例:

<!DOCTYPE html>
<html>
<head>
    <Meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Untitled Document</title>
    <style type="text/css">
        body { margin: 0;}
        canvas { display: block;}
    </style>        
</head>

<body>
    <script>
        //var THREE = new THREE();
        var renderer,scene,camera,nucleus;
        
        var width = window.innerWidth;
        var height = window.innerHeight;
        var fov = 60;
        var near = 1;
        var far = 10000;
        var min = 0;
        var max = 10;
        var insObjSpeed = 0;
        
        var buttons = [];
        var numOfBtns = 1;
        
        var projector,mouse = { x: 0,y: 0 },INTERSECTED;
        
        //var mouse;
        
        function populateScene(){
            var geom = new THREE.CircleGeometry(3,50);
            var matTx = new THREE.TextureLoader().load('imgs/buttons/logo.png');
            var mat = new THREE.MeshBasicMaterial({map:matTx});
            nucleus = new THREE.Mesh(geom,mat);
            nucleus.position.set(0,0);
            scene.add(nucleus);
            
            var btn = null;
            var btnMat = null;
            var plane = new THREE.Plane();
            var point = new THREE.Vector3();
            
            var btnMats = [new THREE.TextureLoader().load('imgs/buttons/georo.png'),new THREE.TextureLoader().load('imgs/buttons/wiki.png'),new THREE.TextureLoader().load('imgs/buttons/port.png'),new THREE.TextureLoader().load('imgs/buttons/yt.png'),new THREE.TextureLoader().load('imgs/buttons/l2r.png'),new THREE.TextureLoader().load('imgs/buttons/ci.png'),new THREE.TextureLoader().load('imgs/buttons/ov.png'),new THREE.TextureLoader().load('imgs/buttons/ttv.png'),new THREE.TextureLoader().load('imgs/buttons/tw.png'),new THREE.TextureLoader().load('imgs/buttons/ffs.png')];
                           
            var usedMats = [];
                            
            for (var i1 = 0; i1 < numOfBtns; i1++){
                var matIdx = Math.floor(Math.random() * (max - min + 1)) + min;
                var matTx = btnMats[matIdx];
                
                if (usedMats.includes(matTx)){
                    while (usedMats.includes(matTx)){
                        matIdx = Math.floor(Math.random() * (max - min + 1)) + min;
                        matTx = btnMats[matIdx];
                    }
                }
                
                usedMats.push(matTx);
                //var matTx = new THREE.TextureLoader().load('imgs/buttons/georo.png')
                var geom2 = new THREE.CircleGeometry(3,50);         
                var mat = new THREE.MeshBasicMaterial({map:matTx});
                btn = new THREE.Mesh(geom2,mat);                   
                btn.angle = new THREE.Vector3(Math.random(),Math.random(),Math.random()).normalize();
                btn.orbitSpeed = 0.0045; //Math.random() * 0.05) * 0.5;
                
                
                plane.normal.copy(btn.angle);
                point.set(Math.random(),Math.random());
                plane.projectPoint(point,btn.position);
                
                if (Math.random() > 0.5) { btn.orbitSpeed *= -1; }
                btn.position.setLength(Math.floor(Math.random() * 20) + 15);
                btn.position.applyAxisAngle(btn.angle,Math.random() / 10);
                btn.position.add(nucleus.position);

                buttons.push(btn);      
                scene.add(btn);             
            }
        }
            
        function updateBtns() {
            var obj = null;
            
            for (var i1 = 0; i1 < numOfBtns; i1++){
                obj = buttons[i1];
                
                obj.position.sub(nucleus.position);
                obj.position.applyAxisAngle(obj.angle,obj.orbitSpeed);
                obj.position.add(nucleus.position);
                
                //if (i1 == 0){ console.log(obj.position); }
            }
        }
            
        function init() {
            document.body.style.backgroundColor = "#333333";
            
            renderer = new THREE.Webglrenderer({
                antialias: true,alpha: true
            });
            
            mouse = new THREE.Vector2();
            
            renderer.shadowMap.enabled = true;
            renderer.shadowMap.type = THREE.PCFSoftShadowMap;
            
            document.body.appendChild(renderer.domElement);
            document.body.style.overflow = "hidden";
            document.body.style.margin = "0";
            document.body.style.padding = "0";
            
            scene = new THREE.Scene();
            camera = new THREE.PerspectiveCamera(fov,width/height,near,far);
            camera.position.z = 100;
            scene.add(camera);
            
            //controls = new THREE.trackballControls(camera,renderer.domElement);
            document.addEventListener( 'mousemove',onDocumentMouseMove,false );
            projector = new THREE.Projector();
            
            resize();
            window.onresize = resize;
            populateScene();
            animate();
        }
        
        function onDocumentMouseMove( event ) 
        {
            // the following line would stop any other event handler from firing
            // (such as the mouse's trackballControls)
            event.preventDefault();
            
            // update the mouse variable
            mouse.x = ( event.clientX / renderer.domElement.clientWidth) * 2 - 1;
            mouse.y = -( event.clientY / renderer.domElement.clientHeight) * 2 + 1;
            
            console.log("mouse pos: " + mouse.x + "," + mouse.y);
            
        }
            
        function resize(){
            width = window.innerWidth;
            height = window.innerHeight;
            
            if (renderer && camera){
                renderer.setSize(width,height);
                camera.aspect = width / height;
                camera.updateProjectionMatrix();    
            }
        }
            
        function render(){
            renderer.render(scene,camera); 
        }
        
        function animate(){             
            checkMouse();
            requestAnimationFrame(animate);
            updateBtns();
            render();
            //checkMouseHover();
            
        }
        
        function checkMouse(){
            var vector = new THREE.Vector3( mouse.x,mouse.y,1 );
            console.log("ray vec: " + vector.x + "," + vector.y);
            projector.unprojectVector( vector,camera );
            var ray = new THREE.Raycaster( camera.position,vector.sub( camera.position ).normalize() );
        
            // create an array containing all objects in the scene with which the ray intersects
            var intersects = ray.intersectObjects( scene.children,true );
        
            // INTERSECTED = the object in the scene currently closest to the camera 
            //      and intersected by the Ray projected from the mouse position    
            
            // if there is one (or more) intersections
            if ( intersects.length > 0 ) {
                // if the closest object intersected is not the currently stored intersection object
                if ( intersects[ 0 ].object != INTERSECTED && intersects[0].object !== nucleus) {
                    // restore prevIoUs intersection object (if it exists) to its original color
                    if ( INTERSECTED ) {
                        console.log("Intersection detected at: " + intersects[0].point);
                        INTERSECTED = intersects[0].object;
                        INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
                        // store reference to closest object as current intersection object
                        
                        // store color of closest object (for later restoration)
                        INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
                        // set a new color for closest object
                        INTERSECTED.material.color.setHex( 0xffff00 );
                    }
                }
            } 
            else { // there are no intersections
                // restore prevIoUs intersection object (if it exists) to its original color
                if ( INTERSECTED ) { INTERSECTED.material.color.setHex( INTERSECTED.currentHex ); }
                // remove prevIoUs intersection object reference
                //     by setting current intersection object to "nothing"
                INTERSECTED = null; 
            }
        }
        
        function onMouSEOver(ev){
            insObjSpeed = ev.object.orbitSpeed;
            //ev.object.orbitSpeed = 0.0;
        }
        
        function onMouSEOut(ev) { ev.object.orbitSpeed = insObjSpeed; }         
        function THREEReady() { init(); }           
        function onMouseMove(event){
            mouse.x = (event.clientX/width)*2-1;    
            mouse.y = (event.clientY/height)*2-1;
        }
        
        (function() {
            window.addEventListener('mousemove',onMouseMove,false);
            
            function addScript(url,callback){
                callback = callback || function() {};
                
                var script = document.createElement("script");
                
                script.addEventListener("load",callback);
                script.setAttribute("src",url);
                document.head.appendChild(script);  
            }
            
            addScript("./js/ThreeJS_0.119.1.js",function() {
                addScript("./js/ThreeJS_0.119.1_Projector.js",function(){
                THREEReady();
            })});
        })();
    </script>
</body>

Live Demo

解决方法

对于初学者来说,您的mouseMove()在进行y值计算之前缺少负号。这意味着您的y值会被翻转(应为-1时为+1),应如下所示:

mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

第二,我不确定为什么只使用现有的mouse Vector2作为outlined in the docs时为什么要在每个帧上创建一个新的Vector3。

// update the picking ray with the camera and mouse position
raycaster.setFromCamera( mouse,camera );

// calculate objects intersecting the picking ray
var intersects = raycaster.intersectObjects( scene.children );

无需执行unprojectVector然后减去摄像机位置,或者如果您使用setFromCamera(),则无需执行任何操作。

编辑:只要意识到您还有两个相互覆盖的侦听器(onMouseMoveonDocumentMouseMove),其中一个侦听器使用错误的公式来计算mouse.y,这就是为什么重新获得一个反向的y值。