Three.js的学习心得
2014-09-12 09:42
609 查看
这几天自己一直在瞎琢磨Three.js,发现它的强大,也发现她的不易。我就我自己根据一个Demo自己写的一个小Demo来讲讲Three.js吧。
Three.js初始化的时候需要一点东西的首先是渲染的,就是叫Renderer的东西,这个东西好像还蛮厉害的,我没有深究也没有研究源代码,就是自己的理解啦,我现在才学习了几天而已。接着就是Camera,Scene,Light,灯光和很多都是要加到场景里的,不然就不会显示的。下面是几个重要部件的初始化代码:
Camera:
定义完这些我们就可以在上面添加我们自己的东西啦,Three.js里面有很多图形,就我现在用到的有正方体,球形还有其他的东西,这些东西API上都有的,可以看看API的,去官网下源码,里面有文档有例子的。我是借用是Demo上一个3D模型来用的,那个模型实现的是模型通过键盘控制运动的。我自己将他改了改,变成了按鼠标右键进行控制的,当然是无障碍的啦。这个部分最重要的要用到Projector,这个东西有个方法能够获得相机发出的射线,在通过这个射线和与物体相交的地方就能够获得交点了。
接着就是模型需要向着鼠标点击的方向,这个使用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', onDoc
4000
umentMouseUp, 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 onload='testAndroid();'>
<div style="text-align: center;position: absolute; left: 400px; font-weight: bold">研究了好几天才完成的,例子给的是用方向键完成转向和行走,自己想用鼠标右键实现行走,类似Dota的。今天终于完成了,虽然走了很多弯路,但是还是开心极了。--支持触屏</div>
<div id="canvas3d"></div>
</body>
</html>
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', onDoc
4000
umentMouseUp, 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 onload='testAndroid();'>
<div style="text-align: center;position: absolute; left: 400px; font-weight: bold">研究了好几天才完成的,例子给的是用方向键完成转向和行走,自己想用鼠标右键实现行走,类似Dota的。今天终于完成了,虽然走了很多弯路,但是还是开心极了。--支持触屏</div>
<div id="canvas3d"></div>
</body>
</html>
相关文章推荐
- JS语言核心学习心得
- 如何学习Three.JS 3D引擎
- three.js学习点滴(1) — 创建场景
- three.js学习 函数使用方法散记2
- Three.JS-学习 The WebGL earth (2)---globe.js分析
- 有志于webgl, three.js编程的朋友进入群52391108,72579998,共同学习提高,本人提供学习相关的资料,webgl,three.js学习,交流的论坛www.webglchina.cn
- Three.js学习记录--html5的编辑和第一个场景
- three.js学习点滴0
- 每日学习心得:Js基本数据类型常用方法扩展
- three.js学习 函数使用方法散记4
- THREE.js 学习笔记(前记)
- HTML5 - Three.js 3D特效学习
- three.js学习
- three.js学习点滴(2)— 模型导入
- 如何学习Three.JS 3D引擎
- js事件的学习心得
- three.js学习
- 每日学习心得:Js获取Checkboxlist所选值、instanceof 和typeof区别、为Array添加contains方法
- three.js学习 函数使用方法散记
- 学习js的一点心得——js对table的修饰