Three.js 3D 动画场景搭建
2018-01-19 14:41
1171 查看
最近看了一篇文章,用three.js写了一个很有趣的游戏场景,看了之后发现又想好好学一下three.js。
文章:https://tympanus.net/codrops/2016/04/26/the-aviator-animating-basic-3d-scene-threejs/?utm_source=tuicool
对整个流程介绍的很是详细。拜读了这篇文章之后,决定也用three.js搭建一个场景试一试,感觉很有趣的样子。很喜欢狐妖小红娘这个国漫,真的很好看的国漫,安利一下。就尝试一下狐妖小红娘里面的相思树吧,能力有限,先做得粗糙一点,作为练习吧!以后有时间了,再好好做一下。
搭建简单的场景,用到了three里面的两种基础几何形状。
CylinderGeometry 柱体类, 构造函数如下所示(
SphereGeometry 是球体类, 构造函数如下所示 (
尝试做一个简单的场景,图片如下:
用CylinderGeometry、SphereGeometry 创建花朵,以及基本的树枝。主要用到了旋转、缩放和平移。由于要注意创建的柱状体的组合,需要计算在x、y、z方向的平移位置。
先这样吧比较粗糙,作为自己的练习~~~~~~~
文章:https://tympanus.net/codrops/2016/04/26/the-aviator-animating-basic-3d-scene-threejs/?utm_source=tuicool
对整个流程介绍的很是详细。拜读了这篇文章之后,决定也用three.js搭建一个场景试一试,感觉很有趣的样子。很喜欢狐妖小红娘这个国漫,真的很好看的国漫,安利一下。就尝试一下狐妖小红娘里面的相思树吧,能力有限,先做得粗糙一点,作为练习吧!以后有时间了,再好好做一下。
搭建简单的场景,用到了three里面的两种基础几何形状。
CylinderGeometry 柱体类, 构造函数如下所示(
radiusTop与
radiusBottom分别是顶面和底面的半径,由此可知,当这两个参数设置为不同的值时,实际上创建的是一个圆台;
height是圆柱体的高度;
radiusSegments与
heightSegments可类比球体中的分段;
openEnded是一个布尔值,表示是否没有顶面和底面,缺省值为false,表示有顶面和底面);
THREE.CylinderGeometry(radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded)
SphereGeometry 是球体类, 构造函数如下所示 (
radius是半径;
segmentsWidth表示经度上的切片数;
segmentsHeight表示纬度上的切片数;
phiStart表示经度开始的弧度;
phiLength表示经度跨过的弧度;
thetaStart表示纬度开始的弧度;
thetaLength表示纬度跨过的弧度), 其中需要注意的是在使用时可以根据经纬度切片数来定制球形外形, 可以通过经纬度弧度来定制球形起始形状;
THREE.SphereGeometry(radius, segmentsWidth, segmentsHeight, phiStart, phiLength, thetaStart, thetaLength)
尝试做一个简单的场景,图片如下:
用CylinderGeometry、SphereGeometry 创建花朵,以及基本的树枝。主要用到了旋转、缩放和平移。由于要注意创建的柱状体的组合,需要计算在x、y、z方向的平移位置。
代码:
<!DOCTYPE html> <html lang=" 4000 en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="three.js"></script> <script type="text/javascript" src="OrbitControls.js"></script> <script type="text/javascript" src="CanvasRenderer.js"></script> <script type="text/javascript" src="Projector.js"></script> <style> #world { position: absolute; width: 100%; height: 100%; overflow: hidden; background: linear-gradient(#e4dcdc, #c0f2f7); } </style> </head> <body> <div id="world"></div> <script> //COLORS var Colors ={ white:'#f7fff3', flo1:'#e0c9e4', flo2:'#e4c4c0', flo3:'#e4a5a7', branch1:'#435516', branch2:'#55492c', blue:'#65f7e2', glass:'#95e9aa' }; // THREEJS RELATED VARIABLES var scene, camera, fieldOfView, aspectRatio, nearPlane, farPlane, renderer, container; //SCREEN & MOUSE VARIABLES var HEIGHT, WIDTH; //INIT THREE JS, SCREEN AND MOUSE EVENTS function createScene() { HEIGHT = window.innerHeight; WIDTH = window.innerWidth; scene = new THREE.Scene(); aspectRatio = WIDTH / HEIGHT; fieldOfView = 60; nearPlane = 1; farPlane = 10000; camera = new THREE.PerspectiveCamera( fieldOfView, aspectRatio, nearPlane, farPlane ); scene.fog = new THREE.Fog('#f7fff3', 100,950); camera.position.x = 0; camera.position.z = 200; camera.position.y = 100; renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true }); renderer.setSize(WIDTH, HEIGHT); renderer.shadowMap.enabled = true; container = document.getElementById('world'); container.appendChild(renderer.domElement); window.addEventListener('resize', handleWindowResize, false); } // HANDLE SCREEN EVENTS function handleWindowResize() { HEIGHT = window.innerHeight; WIDTH = window.innerWidth; renderer.setSize(WIDTH, HEIGHT); camera.aspect = WIDTH / HEIGHT; camera.updateProjectionMatrix(); } // LIGHTS var hemisphereLight, shadowLight; function createLights() { hemisphereLight = new THREE.HemisphereLight(0xaaaaaa,0x000000, .9); shadowLight = new THREE.DirectionalLight(0xffffff, .9); shadowLight.position.set(150, 350, 350); shadowLight.castShadow = true; shadowLight.shadow.camera.left = -400; shadowLight.shadow.camera.right = 400; shadowLight.shadow.camera.top = 400; shadowLight.shadow.camera.bottom = -400; shadowLight.shadow.camera.near = 1; shadowLight.shadow.camera.far = 1000; shadowLight.shadow.mapSize.width = 2048; shadowLight.shadow.mapSize.height = 2048; scene.add(hemisphereLight); scene.add(shadowLight); } function Land(){ var geom = new THREE.SphereGeometry(600,80,80); geom.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI/2)); var mat = new THREE.MeshPhongMaterial({ color:Colors.glass, transparent:true, opacity:0.8, shading:THREE.FlatShading }); this.mesh = new THREE.Mesh(geom, mat); this.mesh.receiveShadow = true; } function Tree(){ this.mesh = new THREE.Object3D(); // 树干 var trunk = new THREE.CylinderGeometry(25,40,120,60,3); var material1 = new THREE.MeshPhongMaterial({ color:Colors.branch2, shading:THREE.FlatShading, transparent:true, opacity:0.8 }); var trunkMesh = new THREE.Mesh(trunk, material1); trunkMesh.castShadow = true; trunkMesh.receiveShadow = true; this.mesh.add(trunkMesh); //顶部 var topB=new Branch(); topB.mesh.scale.set(2,2,2); topB.mesh.position.y = 80; this.mesh.add(topB.mesh); //中层 var len,moveX,moveY,moveZ,i; var numMiddele=6; var angleStepM=(Math.PI*2)/numMiddele; for(i=0;i<6;i++) { var mid=new Branch(); var sc0=2; mid.mesh.applyMatrix(new THREE.Matrix4().makeRotationZ(Math.PI/6)); mid.mesh.applyMatrix(new THREE.Matrix4().makeRotationY(angleStepM*i)); mid.mesh.scale.set(sc0,sc0,sc0); len=Math.cos(Math.PI/2-Math.PI/6)*sc0*14; moveX=-Math.cos(angleStepM*i)*len; moveY=85; moveZ=Math.sin(angleStepM*i)*len; mid.mesh.position.set(moveX,moveY,moveZ); // mid.mesh.position.y = 80; this.mesh.add(mid.mesh); } //底层 var numBottom=10; var angleStepB=(Math.PI*2)/numBottom; for(i=0;i<numBottom;i++) { var sc=2.5; var an=Math.PI/2-Math.PI/8*Math.random(); var bom=new Branch(); bom.mesh.applyMatrix(new THREE.Matrix4().makeRotationZ(an)); bom.mesh.applyMatrix(new THREE.Matrix4().makeRotationY(angleStepB*i)); bom.mesh.scale.set(sc,sc,sc); len=Math.cos(Math.PI/2-an)*sc*14; moveX=-Math.cos(angleStepB*i)*len; moveY=75; moveZ=Math.sin(angleStepB*i)*len; bom.mesh.position.set(moveX,moveY,moveZ); // mid.mesh.position.y = 80; this.mesh.add(bom.mesh); } } function Branch(){ this.mesh = new THREE.Object3D(); var trunk = new THREE.CylinderGeometry(1,2,28,12,1); var scrown = new THREE.SphereGeometry(20,6,5,0,Math.PI*2,0,Math.PI/3); var scale=[1.3,0.7,0.4]; var rotate=[0,Math.PI/6,-Math.PI/4]; var translation=[[0,0,0],[-6,-3,0],[4,-4,0]]; var Ele=[]; for (var i=1; i<=3; i++ ){ var s=scale[i-1]; var ro=rotate[i-1]; var trans=translation[i-1]; var crownMat = new THREE.MeshPhongMaterial({color:Colors['flo'+i], shading:THREE.FlatShading, transparent:true, opacity:0.8}); var trunkMat = new THREE.MeshPhongMaterial({color:Colors.branch1, shading:THREE.FlatShading,transparent:true, opacity:0.6}); var m1 = new THREE.Mesh(trunk.clone(), trunkMat); m1.castShadow = true; m1.receiveShadow = true; var m2 = new THREE.Mesh(scrown.clone(), crownMat); m2.position.set(0,10-Math.cos(Math.PI/3)*20,0); m2.castShadow = true; m2.receiveShadow = true; m1.add(m2); //先旋转 再缩放 再平移 m1.applyMatrix(new THREE.Matrix4().makeRotationZ(ro)); m1.scale.set(s,s,s); m1.position.set(trans[0],trans[1],trans[2]); this.mesh.add(m1); } } function MuitiFlo(){ this.mesh = new THREE.Object3D(); this.nFlowers = 50; var stepAngle = Math.PI*2 / this.nFlowers; for(var i=0; i<this.nFlowers; i++){ var c = new Flower(); var a = stepAngle*i; var h = 650 + Math.random()*200; c.mesh.position.y = Math.sin(a)*h; c.mesh.position.x = Math.cos(a)*h; c.mesh.position.z = -100-Math.random()*100; c.mesh.rotation.z = a - Math.PI/2; var s = 0.2+Math.random()*0.2; c.mesh.scale.set(s,s,s); this.mesh.add(c.mesh); } } //花朵 function Flower() { this.mesh = new THREE.Object3D(); var trunk = new THREE.CylinderGeometry(1, 2, 16); var petal=new THREE.CylinderGeometry(1, 1, 14); var trunkmat = new THREE.MeshPhongMaterial({color: Colors.branch1, shading: THREE.FlatShading}); var trunkpetal = new THREE.MeshPhongMaterial({color: Colors.flo2, shading: THREE.FlatShading}); var trunkpetal1 = new THREE.MeshPhongMaterial({color: Colors.flo3, shading: THREE.FlatShading}); var tmesh = new THREE.Mesh(trunk, trunkmat); tmesh.castShadow = true; tmesh.receiveShadow = true; this.mesh.add(tmesh); var angleIndex=(Math.PI*2)/12; var len,moveX,moveY,moveZ,i; for (i = 0; i <12; i++) { var m = new THREE.Mesh(petal, trunkpetal); m.castShadow = true; m.receiveShadow = true; m.applyMatrix(new THREE.Matrix4().makeRotationZ(Math.PI/3)); m.applyMatrix(new THREE.Matrix4().makeRotationY(angleIndex*i)); len=Math.cos(Math.PI/6)*7; moveX=-Math.cos(angleIndex*i)*len; moveY=8; moveZ=Math.sin(angleIndex*i)*len; m.position.set(moveX,moveY,moveZ); this.mesh.add(m); } angleIndex=(Math.PI*2)/8; for (i = 0; i <8; i++) { var m1 = new THREE.Mesh(petal, trunkpetal1); m1.castShadow = true; m1.receiveShadow = true; m1.applyMatrix(new THREE.Matrix4().makeRotationZ(Math.PI/6)); m1.applyMatrix(new THREE.Matrix4().makeRotationY(angleIndex*i)); len=Math.cos(Math.PI/3)*7; moveX=-Math.cos(angleIndex*i)*len; moveY=8; moveZ=Math.sin(angleIndex*i)*len; m1.position.set(moveX,moveY,moveZ); this.mesh.add(m1); } } var land,tree,flos; function init(event){ document.addEventListener('mousemove', handleMouseMove, false); //创建场景 createScene(); //创建光线 createLights(); land = new Land(); land.mesh.position.y = -550; land.mesh.position.x = 80; land.mesh.position.z = -50; scene.add(land.mesh); tree=new Tree(); tree.mesh.position.y = 50; tree.mesh.position.x = 80; scene.add(tree.mesh); //添加花朵 flos = new MuitiFlo(); flos.mesh.position.y = -550; scene.add(flos.mesh); loop(); } //LOOP function loop(){ renderer.render(scene, camera); flos.mesh.rotation.z += .002; tree.mesh.rotation.y+=0.001; requestAnimationFrame(loop); } // HANDLE MOUSE EVENTS var mousePos = { x: 0, y: 0 }; function handleMouseMove(event) { var tx = -1 + (event.clientX / WIDTH)*2; var ty = 1 - (event.clientY / HEIGHT)*2; mousePos = {x:tx, y:ty}; } window.addEventListener('load', init, false); </script> </body> </html>
截图:
基础对象:
先这样吧比较粗糙,作为自己的练习~~~~~~~
相关文章推荐
- three.js模型搭建与地图的3D可视化参考资源
- 使用WebGL + Three.js制作动画场景
- 初学WebGL,使用Three.js开发第一个3d场景示例
- 如何用webgl(three.js)搭建一个3D库房
- 如何用webgl(three.js)搭建一个3D库房
- 如何用webgl(three.js)搭建一个3D库房
- Three-js 创建第一个3D场景
- 第一章 用three.js创建你的第一个3D场景
- 如何用webgl(three.js)搭建一个3D库房
- 如何用webgl(three.js)搭建一个3D库房
- 如何用webgl(three.js)搭建一个3D库房
- 【H5 3D应用开发】 Three.js 播放json模型动画并切换动画(一)
- 如何用webgl(three.js)搭建一个3D库房
- 如何用webgl(three.js)搭建一个3D库房
- 如何用webgl(three.js)搭建一个3D库房
- three.js自学之旅(2)—— 搭建第一个简单的场景
- 如何用webgl(three.js)搭建一个3D库房
- 在Three.js中重新设置3D模型的中心点
- 使用three.js加载3dmax资源,以及实现场景中的阴影效果
- three.js实现3D模型展示的示例代码