旋转平面后物体向不同方向移动,三个js(v73) [英] Object moving in different direction after rotating the plane, three js(v73)

查看:17
本文介绍了旋转平面后物体向不同方向移动,三个js(v73)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用鼠标移动对象时遇到问题.当我最初移动对象时它工作正常,但是在围绕 y 轴旋转场景后,对象开始向鼠标的相反方向移动.我为此创建了一个 jsfiddle.代码如下:

I am have having issue in moving the object, when using mouse. When i move the object initially it works fine, but after rotating the scene about the y-axis, the object starts moving in opposite direction of the mouse. I have created a jsfiddle for that. Here is the code:

//define global variables here
var container, renderer;
var camera, scene, projector,mouseVector,controls;
var mouseX, mouseY, draggable;
var pen,c_mesh,interactiveObj = [];
var cube_selected=false;
var wallWidth=1200;
var wallHeight=400;
var raycaster = new THREE.Raycaster(); // create once
var mouse = new THREE.Vector2(); // create once 
init();
animate();

function init(){

    container=document.createElement('div');

    document.body.appendChild(container);

    camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 10, 10000);
    //camera.position.set(0,-wallWidth/2+10,wallWidth);
    camera.position.set(0,-wallHeight/2+10,wallWidth);
  // camera.lookAt(new THREE.Vector3(0,-wallWidth/2 +10,10));
    //camera.lookAt(new THREE.Vector3(10,10,10));

    scene = new THREE.Scene();

    var ambient = new THREE.AmbientLight(0x666666);
    scene.add(ambient);

    //walls
    walls = new THREE.Object3D();

    var groundMat = new THREE.MeshPhongMaterial({color:0x808080});

    var groundGeo_2 = new THREE.PlaneGeometry(wallWidth, wallWidth); //for roof and floor

    var ground = new THREE.Mesh(groundGeo_2, groundMat);
    ground.overdraw = true;
    ground.position.set(0, -wallHeight, 0);
    ground.rotation.x = -Math.PI/2;
    walls.add(ground);






    var cube_geometry = new THREE.CubeGeometry(500,300,100);
    var c_material = new THREE.MeshNormalMaterial();
     c_mesh     = new THREE.Mesh(cube_geometry, c_material);

    c_mesh.overdraw = true;
    c_mesh.name = "first_cube";
    c_mesh.position.set(0, -wallHeight+100/2-1 ,0); //c_mesh.add(camera);
    c_mesh.rotation.x = Math.PI * 0.1;

    interactiveObj.push(c_mesh);
    walls.add(c_mesh);



    scene.add(walls);

    //projector = new THREE.Projector();
    mouseVector = new THREE.Vector3();

    renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMapEnabled = true;
    container.appendChild( renderer.domElement );

    //IE, Chrome, Safari, Opera
    document.addEventListener('mousewheel',onDocumentMouseWheel, false);
    //Firefox
    document.addEventListener('DOMMouseScroll', onDocumentMouseWheel, false);
    document.addEventListener( 'mousemove', onDocumentMouseMove, false );

    document.addEventListener('mousedown', onDocumentMouseDown, false);

    document.addEventListener('mouseup', onDocumentMouseUp, false);
    window.addEventListener( 'resize', onWindowResize, false );

}
function animate() {
    requestAnimationFrame( animate );
    render();

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


function onWindowResize() {

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize( window.innerWidth, window.innerHeight );
}

function onDocumentMouseDown(event){
    draggable = true;
    event.preventDefault();

    mouse.x = ( event.clientX / renderer.domElement.width ) * 2 - 1;
    mouse.y = - ( event.clientY / renderer.domElement.height ) * 2 + 1;
    raycaster.setFromCamera( mouse, camera );
    var intersects = raycaster.intersectObjects( interactiveObj, true );
    console.log(intersects);
    if ( intersects.length > 0 ) {
        if(intersects[0].object == c_mesh)  {
            renderer.domElement.style.cursor = 'pointer';           
            console.log("cube selected "); cube_selected=true;               
        }else{
            cube_selected=false;
        }
        draggable = false;
    }

}

function onDocumentMouseUp(event){
    draggable = false;
     cube_selected=false;
     renderer.domElement.style.cursor = 'auto';
}


function onDocumentMouseMove( event ) {
    if(draggable){
        if(mouseX != 0 && mouseY != 0){
            deltaX =  event.clientX - mouseX;
            deltaY =  event.clientY - mouseY;

            walls.rotation.y += deltaX * 0.01;
            walls.rotation.x += deltaY * 0.01;
        }
    }else if (cube_selected==true){
        if(mouseX != 0 && mouseY != 0){
            deltaX =  event.clientX - mouseX;
            deltaY =  event.clientY - mouseY;
            c_mesh.position.x  += deltaX*1.5 ;
            c_mesh.position.y  -= deltaY*1.5 ;               
        }
    }
    mouseX = event.clientX;
    mouseY = event.clientY;
    render();
}

function onDocumentMouseWheel( event ) {
    mouseDelta = (-event.wheelDeltaY|| event.detail);
    camera.position.z += mouseDelta * 1 ;
   // console.log("camera position : "+ camera.position.z);
    render();
}

https://jsfiddle.net/pn1pL4jb/5/

我做了什么:在平面中添加对象,而不是场景,因为我希望平面和对象在同一方向上进行相同的旋转.

What i have done: Added object in plane, rather then to scene because I want the same rotation of plane and object in the same direction.

推荐答案

以下是此问题的第二个答案.OP 已将orbitControls.js 添加到他的应用程序中,现在所有对象都更易于管理.这是整个应用程序的 .html 文件,已更新以反映更改.现在,您可以单击/拖动以旋转整个房间.然后你可以点击/拖动椅子或沙发,然后在房间里拖动它们.它们的 Y 位置被固定在地面 (0.0) 上,这样它们就不会错误地穿透地板.

The following is a 2nd answer to this problem. The OP has added orbitControls.js to his app and now all the objects are more manageable. Here is the whole app's .html file, updated to reflect the changes. Now, you can click/drag to rotate the whole room. And then you can click/drag on the chair or the sofa and drag them around the room. Their Y positions are clamped to the ground (0.0) so that they do not incorrectly penetrate the floor.

物体沿地板滑动是通过仅对地面进行光线投射来实现的(当鼠标选择并拖动它们时).光线投射返回世界空间中的交点,所以我只是将其复制到可拖动对象的位置.然后他们的 Y 位置的后夹防止他们从地板上掉下来.

The sliding of objects along the floor is achieved through raycasting against just the ground (when the mouse has selected them and dragging them). The raycast returns the intersection point in world space, so I just copy that into the draggable objects' position. Then a post-clamp of their Y positions prevent them from falling through the floor.

更好的是,我们不再需要 localToWorld 和 worldToLocal 矩阵黑客",因为一切都与场景相关,这就是现实生活中的情况.:) 为了证明这一点,我添加了一个示例来更新椅子围绕其自身 Y 轴的旋转,因此我们有一个旋转椅子,它能够围绕其自身的局部重心旋转,同时还能够相对于场景(世界).

Even better, is the fact that we don't need localToWorld and worldToLocal matrix 'hacks' anymore because everything is relative to the Scene, which is how it is in real life. :) To prove this, I added an example update the chair's rotation around its own Y axis, so we have a spinning chair that is able to rotate around its own local center of gravity, while also being able to move its position relative to the Scene (world).

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/html">
<head lang="en">
    <meta charset="UTF-8">
    <title>Room</title>
</head>
<body>
<script src="http://alexan0308.github.io/threejs/build/three.min.js"></script>
<script src="http://alexan0308.github.io/threejs/examples/js/loaders/OBJLoader.js"></script>
<script src="http://alexan0308.github.io/threejs/examples/js/loaders/MTLLoader.js"></script>
<script src="http://alexan0308.github.io/threejs/examples/js/loaders/OBJMTLLoader.js"></script>


<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>

<div id="workspace"></div>
<script>
    //define global variables here
    var container, renderer;
    var camera, scene, projector, mouseVector, controls;
    var mouseX, mouseY, draggable;
    var pen, c_mesh, interactiveObj = [], rotateObj = [], groundRaycastObj = [];
    var wallWidth = 1200;
    var wallHeight = 400;
    var chair_model, sofa_model;
    var chair_selected = false;
    var sofa_selected = false;

    var raycaster;
    var mouse = new THREE.Vector2(), INTERSECTED;
    var radius = 100, theta = 0;
    var oldIntersectPoint = new THREE.Vector3();
    var newIntersectPoint = new THREE.Vector3(); 
    var intersectOffset   = new THREE.Vector3();

    var chair_rotate = false;
    var walls;
    var mesh_box;
    var wallright, wallleft, wallback, wallfront, ceiling, ground;
    var strDownloadMime = "image/octet-stream";

    init();
    animate();

    function init() {

        container = document.getElementById('workspace'); //document.createElement('div');

        document.body.appendChild(container);

        //camera
        //camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 10, 10000);
       // camera.position.set(0, -wallHeight / 2 + 10, wallWidth);
        //  camera.lookAt(new THREE.Vector3(10, 10, 10));

        //renderer
        renderer = new THREE.WebGLRenderer({preserveDrawingBuffer: true});
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setClearColor(0x889988);
        renderer.shadowMapEnabled = true;
        container.appendChild(renderer.domElement);

        scene = new THREE.Scene();
        raycaster = new THREE.Raycaster();

        var ambient = new THREE.AmbientLight(0xffffff);
        scene.add(ambient);

        camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 10000 );

        camera.position.z= wallWidth;
        camera.position.y= wallWidth/2;


        controls = new THREE.OrbitControls( camera, renderer.domElement );
                //controls.addEventListener( 'change', render ); // add this only if there is no animation loop (requestAnimationFrame)
                controls.enableDamping = true;
                controls.dampingFactor = 0.25;
                //controls.enableZoom = false;



        //walls
        walls = new THREE.Object3D();


        var groundGeo_2 = new THREE.PlaneGeometry(wallWidth, wallWidth); //for roof and floor
        var groundGeo = new THREE.PlaneGeometry(wallWidth, wallHeight);

        var wallTextureRight = new THREE.MeshBasicMaterial({
            map: THREE.ImageUtils.loadTexture('textures/walls/rainbow.jpg')
        });
        wallTextureRight.map.needsUpdate = true;

        var wallTextureLeft = new THREE.MeshBasicMaterial({
            map: THREE.ImageUtils.loadTexture('textures/walls/rainbow.jpg')
        });

        var wallTextureFront = new THREE.MeshBasicMaterial({
            map: THREE.ImageUtils.loadTexture('textures/walls/wall4.jpg')
        });

        var wallTextureBack = new THREE.MeshBasicMaterial({
            map: THREE.ImageUtils.loadTexture('textures/walls/wall3.png')
        });

        var floorTexture = new THREE.MeshBasicMaterial({
            map: THREE.ImageUtils.loadTexture('textures/walls/floor.jpg')
        });
        floorTexture.map.needsUpdate = true;

        var ceilTexture = new THREE.MeshBasicMaterial({
            map: THREE.ImageUtils.loadTexture('textures/walls/wall4.jpg')
        });

        ground = new THREE.Mesh(groundGeo_2, floorTexture);
        ground.overdraw = true;
        ground.position.set(0, 0, 0);
        ground.rotation.x = -Math.PI / 2;
        walls.add(ground);
        console.log(ground);

        wallleft = new THREE.Mesh(groundGeo, wallTextureLeft);
        wallleft.overdraw = true;
        wallleft.position.set(-wallWidth / 2, wallHeight / 2, 0);
        wallleft.rotation.y = Math.PI / 2;
        walls.add(wallleft);

        wallright = new THREE.Mesh(groundGeo, wallTextureRight);
        wallright.overdraw = true;
        wallright.position.set(wallWidth / 2, wallHeight / 2, 0);
        wallright.rotation.y = -Math.PI / 2;
        walls.add(wallright);

        wallback = new THREE.Mesh(groundGeo, wallTextureBack);
        wallback.overdraw = true;
        wallback.position.set(0, wallHeight / 2, -wallWidth / 2);
        walls.add(wallback);

        wallfront = new THREE.Mesh(groundGeo, wallTextureFront);
        wallfront.overdraw = true;
        wallfront.position.set(0, wallHeight / 2, wallWidth / 2);
        wallfront.rotation.y = -Math.PI;
        walls.add(wallfront);

        ceiling = new THREE.Mesh(groundGeo_2, ceilTexture);
        ceiling.position.set(0, wallHeight, 0);
        ceiling.rotation.x = Math.PI / 2;
        walls.add(ceiling);

        scene.add(walls);

        groundRaycastObj.push(walls);

        //load bed texture
        var bed_texture = new THREE.ImageUtils.loadTexture("textures/cb-rochelle-gray_baked.png");
        var bedMaterial = new THREE.MeshBasicMaterial({
            map: bed_texture,
            side: THREE.DoubleSide
        });

        //load bed
        var loader = new THREE.JSONLoader();
        loader.load('js/sofa.js', function (geometry) {
            sofa_model = new THREE.Mesh(geometry, bedMaterial);
            for (var i = 0; i < sofa_model.children.length; i++) {
                sofa_model.children[i].material = material;
                sofa_model.children[i].userDataParent = sofa_model;
                sofa_model.children[i].name = 'sofa_model';
            }
            sofa_model.position.set(200,0, -200);
            sofa_model.rotation.set(0, 0, 0);
            sofa_model.scale.set(3, 3, 3);
            sofa_model.name = 'sofa_model';
            interactiveObj.push(sofa_model);
            scene.add(sofa_model);

        });


         //load chair texture
        var chair_texture = new THREE.ImageUtils.loadTexture("textures/chair.png");
        var chairMaterial = new THREE.MeshBasicMaterial({
            map: chair_texture,
            side: THREE.DoubleSide
        });

        //load chair
        var loader = new THREE.JSONLoader();
        loader.load('js/chair_model.js', function (geometry) {
            chair_model = new THREE.Mesh(geometry, chairMaterial);
            for (var i = 0; i < chair_model.children.length; i++) {
                chair_model.children[i].material = material;
                chair_model.children[i].userDataParent = sofa_model;
                chair_model.children[i].name = 'chair_model';
            }
            chair_model.position.set(-200,0, -200);
            chair_model.rotation.set(0, 0, 0);
            chair_model.scale.set(3, 3, 3);
            chair_model.name = 'chair_model';
            interactiveObj.push(chair_model);
            scene.add(chair_model);

        });



        //IE, Chrome, Safari, Opera
        document.addEventListener('mousewheel', onDocumentMouseWheel, false);
        //Firefox
        document.addEventListener('DOMMouseScroll', onDocumentMouseWheel, false);
        document.addEventListener('mousemove', onDocumentMouseMove, false);
        document.addEventListener('mousedown', onDocumentMouseDown, false);
        document.addEventListener('mouseup', onDocumentMouseUp, false);
        window.addEventListener('resize', onWindowResize, false);

    }
    function animate() {


        requestAnimationFrame(animate);
        chair_model.rotation.y += 0.02;
        controls.update();

        // Render the frame
        //Don't render twice, it will slow down your animation!
        //render();
        renderer.render(scene, camera);

    }

    function render() {

        renderer.render(scene, camera);
    }



    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);

        //controls.handleResize();

    }

    function onDocumentMouseDown(event) {
        draggable = true;
        event.preventDefault();

    var testIntersects;
        testIntersects = raycaster.intersectObjects(groundRaycastObj, true);
        if (testIntersects.length > 0)
            oldIntersectPoint.copy(testIntersects[0].point);

        // find intersections
        raycaster.setFromCamera(mouse, camera);
        var intersects = raycaster.intersectObjects(interactiveObj, true);
        if (intersects.length > 0) {
            controls.enabled=false;

            if (intersects[0].object.name == 'chair_model') {
                container.style.cursor = 'pointer';
                chair_selected = true;
            } else if (intersects[0].object.name == 'sofa_model') {
                container.style.cursor = 'pointer';
                sofa_selected = true;
            }
            else {
                chair_selected = false;
                sofa_selected = false;
            }
            draggable = false;
        }

    }

    function onDocumentMouseUp(event) {
        draggable = false;
        chair_selected = false;
        sofa_selected = false;
        chair_rotate = false;
        container.style.cursor = 'auto';
        controls.enabled=true;

    oldIntersectPoint.set(0,0,0);
    newIntersectPoint.set(0,0,0);
        intersectOffset.set(0,0,0);
    }


    function onDocumentMouseMove(event) {

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

        var deltaX = event.clientX - mouseX;
        var deltaY = event.clientY - mouseY;

        var testIntersects;

        raycaster.setFromCamera(mouse, camera);
        var intersects = raycaster.intersectObjects(interactiveObj, true);

        if (intersects.length > 0) {
            container.style.cursor = 'pointer';
            //addRotationLine(intersects[0].object);

        } else {
            container.style.cursor = 'auto';
        }

        if (draggable) {

        } else if (chair_selected == true) {

                testIntersects = raycaster.intersectObjects(groundRaycastObj, true);
                if (testIntersects.length > 0) {

            newIntersectPoint.copy(testIntersects[0].point);

            intersectOffset.copy(newIntersectPoint);
                intersectOffset.sub(oldIntersectPoint);
            //uncomment below if you want more precision mouse movements of objects
            //intersectOffset.multiplyScalar(0.1);
                    oldIntersectPoint.copy(newIntersectPoint);
                        chair_model.position.add(intersectOffset); 

                }
                // clamp chair position to the ground
                chair_model.position.y = 0;

        } else if (chair_rotate == true) {
            rotate_object(chair_model, event);
        }
        else if (sofa_selected == true) {
            testIntersects = raycaster.intersectObjects(groundRaycastObj, true);
                if (testIntersects.length > 0) {

            newIntersectPoint.copy(testIntersects[0].point);

            intersectOffset.copy(newIntersectPoint);
                intersectOffset.sub(oldIntersectPoint);
            //uncomment below if you want more precision mouse movements of objects
            //intersectOffset.multiplyScalar(0.1);
                    oldIntersectPoint.copy(newIntersectPoint);
                        sofa_model.position.add(intersectOffset); 

                }
                // clamp sofa position to the ground
                sofa_model.position.y = 0;
        }
        mouseX = event.clientX;
        mouseY = event.clientY;
        //render(); // no need to render
    }

    function onDocumentMouseWheel(event) {
        // This is automatically handled for you by orbitControls.js, 
        // but you can't disable zoom on the controls - so don't type controls.enableZoom = false;

        //mouseDelta = (-event.wheelDeltaY || event.detail);
        //camera.position.z += mouseDelta * 1;
        //render(); // no need to render
    }

    function addRotationLine(objModel) {
        var material = new THREE.LineBasicMaterial({
            color: 0x0000ff,
            linewidth: 6
        });
        var geometry = new THREE.Geometry();
        geometry.vertices.push(
                new THREE.Vector3(-10, 500, 0),
                new THREE.Vector3(1000, 500, 0)
        );
        var line = new THREE.Line(geometry, material);
        objModel.add(line);
    }
    function rotate_object(object, event) {
        mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        mouse.y = -( event.clientY / window.innerHeight ) * 2 + 1;
        var deltaX = event.clientX - mouseX;
        var deltaY = event.clientY - mouseY;

        object.rotation.y += deltaX * 0.02;
        object.rotation.y += deltaY * 0.01;
    }


</script>
</body>
</html>

这篇关于旋转平面后物体向不同方向移动,三个js(v73)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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