Three.js的学习心得

这几天自己一直在瞎琢磨Three.js,发现它的强大,也发现她的不易。我就我自己根据一个Demo自己写的一个小Demo来讲讲Three.js吧。

Three.js初始化的时候需要一点东西的首先是渲染的,就是叫Renderer的东西,这个东西好像还蛮厉害的,我没有深究也没有研究源代码,就是自己的理解啦,我现在才学习了几天而已。接着就是Camera,Scene,Light,灯光和很多都是要加到场景里的,不然就不会显示的。下面是几个重要部件的初始化代码:

Camera:

            camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
            camera.position.x = 250;//设置相机的位置坐标
            camera.position.y = 250;//设置相机的位置坐标
            camera.position.z = 250;//设置相机的位置坐标
            camera.up.x = 0;//设置相机的上为「x」轴方向
            camera.up.y = 1;//设置相机的上为「y」轴方向
            camera.up.z = 0;//设置相机的上为「z」轴方向
Scene:

<span style="white-space:pre">	</span>    scene = new THREE.Scene();
Light:

<span style="white-space:pre">	</span>    light = new THREE.DirectionalLight(0xFFFFFF,1.0,0);//设置平行光DirectionalLight
            light.position.set(1,1,1);//光源向量,即光源的位置

定义完这些我们就可以在上面添加我们自己的东西啦,Three.js里面有很多图形,就我现在用到的有正方体,球形还有其他的东西,这些东西API上都有的,可以看看API的,去官网下源码,里面有文档有例子的。我是借用是Demo上一个3D模型来用的,那个模型实现的是模型通过键盘控制运动的。我自己将他改了改,变成了按鼠标右键进行控制的,当然是无障碍的啦。这个部分最重要的要用到Projector,这个东西有个方法能够获得相机发出的射线,在通过这个射线和与物体相交的地方就能够获得交点了。

 <span style="white-space:pre">	</span>    var vector = new THREE.Vector3(
                            ( event.clientX / window.innerWidth ) * 2 - 1,
                            - ( event.clientY / window.innerHeight ) * 2 + 1,
                    100 );
            //projector.unprojectVector( vector, camera );
            var ray = projector.pickingRay(vector, camera);
            var intersects = ray.intersectObject(plane); 

接着就是模型需要向着鼠标点击的方向,这个使用lookAt就可以了。下面是完整的源代码:Demo地址:http://wangxingyang.com.cn/htmls/testAndroid.html

原先的类似的Demo地址:http://wangxingyang.com.cn/htmls/3D.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>会动的机器人</title>
    <script src="../js/three.min.js" ></script>
    <script src="../js/OrbitControls.js"></script>
    <script src="../js/Stats.js"></script>
    <script src="../js/THREEx.KeyboardState.js"></script>
    <!--<script src="js/three.min.js" ></script>-->
    <!--<script src="js/OrbitControls.js"></script>-->
    <!--<script src="js/Stats.js"></script>-->
    <!--<script src="js/THREEx.KeyboardState.js"></script>-->
    <!--<script src="js/thumbs.0.6.0.min.js"></script>-->
    <script type="text/javascript">
        var renderer,
                stats,
                camera,
                controls,
                scene,
                light,
                projector,
                plane,
                nowplace;
        var android,
                animOffset       = 0,   // starting frame of animation
                walking         = false,
                duration        = 1000, // milliseconds to complete animation
                keyframes       = 20,   // total number of animation frames
                interpolation   = duration / keyframes, // milliseconds per frame
                lastKeyframe    = 0,    // previous keyframe
                currentKeyframe = 0;
        var keyboard = new THREEx.KeyboardState();
        var clock = new THREE.Clock();

        function testAndroid ()
        {
            var SCREEN_WIDTH = window.screen.availWidth-25, SCREEN_HEIGHT = window.screen.availHeight-80;
            var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;

            document.getElementById('canvas3d').clientWidth = SCREEN_WIDTH-100;//获取画布「canvas3d」的宽
            document.getElementById('canvas3d').clientHeight=SCREEN_HEIGHT;//获取画布「canvas3d」的高
            renderer=new THREE.WebGLRenderer({antialias:true});//生成渲染器对象(属性:抗锯齿效果为设置有效)
            renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT );//指定渲染器的高宽(和画布框大小一致)
            document.getElementById('canvas3d').appendChild(renderer.domElement);//追加 【canvas】 元素到 【canvas3d】 元素中。
            renderer.setClearColor(0xFFFFFF, 1.0);//设置canvas背景色(clearColor)
            /*添加状态显示*/
            stats = new Stats();
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            document.getElementById('canvas3d').appendChild(stats.domElement);
            /*添加摄像机*/
            camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
            controls = new THREE.OrbitControls(camera,renderer.domElement );
            //controls.addEventListener('change', updateControls );
            camera.position.x = 250;//设置相机的位置坐标
            camera.position.y = 250;//设置相机的位置坐标
            camera.position.z = 250;//设置相机的位置坐标
            camera.up.x = 0;//设置相机的上为「x」轴方向
            camera.up.y = 1;//设置相机的上为「y」轴方向
            camera.up.z = 0;//设置相机的上为「z」轴方向
            /*添加场景*/
            scene = new THREE.Scene();
            /*添加灯光*/
            light = new THREE.DirectionalLight(0xFFFFFF,1.0,0);//设置平行光DirectionalLight
            light.position.set(1,1,1);//光源向量,即光源的位置
            scene.add(light);// 追加光源到场景
            /*添加地面*/
            var geometry = new THREE.PlaneGeometry( 1000, 1000 );
            var material = new THREE.MeshBasicMaterial( {color: 0xff0000, side: THREE.DoubleSide} );
            plane = new THREE.Mesh( geometry, material );
            plane.rotation.x = 90*Math.PI/180;
            scene.add( plane );
            /*添加机器人*/
            var jsonLoader = new THREE.JSONLoader();
            jsonLoader.load( "../models/android-animations.js", addModelToScene );

            /*添加事件*/
            document.addEventListener( 'mousedown', onDocumentMouseDown, false );
            document.addEventListener( 'touchstart', onDocumentTouchStart, false );
            document.addEventListener( 'mousemove', onDocumentMouseMove, false );
            document.addEventListener( 'mouseup', onDocumentMouseUp, false );

            projector = new THREE.Projector();
            /*画面更新*/
            animate();
        };
        //鼠标按下事件
        function onDocumentMouseDown( event ) {
            //remember mouse postion
            var vector = new THREE.Vector3(
                            ( event.clientX / window.innerWidth ) * 2 - 1,
                            - ( event.clientY / window.innerHeight ) * 2 + 1,
                    100 );//使用projectpor转换
            //projector.unprojectVector( vector, camera );
            var ray = projector.pickingRay(vector, camera);//计算从相机发出的穿过近平面上mx my 点的射线
            var intersects = ray.intersectObject(plane); //计算射线和 平面的所有交点 0 或者 1个
            if(intersects.length > 0)
            {
                //存在交点
                if(event.button==2)//右键点击
                {
                    nowplace = intersects[0].point;
                    android.lookAt(nowplace);
                    console.log( 100 * delta);
                    walking =true;
                }
            }

        }
        //触摸事件
        function onDocumentTouchStart( event ) {
            //remember mouse postion
            var vector = new THREE.Vector3(
                            ( event.targetTouches[0].clientX / window.innerWidth ) * 2 - 1,
                            - ( event.targetTouches[0].clientY / window.innerHeight ) * 2 + 1,
                    100 );//使用projectpor转换
            //projector.unprojectVector( vector, camera );
            var ray = projector.pickingRay(vector, camera);//计算从相机发出的穿过近平面上mx my 点的射线
            var intersects = ray.intersectObject(plane); //计算射线和 平面的所有交点 0 或者 1个
            if(intersects.length > 0)
            {
                //存在交点
                nowplace = intersects[0].point;
                android.lookAt(nowplace);
                //console.log(nowplace.x+":"+nowplace.y+":"+nowplace.z);
                walking =true;
            }

        }
        //鼠标移动
        function onDocumentMouseMove( event ) {

        }
        //鼠标弹起
        function onDocumentMouseUp( event ) {

        }
        function addModelToScene( geometry, materials )
        {
            // for preparing animation
            for (var i = 0; i < materials.length; i++)
                materials[i].morphTargets = true;

            var material = new THREE.MeshFaceMaterial( materials );
            android = new THREE.Mesh( geometry, material );
            android.scale.set(5,5,5);
            android.position.set(0,0,0);
            scene.add( android );
        }
        function update() {
            // delta = change in time since last call (seconds)
            delta = clock.getDelta();
            var moveDistance = 100 * delta;
            //walking = false;

           if(android&&walking)
           {
               if(Math.floor(android.position.z) != Math.ceil(nowplace.z) && Math.floor(android.position.x) !=  Math.ceil(nowplace.x)) {
                   android.translateZ(moveDistance);
                   //console.log(Math.floor(android.position.z)+":"+nowplace.z);
               }else
               {
                   walking =false;
               }
           }

            controls.update();
            stats.update();
           // renderer.render(scene, camera);
        };
        function render()
        {
            if ( android&&walking ) // exists / is loaded
            {
                // Alternate morph targets
                time = new Date().getTime() % duration;
                keyframe = Math.floor( time / interpolation ) + animOffset;
                if ( keyframe != currentKeyframe )
                {
                    //console.log(currentKeyframe);
                    android.morphTargetInfluences[ lastKeyframe ] = 0;
                    android.morphTargetInfluences[ currentKeyframe ] = 1;
                    android.morphTargetInfluences[ keyframe ] = 0;
                    lastKeyframe = currentKeyframe;
                    currentKeyframe = keyframe;
                }
                android.morphTargetInfluences[ keyframe ] =
                        ( time % interpolation ) / interpolation;
                //console.log(( time % interpolation ) / interpolation);
                android.morphTargetInfluences[ lastKeyframe ] =
                        1 - android.morphTargetInfluences[ keyframe ];
            }

            renderer.render( scene, camera );
        };
        function animate()
        {
            requestAnimationFrame(animate);
            update();
            render();
        };
    </script>
</head>

<body οnlοad='testAndroid();'>
    <div style="text-align: center;position: absolute; left: 400px; font-weight: bold">研究了好几天才完成的,例子给的是用方向键完成转向和行走,自己想用鼠标右键实现行走,类似Dota的。今天终于完成了,虽然走了很多弯路,但是还是开心极了。--支持触屏</div>
    <div id="canvas3d"></div>
</body>
</html>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值