Three.js使用对象组合的实现案例代码
程序员文章站
2023-11-25 12:48:46
简介
将多个模型放到一个组里面,就是一个对象组合。
创建组非常简单,每个你创建的网格都可以包含子元素,子元素可以使用add函数来添加。在组中添加子元素的效果是:你可以移动、缩放...
简介
将多个模型放到一个组里面,就是一个对象组合。
创建组非常简单,每个你创建的网格都可以包含子元素,子元素可以使用add函数来添加。在组中添加子元素的效果是:你可以移动、缩放、旋转和变形父对象,而所有的子对象都将会受到影响。
点击勾选右上角的rotate会发现模型进行自转,球形效果看不出来。如果,再勾选grouping选项,会发现两个模型不再自转,而是围绕中间的辅助坐标进行旋转。
对象组合的实现
对象组合很好实现,首先创建一个three.object3d的类的对象。这是three.mesh和three.scene的基类,但是它本身不包含任何东西,也不会渲染任何东西。请注意,在three.js的最新版本中引入了一个名为three.group的新对象以支持分组。该对象与three.object3d对象完全相同,它两个可以互换。
var group = new three.object3d(); //实例化一个three.object3d对象 group.add(sphere); //在对象里面添加第一个子元素 group.add(cube); //在对象里面添加第二个子元素 scene.add(group); //将对象组添加到场景当中
代码如上,我们就实现了一个场景组。
注意:你旋转一个组时,并不是分别旋转组中的每一个对象,而是绕其中心旋转整个组(在我们的例子里,是绕着group对象的中心旋转整个组)。
使用组的时候,你依然可以引用、修改和定位每一个单独的几何体。唯一需要记住的是:所有的定位、旋转和变形都是相对父对象的。
案例代码
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>title</title> <style type="text/css"> html, body { margin: 0; height: 100%; } canvas { display: block; } </style> </head> <body onload="draw();"> </body> <script src="/lib/three.js"></script> <script src="/lib/js/controls/orbitcontrols.js"></script> <script src="/lib/js/libs/stats.min.js"></script> <script src="/lib/js/libs/dat.gui.min.js"></script> <script> var renderer; function initrender() { renderer = new three.webglrenderer({antialias:true}); renderer.setsize(window.innerwidth, window.innerheight); //告诉渲染器需要阴影效果 renderer.shadowmap.enabled = true; renderer.shadowmap.type = three.pcfsoftshadowmap; // 默认的是,没有设置的这个清晰 three.pcfshadowmap document.body.appendchild(renderer.domelement); } var camera; function initcamera() { camera = new three.perspectivecamera(45, window.innerwidth/window.innerheight, 0.1, 1000); camera.position.set(0, 40, 50); camera.lookat(new three.vector3(0,0,0)); } var scene; function initscene() { scene = new three.scene(); } //初始化dat.gui简化试验流程 var gui; function initgui() { //声明一个保存需求修改的相关数据的对象 gui = { spherex:-5, //球的x轴的位置 spherey:5, //球的y轴的位置 spherez:0, //球的z轴的位置 spherescale:1, //球的缩放 cubex:15, //立方体的x轴位置 cubey:5, //立方体的y轴位置 cubez:-5, //立方体的z轴的位置 cubescale:1, //立方体的缩放 groupx:0, //模型组的x轴位置 groupy:0, //模型组的y轴位置 groupz:0, //模型组的z轴的位置 groupscale:1, //模型组的缩放 grouping:false, //是否整个模型组旋转 rotate:false, //是否旋转 }; var datgui = new dat.gui(); //将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值) //球型的操作 var spherefolder = datgui.addfolder("sphere"); spherefolder.add(gui,"spherex",-30,30).onchange(function (e) { sphere.position.x = e; }); spherefolder.add(gui,"spherey",-30,30).onchange(function (e) { sphere.position.y = e; }); spherefolder.add(gui,"spherez",-30,30).onchange(function (e) { sphere.position.z = e; }); spherefolder.add(gui,"spherescale",0,3).onchange(function (e) { sphere.scale.set(e, e, e); }); //立方体的操作 var cubefolder = datgui.addfolder("cube"); cubefolder.add(gui,"cubex",-30,30).onchange(function (e) { cube.position.x = e; }); cubefolder.add(gui,"cubey",-30,30).onchange(function (e) { cube.position.y = e; }); cubefolder.add(gui,"cubez",-30,30).onchange(function (e) { cube.position.z = e; }); cubefolder.add(gui,"cubescale",0,3).onchange(function (e) { cube.scale.set(e, e, e); }); //场景组的操作 var groupfolder = datgui.addfolder("group"); groupfolder.add(gui,"groupx",-30,30).onchange(function (e) { group.position.x = e; }); groupfolder.add(gui,"groupy",-30,30).onchange(function (e) { group.position.y = e; }); groupfolder.add(gui,"groupz",-30,30).onchange(function (e) { group.position.z = e; }); groupfolder.add(gui,"groupscale",0,3).onchange(function (e) { group.scale.set(e, e, e); }); //添加旋转功能 datgui.add(gui, "grouping"); datgui.add(gui, "rotate"); } var light; function initlight() { scene.add(new three.ambientlight(0x444444)); light = new three.pointlight(0xffffff); light.position.set(15,50,10); //告诉平行光需要开启阴影投射 light.castshadow = true; scene.add(light); } var sphere,cube,group; function initmodel() { //模型组 group = new three.object3d(); scene.add(group); //球 var spheregeometry = new three.spheregeometry(5,200,200); var spherematerial = new three.meshlambertmaterial({color:0xaaaaaa}); sphere = new three.mesh(spheregeometry, spherematerial); sphere.position.x = -5; sphere.position.y = 5; //告诉球需要投射阴影 sphere.castshadow = true; group.add(sphere); //辅助工具 var helper = new three.axishelper(50); scene.add(helper); //立方体 var cubegeometry = new three.cubegeometry(10,10,8); var cubematerial = new three.meshlambertmaterial({color:0x00ffff}); cube = new three.mesh(cubegeometry, cubematerial); cube.position.x = 15; cube.position.y = 5; cube.position.z = -5; //告诉立方体需要投射阴影 cube.castshadow = true; group.add(cube); //底部平面 var planegeometry = new three.planegeometry(100,100); var planematerial = new three.meshstandardmaterial({color:0xaaaaaa}); var plane = new three.mesh(planegeometry, planematerial); plane.rotation.x = - 0.5 * math.pi; plane.position.y = -0; //告诉底部平面需要接收阴影 plane.receiveshadow = true; scene.add(plane); } //初始化性能插件 var stats; function initstats() { stats = new stats(); document.body.appendchild(stats.dom); } //用户交互插件 鼠标左键按住旋转,右键按住平移,滚轮缩放 var controls; function initcontrols() { controls = new three.orbitcontrols( camera, renderer.domelement ); // 如果使用animate方法时,将此函数删除 //controls.addeventlistener( 'change', render ); // 使动画循环使用时阻尼或自转 意思是否有惯性 controls.enabledamping = true; //动态阻尼系数 就是鼠标拖拽旋转灵敏度 //controls.dampingfactor = 0.25; //是否可以缩放 controls.enablezoom = true; //是否自动旋转 controls.autorotate = false; //设置相机距离原点的最远距离 controls.mindistance = 100; //设置相机距离原点的最远距离 controls.maxdistance = 200; //是否开启右键拖拽 controls.enablepan = true; } var step = 0.02; //模型旋转的速度 function render() { //判断当前是否自动旋转 if(gui.rotate){ //判断是单个模型自转,还是模型组自转 if(gui.grouping){ group.rotation.y += step; } else{ sphere.rotation.y += step; cube.rotation.y += step; } } renderer.render( scene, camera ); } //窗口变动触发的函数 function onwindowresize() { camera.aspect = window.innerwidth / window.innerheight; camera.updateprojectionmatrix(); render(); renderer.setsize( window.innerwidth, window.innerheight ); } function animate() { //更新控制器 render(); //更新性能插件 stats.update(); controls.update(); requestanimationframe(animate); } function draw() { initgui(); initrender(); initscene(); initcamera(); initlight(); initmodel(); initcontrols(); initstats(); animate(); window.onresize = onwindowresize; } </script> </html>
上一篇: js DOM 元素ID就是全局变量
下一篇: Python多进程机制实例详解