防止物体在三个js中移动到房间外 [英] Prevent objects from moving outside room in three js

查看:22
本文介绍了防止物体在三个js中移动到房间外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用三个js创建了一个房间并在其中添加了各种对象.但,物体正在移出房间.这是我的代码运行所在的网址:

I have created a room in three js and added various objects in it. But, the objects are moving out of the room. Here is the url on which my code is running:

http://istation-demo.cladev.com/room.html

推荐答案

为了防止物体离开房间或相互碰撞,你必须至少有一个简单的碰撞检测形式.大多数 3D 引擎,包括three.js,对于所有创建的3d 对象都有轴对齐的边界框(或AABB).在three.js中访问边界框,最简单的方法是调用var boundingBoxHelperObject = new THREE.BoundingBoxHelper( object )如果您将它添加到场景中,它会显示为一个线框灰色框,紧紧围绕着对象.如果您对助手调用 update(您很快就会看到),它将实时更新 3d 对象的尺寸和移动 - 非常酷!

In order to prevent objects leaving the room or colliding with each other, you must have at least a simple form of collision detection. Most 3D engines, three.js included, have Axis-Aligned Bounding Boxes ( or AABB ) for all the 3d objects that are created. In three.js to get access to bounding boxes, the easiest way is to call var boundingBoxHelperObject = new THREE.BoundingBoxHelper( object ) If you add it to the scene, it shows up as a wireframe grey box that fits tightly around the object. If you call update on the helper (as you will see shortly), it will update to the dimensions and movement of the 3d object in real time - pretty cool!

然后,要对所有这些框执行碰撞检测,您可以调用boundingBoxHelperObject.box.intersectsBox( anotherBoxHelperObject.box)

Then, to perform collision detection on all these boxes, you call boundingBoxHelperObject.box.intersectsBox( anotherBoxHelperObject.box )

碰撞时输出真,不碰撞时输出假.然后执行适当的操作,例如将盒子向后移动一个框架以防止它逃出房间或穿透另一个固体对象,或者改变两个碰撞对象的颜色,或者任何你想要的.

which outputs true if colliding or false if not colliding. Then perform the appropriate actions, such as moving the box back a frame to prevent it from escaping a room or penetrating another solid object, or changing both colliding objects' colors, or whatever you want.

这是最终代码示例,其中包含您几个月前发布的最后一篇文章中我更正的拾取/拖动代码,以及新的边界框和碰撞测试代码:

Here's the final code sample with my corrected picking/dragging code from the last post you made months ago, plus the new bounding boxes and collision testing code:

    <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/html">
<head lang="en">
    <meta charset="UTF-8">
    <title>Room</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r75/three.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 chairOldPosition = new THREE.Vector3();
    var sofaOldPosition = new THREE.Vector3();

    var chair_rotate = false;
    var walls;
    var mesh_box;
    var wallright, wallleft, wallback, wallfront, ceiling, ground;
    var strDownloadMime = "image/octet-stream";
    var chairBox, sofaBox;
    var wallrightBox, wallleftBox, wallbackBox, wallfrontBox;

    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);

        wallleftBox = new THREE.BoundingBoxHelper( wallleft );
        wallleftBox.update(wallleft);
            //wallleftBox.box.min.x -= 0.1;
        //wallleftBox.box.max.x += 0.1;
        //scene.add(wallleftBox);

        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);

        wallrightBox = new THREE.BoundingBoxHelper( wallright );
        wallrightBox.update(wallright);
            //wallrightBox.box.min.x -= 0.1;
        //wallrightBox.box.max.x += 0.1;
        //scene.add(wallrightBox);

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

        wallbackBox = new THREE.BoundingBoxHelper( wallback );
        wallbackBox.update(wallback);
        //scene.add(wallbackBox);

        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);

        wallfrontBox = new THREE.BoundingBoxHelper( wallfront );
        wallfrontBox.update(wallfront);
        //scene.add(wallfrontBox);



        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);

        sofaBox = new THREE.BoundingBoxHelper( sofa_model );

            // comment next line out if you don't want to see the wireframe sofa boxHelper
            scene.add(sofaBox);

        });


         //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(-300,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);

        chairBox = new THREE.BoundingBoxHelper( chair_model );

        // comment next line out if you don't want to see the wireframe chair boxHelper
            scene.add(chairBox);

        });



        //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;

    chairBox.update(chair_model);
    sofaBox.update(sofa_model);
    //wallrightBox.update(wallright);
    //wallleftBox.update(wallleft);
    //wallfrontBox.update(wallfront);
    //wallbackBox.update(wallback);



        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;
            //oldIntersectPoint.copy(chair_model.position);
        chairBox.material.color.set('white');
            } else if (intersects[0].object.name == 'sofa_model') {
                container.style.cursor = 'pointer';
                sofa_selected = true;
            //oldIntersectPoint.copy(sofa_model.position);
        sofaBox.material.color.set('white');
            }
            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);

    chairBox.material.color.set('grey');
    sofaBox.material.color.set('grey');
    }


    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) {

            var okToMove = true;

            chairOldPosition.copy(chair_model.position);

            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);
            // store old intersect point for next frame
            oldIntersectPoint.copy(newIntersectPoint);

                        chair_model.position.add(intersectOffset);
            chair_model.updateMatrixWorld(true);
            //chairBox.updateMatrixWorld(true);
            chairBox.update(chair_model);

            // default
            chairBox.material.color.set('white');   

            if( chairBox.box.intersectsBox(sofaBox.box) ) {
                okToMove = false;
                chairBox.material.color.set('red');
            }
            else if( chairBox.box.intersectsBox(wallrightBox.box) ) {
                okToMove = false;
                chairBox.material.color.set('red');
            }
            else if( chairBox.box.intersectsBox(wallleftBox.box) ) {
                okToMove = false;
                chairBox.material.color.set('red');
            }
            else if( chairBox.box.intersectsBox(wallfrontBox.box) ) {
                okToMove = false;
                chairBox.material.color.set('red');
            }
            else if( chairBox.box.intersectsBox(wallbackBox.box) ) {
                okToMove = false;
                chairBox.material.color.set('red');
            }

            // if NOT ok to move and chair is hitting something,
            if ( !okToMove ) {
                // put chair back where it was
                chair_model.position.copy(chairOldPosition);
            }


                }
                // 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) {

            var okToMove = true;

            sofaOldPosition.copy(sofa_model.position);

            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);

            sofa_model.updateMatrixWorld(true);
            //sofaBox.updateMatrixWorld(true);
            sofaBox.update(sofa_model);

            // default
            sofaBox.material.color.set('white');    

            if( sofaBox.box.intersectsBox(chairBox.box) ) {
                okToMove = false;
                sofaBox.material.color.set('red');
            }
            else if( sofaBox.box.intersectsBox(wallrightBox.box) ) {
                okToMove = false;
                sofaBox.material.color.set('red');
            }
            else if( sofaBox.box.intersectsBox(wallleftBox.box) ) {
                okToMove = false;
                sofaBox.material.color.set('red');
            }
            else if( sofaBox.box.intersectsBox(wallfrontBox.box) ) {
                okToMove = false;
                sofaBox.material.color.set('red');
            }
            else if( sofaBox.box.intersectsBox(wallbackBox.box) ) {
                okToMove = false;
                sofaBox.material.color.set('red');
            }

            // if NOT ok to move and sofa is hitting something,
            if ( !okToMove ) {
                // put sofa back where it was
                sofa_model.position.copy(sofaOldPosition);
            }

                }
                // 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中移动到房间外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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