我想知道如何使用鼠标围绕用THREE.JS创建的网格的Z轴旋转

时间:2017-03-23 06:59:50

标签: javascript three.js rotation mesh z-axis

我正在实现使用鼠标旋转网格的功能。

引用代码是链接的网站。 ( “http://3dit.bordeaux.inria.fr/testbed.html#navigation_Map_Navigation”)

我想知道如何使用鼠标绕Z轴(红线)旋转。

我发现Three.js中的所有示例都只能围绕x轴或y轴旋转。

真的需要帮助。

我的代码:https://jsfiddle.net/pfk7j7a3/3/

<script type="text/javascript">
    CustomOrbit = function () {
        var EPS = 0.000001;
        var rotateStart = new THREE.Vector2();
        var rotateEnd = new THREE.Vector2();
        var rotateDelta = new THREE.Vector2();

        var phiDelta = 0;
        var thetaDelta = 0;

        var target = new THREE.Vector3();

        /// How far you can orbit vertically, upper and lower limits.
        var minPolarAngle = Math.PI / 2;
        var maxPolarAngle = Math.PI * 0.91;

        var onMouseDownPosition = new THREE.Vector2();

        this.Initialize = function () {
            renderer.domElement.addEventListener('mousedown', onMouseDown, false);
        }

        var onMouseMove = function (event) {
            event.preventDefault();
            rotateEnd.set(event.clientX, event.clientY);
            rotateDelta.subVectors(rotateEnd, rotateStart);

            thetaDelta -= 2 * Math.PI * rotateDelta.x / renderer.domElement.clientWidth;
            phiDelta -= 2 * Math.PI * rotateDelta.y / renderer.domElement.clientHeight;

            var position = camera.position;
            var offset = position.clone().sub(target);

            // angle from z-axis around y-axis          
            var theta = Math.atan2(offset.x, offset.z);
            theta += thetaDelta;

            // angle from y-axis
            var phi = Math.atan2(Math.sqrt(offset.x * offset.x + offset.z * offset.z), offset.y);
            phi += phiDelta;
            phi = Math.max(minPolarAngle, Math.min(maxPolarAngle, phi));// restrict phi to be between desired limits
            phi = Math.max(EPS, Math.min(Math.PI - EPS, phi));          // restrict phi to be between EPS and PI-EPS

            var radius = offset.length();
            radius = Math.max(0, Math.min(Infinity, radius)); // restrict radius to be between desired limits

            offset.x = radius * Math.sin(phi) * Math.sin(theta);
            offset.y = radius * Math.cos(phi);
            offset.z = radius * Math.sin(phi) * Math.cos(theta);

            position.copy(target).add(offset);

            camera.lookAt(target);

            thetaDelta = 0;
            phiDelta = 0;

            rotateStart.copy(rotateEnd);
        }
        var onMouseUp = function (event) {
            renderer.domElement.removeEventListener('mousemove', onMouseMove, false);
            renderer.domElement.removeEventListener('mouseup', onMouseUp, false);
        }

        var onMouseDown = function (event) {
            event.preventDefault();

            vector = new THREE.Vector3(0, 0, camera.near);
            vector.unproject(camera);
            raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize(), camera.near, camera.far);
            intersects = raycaster.intersectObject(pickingMesh);

            if (intersects.length > 0) {
                target = intersects[0].point;
                rotateStart.set(event.clientX, event.clientY);

                renderer.domElement.addEventListener('mousemove', onMouseMove, false);
                renderer.domElement.addEventListener('mouseup', onMouseUp, false);
            }
        }
    };
</script>
<script type="text/javascript">
    var camera, scene, renderer, pickingMesh, rendWidth = 500, rendHeight = 500;
    init();
    makeMesh();
    makeAxis(200);
    animate();

    function init() {
        scene = new THREE.Scene();
        renderer = new THREE.WebGLRenderer({ antialias: true, alpha: false });
        renderer.setSize(500, 500);
        document.body.appendChild(renderer.domElement);

        camera = new THREE.PerspectiveCamera(55, 500 / 500, 0.1, 10000);
        camera.position.x = 200000;
        camera.position.y = 400000;
        camera.position.z = 300;
        camera.lookAt(new THREE.Vector3(200000, 400000, 0.0));
    }

    function animate() {
        requestAnimationFrame(animate);
        renderer.render(scene, camera);
    }


    //create red square mesh
    function makeMesh() {
        var geometry = new THREE.BufferGeometry();
        var vertices = new Float32Array([
            200000 - 100.0, 400000 - 100.0, 0.0,
            200000 + 100.0, 400000 + 100.0, 0.0,
            200000 - 100.0, 400000 + 100.0, 0.0,

            200000 - 100.0, 400000 - 100.0, 0.0,
            200000 + 100.0, 400000 - 100.0, 0.0,
            200000 + 100.0, 400000 + 100.0, 0.0
        ]);

        geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3));
        var material = new THREE.MeshBasicMaterial({ color: 0xff0000, transparent: true, opacity: 0.5 });
        material.side = THREE.DoubleSide;
        pickingMesh = new THREE.Mesh(geometry, material);

        scene.add(pickingMesh);
    }

    function makeAxis(axisLength) {
        var x_axis = new THREE.Geometry(); x_axis.vertices.push(new THREE.Vector3(200000 - axisLength, 400000, 0), new THREE.Vector3(200000 + axisLength, 400000, 0));
        var y_axis = new THREE.Geometry(); y_axis.vertices.push(new THREE.Vector3(200000, 400000 - axisLength, 0), new THREE.Vector3(200000, 400000 + axisLength, 0));
        var z_axis = new THREE.Geometry(); z_axis.vertices.push(new THREE.Vector3(200000, 400000, -axisLength), new THREE.Vector3(200000, 400000, axisLength));
        var x_axis_line = new THREE.Line(x_axis, new THREE.LineBasicMaterial({ linewidth: 1, transparent: true, color: 0x0000ff }));
        var y_axis_line = new THREE.Line(y_axis, new THREE.LineBasicMaterial({ linewidth: 1, transparent: true, color: 0x00ff00 }));
        var z_axis_line = new THREE.Line(z_axis, new THREE.LineBasicMaterial({ linewidth: 1, transparent: true, color: 0xff0000 }));
        scene.add(x_axis_line);
        scene.add(y_axis_line);
        scene.add(z_axis_line);
    };

    var myOrbit = new CustomOrbit();
    myOrbit.Initialize();
</script>

1 个答案:

答案 0 :(得分:0)

如果你试图旋转出0,0,0位置(相机周围的物体,物体在中心周围的某个位置),数学将开始变得更加复杂。

我最好的经验是使用轨道控制。 https://threejs.org/examples/misc_controls_orbit.html

您可以设置角度限制和平移限制。