三维坐标与平面坐标的转换(threejs)

这个是世界坐标转平面坐标
function updateScreenPosition() {
    if (sprite === undefined) {
        return false;
    } else {


        var vector = new THREE.Vector3(sprite.matrixWorld.elements[12], sprite.matrixWorld.elements[13], sprite.matrixWorld.elements[14]);
        var canvas1 = renderer.domElement;


        vector.project(camera);


        vector.x = Math.round((0.5 + vector.x / 2) * window.innerWidth);
        vector.y = Math.round((0.5 - vector.y / 2) * window.innerHeight);


        annotation.style.top = vector.y + "px";
        annotation.style.left = vector.x + "px";
    }


}


这是屏幕坐标转换成三维坐标
_mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1;
_mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1;




其它:
     var WIDTH = window.innerWidth;
        var HEIGHT = window.innerHeight;


        //将鼠标的屏幕坐标转换为NDC坐标
        var mX = ( ev.clientX / WIDTH ) * 2 - 1;
        var mY = - ( ev.clientY / HEIGHT ) * 2 + 1;


        //这里定义深度值为0.5,深度值越大,意味着精度越高
        var vector = new THREE.Vector3(mX, mY, 0.5 );
        //将鼠标坐标转换为3D空间坐标

        vector.unproject(camera);


我发现好多人看了上面也并不知道怎么获取三维的坐标,其实是没有深度的原因;上面算的只是系数,你要根据深度(z坐标)

我是在里面加了一个平面,然后用射线,这样,根据射线投射到平面的点就是他的坐标,平面就相当于我们知道他的深度,然后根据系数算它的坐标,这只是一种思路,让你明白它们之间的关系;


我的代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>鼠标移动世界坐标中的物体一起移动 - 平面坐标转换成3d坐标</title>
    <meta charset="utf-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <style>
        body {
            font-family: Monospace;
            background-color: #000;
            color: #fff;
            margin: 0px;
            overflow: hidden;
            text-align:center;
        }

        a {
            position: absolute;
            text-align:center;
            top: 20px;
            font-size: 18px;
        }
    </style>
    <script src="../js/three.js"></script>
    <script src="../js/TrackballControls.js"></script>
    <script src="../js/hammer.js"></script>
    <a> 屏幕坐标转换成3d坐标,查了很多资料,都是只讲了一个大概;
        如实现算法:
        mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        mouse.y = -( event.clientY / window.innerHeight ) * 2 + 1;
        但是你以为这么就可以得到世界坐标,结果发现并没有,
        最后我查了很多资料,并看了democ才有所启发,我的实现方式是使用射线;
        上面的计算你得到的只是系数,并不是世界坐标中的坐标,因为计算机根本就不知道你的深度,你要点击的是什么位置,
        所有我用了射线;实现思路就是,你在屏幕上移动的物体的坐标,转换成世界坐标,相机的位置,和屏幕的位置(点击位置),
        形成了一条射线,然后在与你想要的位置屏幕,相差交叉,就得到了世界坐标的位置;
    </a>
    <script>
        var container;
        var camera, scene, renderer;
        var camera_angle = 45;//设置相机的角度
        var obj = null;
        var controls;
        var isRotate = false;//obj是否旋转
        var roomMesh1;
        var raycaster;
        var mouse = new THREE.Vector2(100, 100), INTERSECTED;
        var planeMesh;

        function initView() {

            container = document.createElement('div');
            document.body.appendChild(container);
            raycaster = new THREE.Raycaster();
            // scene
            initScene();
            initCamera();
            initOrbitControls();

            initLight();
            initRenderer();

            var materialRing1 = new THREE.MeshBasicMaterial({color: 0x0000ff});

            var geometry1 = new THREE.SphereBufferGeometry(5, 32, 32);
            roomMesh1 = new THREE.Mesh(geometry1, materialRing1);
            roomMesh1.position.set(0, 0, 0);
            scene.add(roomMesh1);

            var planeMaterial = new THREE.MeshBasicMaterial({
                color: 0x2194ce,
                opacity: 0,
                transparent: true,
                depthTest: true
            });
            var planeGeometry = new THREE.PlaneBufferGeometry(800, 800, 1);
            planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
            planeMesh.position.set(0, 0, 0);
            console.log(planeMesh);
//            scene.add(planeMesh);
            animate();
        }


        function initCamera() {
            camera = new THREE.PerspectiveCamera(camera_angle, window.innerWidth / window.innerHeight, 0.1, 20000);
            camera.position.set(400, 400, 400);
            camera.up.set(0, 1, 0);
        }


        function initScene() {
            scene = new THREE.Scene();
            document.addEventListener('mousemove', onDocumentMouseMove, false);
        }

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


        var pointLight;//跟上相机一起的点光源,用于透明
        var spotLight;//光束光 ,用于不透明
        function initLight() {
            var ambientLight = new THREE.AmbientLight(0x505050);
            scene.add(ambientLight);

            pointLight = new THREE.PointLight(0xffffff, 1);
            camera.add(pointLight);
            scene.add(camera);
        }

        function initOrbitControls() {
            controls = new THREE.TrackballControls(camera);
            controls.rotateSpeed = 1.0;
            controls.zoomSpeed = 1.2;
            controls.panSpeed = 0.8;
            controls.noZoom = false;
            controls.noPan = false;
            controls.staticMoving = true;
            controls.dynamicDampingFactor = 0.3;
            // controls = new THREE.OrbitControls(camera, renderer.domElement);
        }

        function initRenderer() {
            renderer = new THREE.WebGLRenderer({antialias: true});
            renderer.setPixelRatio(window.devicePixelRatio);
            renderer.shadowMap.enabled = true;
            renderer.shadowMap.renderSingleSided = false;
            /*设置设备像素比*/
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.shadowMapEnabled = true;
            renderer.shadowMap.type = THREE.PCFSoftShadowMap;//让边缘柔和起来
            renderer.gammaInput = true;

            renderer.gammaOutput = true;
            container.appendChild(renderer.domElement);
        }


        /*循环*/
        function animate() {
            render();
            requestAnimationFrame(animate);
        }

        /*更新渲染*/
        function render() {
            planeMesh.lookAt(camera.position);

            if (obj != null && isRotate) {
                obj.rotateOnAxis(new THREE.Vector3(0, 1, 0), 0.005)
            }
            controls.update();

            raycaster.setFromCamera(mouse, camera);
            var intersects = raycaster.intersectObject(planeMesh);
            if (intersects.length > 0) {
                if (intersects[0].object) {
                    console.log(intersects[0].object);
                    intersects[0].object.material.color.setHex(0x0000ff);
                    roomMesh1.position.copy(intersects[0].point);
                }
            }
            renderer.render(scene, camera);
        }

    </script>
</head>
<body onload="initView()">

</body>
</html>



展开阅读全文

没有更多推荐了,返回首页