如何让我的文字标签始终面向相机?也许使用精灵?

时间:2013-04-14 16:14:30

标签: javascript three.js

我正在看两个例子,一个是画布交互式对象,另一个是鼠标工具提示。我尝试将两者结合起来在每个立方体上生成文本标签,这是我到目前为止所拥有的。

但是,文本随着旋转的立方体移动,文本有时会向后或侧向显示。

如何在鼠标工具提示(http://stemkoski.github.io/Three.js/Mouse-Tooltip.html)示例中的精灵中修复文本?我试图合并精灵,但我一直在收到错误。我不知道怎么做。你能解释一下我是怎么做到的吗?

感谢。

到目前为止,这是我的代码:

<!DOCTYPE html>
<html lang="en">
    <head>
            <title>three.js canvas - interactive - cubes</title>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
            <style>
                    body {
                            font-family: Monospace;
                            background-color: #f0f0f0;
                            margin: 0px;
                            overflow: hidden;
                    }
            </style>
    </head>
    <body>

            <script src="js/three.min.js"></script>

            <script src="js/stats.min.js"></script>

            <script>

                    var container, stats;
                    var camera, scene, projector, renderer;
                    var projector, mouse = { x: 0, y: 0 }, INTERSECTED;
                    var particleMaterial;
                    var currentLabel = null;

                    var objects = [];

                    init();
                    animate();

                    function init() {

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

                            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://threejs.org" target="_blank">three.js</a> - clickable objects';
                            container.appendChild( info );

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

                            scene = new THREE.Scene();

                            var geometry = new THREE.CubeGeometry( 100, 100, 100 );

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

                                    var object = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, opacity: 0.5 } ) );
                                    object.position.x = Math.random() * 800 - 400;
                                    object.position.y = Math.random() * 800 - 400;
                                    object.position.z = Math.random() * 800 - 400;

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

                                    object.rotation.x = Math.random() * 2 * Math.PI;
                                    object.rotation.y = Math.random() * 2 * Math.PI;
                                    object.rotation.z = Math.random() * 2 * Math.PI;

                                    object.label = "Object " + i;

                                    scene.add( object );

                                    objects.push( object );

                            }

                            var PI2 = Math.PI * 2;
                            particleMaterial = new THREE.ParticleCanvasMaterial( {

                                    color: 0x000000,
                                    program: function ( context ) {

                                            context.beginPath();
                                            context.arc( 0, 0, 1, 0, PI2, true );
                                            context.closePath();
                                            context.fill();

                                    }

                            } );

                            projector = new THREE.Projector();

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

                            container.appendChild( renderer.domElement );

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

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

                            //

                            window.addEventListener( 'resize', onWindowResize, false );

                    }

                    function onWindowResize() {

                            camera.aspect = window.innerWidth / window.innerHeight;
                            camera.updateProjectionMatrix();

                            renderer.setSize( window.innerWidth, window.innerHeight );

                    }

                    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 raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );

                            var intersects = raycaster.intersectObjects( objects );

                            if ( intersects.length > 0 ) {

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

                                             // restore previous intersection object (if it exists) to its original color
                                            if ( INTERSECTED ) {


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

                                            // store reference to closest object as current intersection object
                                            INTERSECTED = intersects[ 0 ].object;
                                            // store color of closest object (for later restoration)
                                            INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
                                            // set a new color for closest object
                                            INTERSECTED.material.color.setHex( 0xffff00 );

                                            var canvas1 = document.createElement('canvas');
                                            var context1 = canvas1.getContext('2d');
                                            context1.font = "Bold 40px Arial";
                                            context1.fillStyle = "rgba(255,0,0,0.95)";
                                            context1.fillText(INTERSECTED.label, 0, 50);

                                            // canvas contents will be used for a texture
                                            var texture1 = new THREE.Texture(canvas1) 
                                            texture1.needsUpdate = true;

                                            var material1 = new THREE.MeshBasicMaterial( {map: texture1, side:THREE.DoubleSide } );
                                            material1.transparent = true;

                                            var mesh1 = new THREE.Mesh(
                                            new THREE.PlaneGeometry(canvas1.width, canvas1.height),
                                            material1



                                    );
                                            mesh1.position = intersects[0].point;
                                            if (currentLabel)
                                                    scene.remove(currentLabel);
                                            scene.add( mesh1 );                             
                                            currentLabel = mesh1;
                            } 

                            else // there are no intersections
                                            {
                                    // restore previous intersection object (if it exists) to its original color
                                    if ( INTERSECTED ) {
                                            console.log("hello");
                                            INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
                                            }
                                            // remove previous intersection object reference
                                            //     by setting current intersection object to "nothing"
                                            INTERSECTED = null;
                                            mesh1 = null; 
                                            mesh1.position = intersects[0].point; 
                                            scene.add( mesh1 );

                                            }






                                    //var particle = new THREE.Particle( particleMaterial );
                                    //particle.position = intersects[ 0 ].point;
                                    //particle.scale.x = particle.scale.y = 8;
                                    //scene.add( particle );

                            }

                            /*
                            // Parse all the faces
                            for ( var i in intersects ) {

                                    intersects[ i ].face.material[ 0 ].color.setHex( Math.random() * 0xffffff | 0x80000000 );

                            }
                            */


                    }

                    //

                    function animate() {

                            requestAnimationFrame( animate );

                            render();
                            stats.update();

                    }

                    var radius = 600;
                    var theta = 0;

                    function render() {

                            theta += 0.1;

                            camera.position.x = radius * Math.sin( THREE.Math.degToRad( theta ) );
                            camera.position.y = radius * Math.sin( THREE.Math.degToRad( theta ) );
                            camera.position.z = radius * Math.cos( THREE.Math.degToRad( theta ) );
                            camera.lookAt( scene.position );

                            renderer.render( scene, camera );

                    }

            </script>

    </body>

1 个答案:

答案 0 :(得分:7)

Billboarding很容易。在您的情况下,您所要做的就是在渲染循环中添加它:

if ( currentLabel ) currentLabel.lookAt( camera.position );