如何在Three.js中定位精灵?

时间:2015-07-06 22:49:38

标签: javascript three.js

我目前正在使用PointCloud生成一个粒子系统但在其中我想要一个浮在我指示位置的精灵。当我尝试使用这个three.js示例时:http://threejs.org/examples/#webgl_sprites我发现正交相机限制了我仍然能够放大的能力。

        var container, stats;
        var camera, scene, renderer, particles, geometry, materials =[], i, h, color, sprite, size;
        var mouseX = 0, mouseY = 0;

        var windowHalfX = window.innerWidth / 2;
        var windowHalfY = window.innerHeight / 2;

        init();
        animate();

        function init() {

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

            camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 2, 2000 );
            camera.position.z = 1000;

            scene = new THREE.Scene();
            scene.fog = new THREE.FogExp2( 0x000000, 0.001 );

            geometry = new THREE.Geometry();

            sprite = THREE.ImageUtils.loadTexture( "disc.png" );


            for ( i = 0; i < 5000; i ++ ) {

                var vertex = new THREE.Vector3();
                vertex.x = 2000 * Math.random() - 1000;
                vertex.y = 2000 * Math.random() - 1000;
                vertex.z = 2000 * Math.random() - 1000;

                geometry.vertices.push( vertex );

            }

            // size = Math.random() * 10;

            material = new THREE.PointCloudMaterial( { size: 5, sizeAttenuation: false, map: sprite, alphaTest: 0.5, transparent: true } );

            particles = new THREE.PointCloud( geometry, material );
            scene.add( particles );

            var map2 = THREE.ImageUtils.loadTexture( "astronaut.png" );
            var material2 = new THREE.SpriteMaterial( { map: map2, color: 0xffffff, fog: true } );
            var sprite2 = new THREE.Sprite( material2 );
            sprite2.position.x = 0;
            sprite2.position.y = 0;
            sprite2.position.z = 498;
            scene.add( sprite2 );


            //

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

            //

            document.addEventListener( 'mousemove', onDocumentMouseMove, false );
            document.addEventListener( 'touchstart', onDocumentTouchStart, false );
            document.addEventListener( 'touchmove', onDocumentTouchMove, false );

            //

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

        }

        function onWindowResize() {

            windowHalfX = window.innerWidth / 2;
            windowHalfY = window.innerHeight / 2;

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

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

        }

        function onDocumentMouseMove( event ) {

            mouseX = event.clientX - windowHalfX;
            mouseY = event.clientY - windowHalfY;

        }

        function onDocumentTouchStart( event ) {

            if ( event.touches.length == 1 ) {

                event.preventDefault();

                mouseX = event.touches[ 0 ].pageX - windowHalfX;
                mouseY = event.touches[ 0 ].pageY - windowHalfY;

            }
        }

        function onDocumentTouchMove( event ) {

            if ( event.touches.length == 1 ) {

                event.preventDefault();

                mouseX = event.touches[ 0 ].pageX - windowHalfX;
                mouseY = event.touches[ 0 ].pageY - windowHalfY;

            }

        }

        //

        function animate() {

            requestAnimationFrame( animate );

            render();


        }

        function render() {

            var time = Date.now() * 0.00005;

            camera.position.x += ( mouseX - camera.position.x ) * 0.05;
            camera.position.y += ( - mouseY - camera.position.y ) * 0.05;

            camera.lookAt( scene.position );

            h = ( 360 * ( 1.0 + time ) % 360 ) / 360;

            renderer.render( scene, camera );

        }

我尝试解决这个问题的原因是:

var map2 = THREE.ImageUtils.loadTexture( "astronaut.png" );
var material2 = new THREE.SpriteMaterial( { map: map2, color: 0xffffff, fog: true } );
var sprite2 = new THREE.Sprite( material2 );
sprite2.position.x = 0;
sprite2.position.y = 0;
sprite2.position.z = 498;
scene.add( sprite2 );

现在,当我第一次加载时,精灵位于屏幕的中央,但是当我开始移动相机时它会立即消失。理想情况下,我希望astronaut.png精灵与其他粒子一起移动,但如果这很难,让他总是固定在屏幕的中心也可以正常工作。

2 个答案:

答案 0 :(得分:1)

我自己解决了这个问题。我创建了第二个THREE.Geometry和THREE.Vector3,用顶点定位它。

geometry2 = new THREE.Geometry();
var vertex2 = new THREE.Vector3(0, 0, -50);

geometry2.vertices.push( vertex2 );

var material2 = new THREE.PointCloudMaterial( { size: 100, sizeAttenuation: false, map: map2, alphaTest: 0.5, transparent: true } );

particles2 = new THREE.PointCloud( geometry2, material2 );
scene.add( particles2 );

答案 1 :(得分:1)

在我看来,鼠标位置的值对于相机位置来说太高了。 OpenGL以(-1,1)(1,1)(1,-1)( - 1,-1)边界矩形为单位。光标位置的像素在屏幕像素中,如350,720等。

当你增加一半距离时,你的数字仍然太大。所以在这里你必须除以你的宽度/高度:

            camera.position.x += ( mouseX / window.innerWidth- camera.position.x ) * 0.05;
            camera.position.y += ( - mouseY /window.innerHeight- camera.position.y ) * 0.05;

假设您的GL门户与窗口大小相同。