threejs学习1 绘制一个旋转的门

最近在学习threejs,是一个基于webgl的三维库

web前端开发人员可以直接用webgl 接口进行编程,但webgl只是非常基础的绘图API,需要编程人员有很多的数学知识、绘图知识才能完成3D编程任务,而且代码量巨大。threejs 对webgl进行了封装,让前端开发人员在不需要掌握很多数学知识和绘图知识的情况下,也能够轻松进行web 3D开发,降低了门槛,同时大大提升了效率。

想用threejs 实现一个旋转的门效果,效果如下:

涉及到的知识点有 纹理贴图、对象沿轴旋转、灯光渲染、摄像机运动等

1.准备threejs文件

three.js复制到该HTML文件所在的目录下的js/目录下

2.跨域问题

因为代码中涉及到加载本地图像,会遇到浏览器禁止跨域加载的问题。解决方法可以参考下面这篇教程。

3.threejs 纹理

下面博客是对threejs中不同纹理使用方式的介绍,比较详细:

宫本勇次:关于Three.js-网格材质种类总结

我们可以通过MeshLambertMaterial 实现对一个扁平的长方体贴上门的纹理图像,并实现光漫反射的效果,其中map参数可以加载图像,用于将图像纹理贴在几何体上面,可以参考 http://www.linhongxu.com/post/view?id=222

4.threejs动画

threejs 很容易绘制一个 我们得到了一个静态的点、线、面,那么如果想让它动起来该怎么操作呢?

js 提供了requestAnimationFrame 这个函数,用法可以参考下面这个博客介绍

大概方案如下。

function draw(){ //`绘制代码 requestAnimationFrame(draw);//递归调用,实现循环绘制 //参数变化 }

通过 requestAnimationFrame 递归调用draw函数 实现循环绘制。

5.门沿着边沿旋转

three js 可以方便的对目标进行旋转,例如door是一个长方体,想让它在y轴方向旋转,那么只要在draw函数中,改变door.rotation.y的值就可以了,例如下面就表示每一帧沿着y轴 旋转0.01弧度

function draw(){ //`绘制代码 door.rotation.y += 0.01;//沿着y轴旋转0.01弧度 renderer.render( scene, camera );//绘制 requestAnimationFrame(draw);//递归调用,实现循环绘制 //参数变化 }

但是这样的旋转只能是目标沿着它的 y方向中心轴旋转,门一般都是沿着边沿旋转,所以直接旋转行不通(如下图所示)

解决方案如这个博客,把待旋转目标外面套一个父对象(Group),通过旋转父对象来实现。虽然父对象旋转依然是按照中心轴来旋转,但是如果待旋转目标 刚好占据父对象一半大小,那么父对象沿着中心轴来旋转,待旋转目标就能沿着边沿旋转。参考:three.js 对象绕任意轴旋转–模拟门转动

6.摄像机运动

如果想在门动的同时加入摄像机运动,可以在requestAnimationFrame 函数中,动态设置摄像机位置,例如下面代码中就通过三角函数值实现摄像机围绕目标实现

var cam_R = 50;//摄像机旋转半径 var theta = 0.01;//弧度值 function draw(){ //`绘制代码 camera.position.set( cam_R*Math.cos(theta), cam_R*Math.sin(theta), cam_R*Math.sin(theta) ); theta += 0.01; renderer.render( scene, camera );//绘制 requestAnimationFrame(draw);//递归调用,实现循环绘制 //参数变化 }

完整 html 代码如下:

<!DOCTYPE html> <html> </style> <head> <meta charset=utf8> <title>My first three.js app</title> <style> body { margin: 0; } canvas { width: 100%; height: 100% } #info { position: absolute; top: px; width: 100%; textalign: center; zindex: 100; display:block; } </style> </head> <body> <script src=“./js/three.js”></script> <script> // Our Javascript will go here. var scene = new THREE.Scene(); // var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.set( 0, 0, 50 ); camera.lookAt( 0, 0, 0 ); var renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); // 创建门 const door = new THREE.BoxBufferGeometry(10, 20, 0.5); // const doorMaterial = new THREE.MeshLambertMaterial({ color: 0xd88c00 , side: THREE.DoubleSide}); var materials = [ new THREE.MeshLambertMaterial( { map:new THREE.TextureLoader().load(“door.png”) } ), // right new THREE.MeshLambertMaterial( { map:new THREE.TextureLoader().load(“door.png”) } ), // left new THREE.MeshLambertMaterial( { map:new THREE.TextureLoader().load(“door.png”) } ), // top new THREE.MeshLambertMaterial( { map:new THREE.TextureLoader().load(“door.png”) } ), // bottom new THREE.MeshLambertMaterial( { map:new THREE.TextureLoader().load(“door.png”) } ), // front new THREE.MeshLambertMaterial( { map:new THREE.TextureLoader().load(“door.png”) } ), // back ]; var cubeSidesMaterial = new THREE.MultiMaterial( materials ); const doorMesh = new THREE.Mesh(door, cubeSidesMaterial); // 实现门围绕特定轴旋转 const group = new THREE.Group(); // 外层对象 group.position.set(5, 10, 0); // 设置外层对象的中心为原本想要旋转的位置 group.add(doorMesh); // 把门添加进外层对象中 doorMesh.position.set(5, 0, 0); // 调整门在外层对象中的相对位置 scene.add( doorMesh ); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap //Create a PointLight and turn on shadows for the light var light = new THREE.PointLight( 0xffffff, 1, 200 ); light.position.set( 20, 20, 0 ); light.castShadow = true; // default false scene.add( light ); //Set up shadow properties for the light light.shadow.mapSize.width = 512; // default light.shadow.mapSize.height = 512; // default light.shadow.camera.near = 1; // default light.shadow.camera.far = 30 // default //Create a helper for the shadow camera (optional) var helper = new THREE.CameraHelper( light.shadow.camera ); scene.add( helper ); renderer.setClearColor(0xb9d3ff,1);//设置背景颜色 renderer.render( scene, camera ); var cam_R = 50; var theta = 0.01; var animate = function () { requestAnimationFrame( animate ); camera.position.set( cam_R*Math.cos(theta), cam_R*Math.sin(theta), cam_R*Math.sin(theta) ); camera.lookAt( 0, 0, 0 ); theta += 0.01; doorMesh.rotation.y += 0.01; renderer.render( scene, camera ); }; animate(); </script> </body> </html>

    THE END
    喜欢就支持一下吧
    点赞12 分享
    评论 抢沙发
    头像
    欢迎您留下宝贵的见解!
    提交
    头像

    昵称

    取消
    昵称表情代码图片

      暂无评论内容