Three.js - how to detect what shape was selected?

2020-01-31 12:56发布

问题:

I made a canvas with shapes in it...the shapes are draggable. Everything seems to work fine...But now I'm trying to figure out how can I detect what shape was selected/dragged?

this is my code: (Javascript)

var container, stats;
            var camera, scene, projector, renderer;
            var objects = [], plane;

            var mouse = new THREE.Vector2(),
            offset = new THREE.Vector3(),
            INTERSECTED, SELECTED;

            var basic_x_dist = 0;

            var cameraX = 0,cameraY = 0,cameraZ = 100; // default-same as camera.position.z!            

            init();
            animate();

            function init() {

                container = document.createElement( 'div' );
                document.body.appendChild( container );

                camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 500 );
                camera.position.z = 300;

                scene = new THREE.Scene();

                scene.add( new THREE.AmbientLight( 0x505050 ) );

                var light = new THREE.SpotLight( 0xffffff, 1.5 );
                light.position.set( 0, 500, 2000 );
                light.castShadow = true;
                scene.add( light );             

                var geometry = new THREE.CubeGeometry( 7, 7, 1, 3, 3, 1);

                for ( var i = 0; i < 5; i ++ ) {

                    var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( {  map:                                       THREE.ImageUtils.loadTexture( 'red.png' ) } ) );

                    //object.material.ambient = object.material.color;

                      object.position.x = basic_x_dist;
                      basic_x_dist += 10;
                    //object.position.x = Math.random() * 100 - 50;
                    //object.position.y = Math.random() * 60 - 30;
                    //object.position.z = Math.random() * 80 - 40;

                    //object.rotation.x = ( Math.random() * 360 ) * Math.PI / 180;
                    //object.rotation.y = ( Math.random() * 360 ) * Math.PI / 180;
                    //object.rotation.z = ( Math.random() * 360 ) * Math.PI / 180;

                    //object.scale.x = Math.random() * 2 + 1;
                    //object.scale.y = Math.random() * 2 + 1;
                    //object.scale.z = Math.random() * 2 + 1;

                    //object.castShadow = true;
                    //object.receiveShadow = true;

                    scene.add( object );

                    objects.push( object );

                }

                plane = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000, 8, 8 ), new                    THREE.MeshBasicMaterial( { color: 0x000000, opacity: 0.25, transparent: true, wireframe:                    true } ) );

                plane.lookAt( camera.position );
                plane.visible = false;
                scene.add( plane );

                projector = new THREE.Projector();

                renderer = new THREE.CanvasRenderer();
                renderer.sortObjects = false;
                renderer.setSize( window.innerWidth, window.innerHeight );


                //renderer.shadowMapEnabled = true;
                //renderer.shadowMapSoft = true;

                //renderer.shadowCameraNear = 3;
                //renderer.shadowCameraFar = camera.far;
                //renderer.shadowCameraFov = 50;

                //renderer.shadowMapBias = 0.0039;
                //renderer.shadowMapDarkness = 0.5;
                //renderer.shadowMapWidth = 1024;
                //renderer.shadowMapHeight = 1024;

                container.appendChild( renderer.domElement );

                var info = document.createElement( 'div' );
                info.style.position = 'absolute';
                info.style.top = '10px';
                info.style.width = '100%';
                info.style.textAlign = 'center';
                info.innerHTML = '<a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> webgl - draggable cubes';
                container.appendChild( info );

                stats = new Stats();
                stats.domElement.style.position = 'absolute';
                stats.domElement.style.top = '0px';
                container.appendChild( stats.domElement );

                renderer.domElement.addEventListener( 'mousemove', onDocumentMouseMove, false );
                renderer.domElement.addEventListener( 'mousedown', onDocumentMouseDown, false );
                renderer.domElement.addEventListener( 'mouseup', onDocumentMouseUp, false );
                document.onkeypress=key_event;

            }

            function onDocumentMouseMove( event ) {

                event.preventDefault();

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


                var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
                projector.unprojectVector( vector, camera );

                var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );


                if ( SELECTED ) {

                    var intersects = ray.intersectObject( plane );
                    SELECTED.position.copy( intersects[ 0 ].point.subSelf( offset ) );
                    return;

                }


                var intersects = ray.intersectObjects( objects );

                if ( intersects.length > 0 ) {

                    if ( INTERSECTED != intersects[ 0 ].object ) {

                        if ( INTERSECTED ) INTERSECTED.material.color.setHex( INTERSECTED.currentHex );

                        INTERSECTED = intersects[ 0 ].object;
                        INTERSECTED.currentHex = INTERSECTED.material.color.getHex();

                        plane.position.copy( INTERSECTED.position );

                    }

                    container.style.cursor = 'pointer';

                } else {

                    if ( INTERSECTED ) INTERSECTED.material.color.setHex( INTERSECTED.currentHex );

                    INTERSECTED = null;

                    container.style.cursor = 'auto';

                }

            }

            function onDocumentMouseDown( event ) {

                event.preventDefault();

                var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
                projector.unprojectVector( vector, camera );

                var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );

                var intersects = ray.intersectObjects( objects );

                if ( intersects.length > 0 ) {

                    SELECTED = intersects[ 0 ].object;

                    var intersects = ray.intersectObject( plane );
                    offset.copy( intersects[ 0 ].point ).subSelf( plane.position );

                    container.style.cursor = 'move';

                }

            }

            function onDocumentMouseUp( event ) {

                event.preventDefault();

                if ( INTERSECTED ) {

                    plane.position.copy( INTERSECTED.position );

                    SELECTED = null;

                }

                container.style.cursor = 'auto';

            }

            function rotateLeft(){
                cameraX += 5;           
            }

            function rotateRight(){
                cameraX -= 5;           
            }

            function rotateUp(){
                cameraY += 5;           
            }

            function rotateDown(){
                cameraY -= 5;           
            }

            function zoomIn(){
                cameraZ += 5;           
            }

            function zoomOut(){
                cameraZ -= 5;           
            }

            function showPositions(){
                for(var i=0; i<5; i++){
                    alert(objects[i].position.x);
                    alert(objects[i].position.y);
                    alert(objects[i].position.z);
                }
            }

            function key_event( event ) {

                var unicode=event.keyCode? event.keyCode : event.charCode;
                //alert(unicode); // find the char code
                switch(unicode){
                    case 97:  rotateLeft(); break;
                    case 100: rotateRight(); break;
                    case 119: rotateUp(); break;
                    case 120: rotateDown(); break;
                    case 122: zoomIn(); break;
                    case 99:  zoomOut(); break;
                    case 115: showPositions(); break;
                }
                }


            function animate() {

                requestAnimationFrame( animate );

                render();
                stats.update();

            }

            function render() {

                camera.position.x = cameraX; // updating the camera view-x scale after events
                camera.position.y = cameraY; // updating the camera view-y scale after events
                camera.position.z = cameraZ; // updating the camera view-z scale after events
                camera.lookAt( scene.position );
                renderer.render( scene, camera );

            }

回答1:

I found pretty simple solution...but I guess that's the way it always works :-) All you have to do for the detection is 2 things: First of all add another variable: var thisObject; After that you have to go to the onMouseDown() function. Right after the SELECTED = intersects[0].object; you have to write this thing:

 for(var i=0; i<objects.length; i++)
    { 
       if(SELECTED.position.x == objects[i].position.x)
              thisObject = i; 
    }

...Now thisObject holds the index of the current shape (that was selected/dragged) in objects array...yeah that simple :-)