three.jsmeshplaneline-intersection

Three.js mouseover mesh with ray intersection, no reaction


I'm trying to set up a website that runs in a single WebGL element. I'm trying to get it to tell when the mouse is over an object. I'm using a couple of planes with a with transparent textures on them as links, but it won't pick up on any intersections at all. It does absolutely nothing. I've even added a cube and used the same code as the interactive cubes example (http://mrdoob.github.com/three.js/examples/webgl_interactive_cubes.html) and it does absolutely nothing. No changing the color, absolutely nothing. I've gone through and tried about 8 different examples online having to do with this and not a single one has worked for me.

Here is my code:

    <meta charset="utf-8">

    <style type="text/css">
        body {
            margin: 0px;
            overflow: hidden;
            background: #000000;
        }
        div {
            margin: 0px;
        }
    </style>

    </head>
    <div>
        <script src="http://www.html5canvastutorials.com/libraries/Three.js"></script>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
        <script type="text/javascript">

            //Variable Declarations
            var camera, scene, renderer, aspect, projector;
            var INTERSECTED;
            var mouseX = 0, mouseY = 0;

            init();

            //Method Declarations
            function init() {
                aspect = window.innerWidth / window.innerHeight;
                //aspect = 1.25;
                //Sets the camera variable to a new Perspective Camera with a field of view of 45 degrees, an aspect ratio
                //of the window width divided by the window height, the near culling distance of 1 and the far culling distance of 2000
                camera = new THREE.PerspectiveCamera(45, aspect, 1, 2000);

                //Sets the height of the camera to 400
                camera.position.z = 700;

                //Sets a variable "lookat" to a new 3d vector with a position of 0, 0, 0, 
                //or the center of the scene/center of the menu plane
                var lookat = new THREE.Vector3(0, 0, 0);

                //Uses a function built in to every camera object to make it look at a given coordinate
                camera.lookAt(lookat);

                //Makes a new scene object to add everything to
                scene = new THREE.Scene();

                //Adds the camera object to the scene
                scene.add(camera);

                //Sets the renderer varialbe to a new WebGL renderer object
                //Change "WebGLRenderer" to "CanvasRenderer" to use canvas renderer instead
                renderer = new THREE.WebGLRenderer({antialias:true});
                //renderer.sortObjects = false;

                //Sets the size of the renderer object to the size of the browser's window
                //renderer.setSize(window.innerWidth, window.innerHeight);
                renderer.setSize(window.innerWidth, window.innerHeight);

                //Adds an event listener to the webpage that "listens" for mouse movements and when the mouse does move, it runs the 
                //"onMouseMove" function
                document.addEventListener('mousemove', onMouseMove, false);

                //Force canvas to stay proportional to window size
                window.addEventListener('resize', onWindowResize, false);

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

                //Sets the update frequency of the webpage in milliseconds
                setInterval(update, 1000/60);


                //Makes a variable "texture" and sets it to the returned value of the method "loadTexture" 
                //supplied by the THREE.js library
                var texture = THREE.ImageUtils.loadTexture('imgs/backgrounds.png');

                //Makes a variable "geometry" and sets it to a "PlaneGeometry" object with a width of 645 and a height of 300
                var geometry = new THREE.PlaneGeometry(645, 300);

                //Makes a variable "material" and sets it to a "MeshBasicMaterial" object with it's map set to
                //the "texture" object, it also makes it transparent
                var material = new THREE.MeshBasicMaterial({map: texture, transparent: true});

                //Makes a variable "plane" and sets it to a "Mesh" object with its geometry set to the "geometry" object
                //and it's material set to the "material" object
                var plane = new THREE.Mesh(geometry, material);


                //Background Texture
                var backgroundTexture = THREE.ImageUtils.loadTexture('imgs/gears.png');
                var backgroundGeo = new THREE.PlaneGeometry(3500, 2500);
                var backgroundMat = new THREE.MeshBasicMaterial({map: backgroundTexture});
                var backgroundPlane = new THREE.Mesh(backgroundGeo, backgroundMat);
                backgroundPlane.position.z = -1000;
                backgroundPlane.overdraw = true;


                //Home Button
                //Makes a "homeTexture" variable and sets it to the returned value of the makeTextTexture function when 
                //the text passed in is set to "Home", the width is set to 300, height of 150, font set to 80pt Arial, 
                //fillStyle set to white, textAlign set to center, textBaseLine set to middle, and the color of the 
                //background set to red = 0, green = 0, blue = 0 and alpha = 0
                var homeTexture = makeTextTexture("Home", 300, 150, '80pt Arial', 'white', "center", "middle", "rgba(0,0,0,0)");
                var homeGeom = new THREE.PlaneGeometry(50, 25);
                var homeMaterial = new THREE.MeshBasicMaterial({map: homeTexture, transparent: true});
                var homeTest = new THREE.Mesh(homeGeom, homeMaterial);
                homeTest.position.x -= 270;
                homeTest.position.y += 120;
                homeTest.position.z = 40;
                homeTest.castShadow = true;

                //Gallery Button
                var galleryTexture = makeTextTexture("Gallery", 340, 150, '80pt Arial', 'white', "center", "middle", "rgba(0,0,0,0)");
                var galleryGeom = new THREE.PlaneGeometry(50, 25);
                var galleryMaterial = new THREE.MeshBasicMaterial({map: galleryTexture, transparent: true});
                var galleryTest = new THREE.Mesh(galleryGeom, galleryMaterial);
                galleryTest.position.x -= 270; 
                galleryTest.position.y += 90;
                galleryTest.position.z = 40;
                galleryTest.castShadow = true;


                //The Team Button
                var theTeamTexture = makeTextTexture("Company", 510, 150, '80pt Arial', 'white', "center", "middle", "rgba(0,0,0,0)");
                var theTeamGeom = new THREE.PlaneGeometry(80, 25);
                var theTeamMaterial = new THREE.MeshBasicMaterial({map: theTeamTexture, transparent: true});
                var theTeamTest = new THREE.Mesh(theTeamGeom, theTeamMaterial);
                theTeamTest.position.x -= 260; 
                theTeamTest.position.y += 60;
                theTeamTest.position.z = 40;
                theTeamTest.castShadow = true;

                projector = new THREE.Projector();

                var cubeGeom = new THREE.CubeGeometry(20, 20, 20);
                var cubeMat = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
                var cubeMesh = new THREE.Mesh(cubeGeom, cubeMat);
                cubeMesh.position.z = 15;

                //scene.add(cubeMesh);

                //Adds all of the previously created objects to the scene
                scene.add(plane);
                scene.add(backgroundPlane);
                scene.add(homeTest);
                scene.add(theTeamTest);
                scene.add(galleryTest);

                //Adds the renderer to the webpage
                document.body.appendChild(renderer.domElement);
            }

            function update() {
                camera.position.x = (mouseX - (window.innerWidth / 2)) * 0.1;

                camera.position.y = -((mouseY - (window.innerHeight / 2)) * 0.15);
                camera.lookAt(new THREE.Vector3(0, 0, 0));

                render();
            }

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

            function onMouseMove(event) {
                mouseX = event.clientX;
                mouseY = event.clientY;
            }

            function onDocumentMouseDown(event) {
                event.preventDefault();

                var vector = new THREE.Vector3(
                    ( event.clientX / window.innerWidth ) * 2 - 1,
                  - ( event.clientY / window.innerHeight ) * 2 + 1,
                    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 ) {

                    intersects[ 0 ].object.materials[ 0 ].color.setHex( Math.random() * 0xffffff );
                }

            }

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

            function makeTextTexture(text, width, height, font, fillStyle, textAlign, textBaseline, backgroundColor)
            {
                //Makes a new canvas element
                var bitmap = document.createElement('canvas');

                //Gets its 2d css element
                var g = bitmap.getContext('2d');

                //Sets it's width and height
                bitmap.width = width;
                bitmap.height = height;

                //Takes "g", it's 2d css context and set's all of the following
                g.font = font;

                g.fillStyle = backgroundColor;
                g.fillRect(0, 0, width, height);

                g.textAlign = "center";
                g.textBaseline = "middle";
                g.fillStyle = fillStyle;
                g.fillText(text, width / 2, height / 2);

                //Rendered the contents of the canvas to a texture and then returns it
                var texture = new THREE.Texture(bitmap);
                texture.needsUpdate = true;

                return texture;
            }


        </script>
    </div>
</html>

Thanks to anyone that can help out. I wish I could figure out what's going on myself, it seems like I'm using StackOverflow to answer my questions way too much.


Solution

  • You have not declared the variable objects. Do this:

    var objects = [];
    

    Then populate it:

    objects.push( plane );
    objects.push( backgroundPlane );
    

    Now, this line will work:

    var intersects = ray.intersectObjects( objects );