Three.js使用THREE.ParametricGeometry生成平面图形、波浪图形、和克莱因瓶
程序员文章站
2022-06-07 14:52:11
简介
使用three.parametricgeometry可以根据传入的公式,计算出相应的几何体。这是一个很具有扩展性的几何体。
简单实现
var geometry =...
简介
使用three.parametricgeometry可以根据传入的公式,计算出相应的几何体。这是一个很具有扩展性的几何体。
简单实现
var geometry = new three.parametricgeometry(function, slices, stacks);
通过上面的方法,就可以创建出一个three.parametricgeometry的几何体。相关的参数为:
相关参数
属性 | 是否必需 | 描述 |
---|---|---|
function | 是 | 该属性为一个函数,该函数以u、v值作为参数定义每个顶点的位置。需要返回three.vector3的值 |
slices | 是 | 该属性定义u值应该分成多少份 |
stacks | 是 | 该属性定义v值应该分成多少份 |
方法讲解
在我们设置好相关的属性值之后,three.parametricgeometry会根据我们定义的slices和stacks将u和v生成的值传给function循环调用。u和v的范围是0-1。
举个列子:如果我们要生成一个width为10,depth为10的平面图形,将slices设置为5,stacks设置为4。function的表达式为
//创建平面模型的方法 var plane = function (u, v) { var x = u*10; var y = 0; var z = v*10; return new three.vector3(x, y, z); };
那么,在运算的时候,会生成的点就是:
u:0/5; v:0/4; return: three.vector3(0, 0, 0); u:1/5; v:0/4; return: three.vector3(2, 0, 0); u:2/5; v:0/4; return: three.vector3(4, 0, 0); u:3/5; v:0/4; return: three.vector3(6, 0, 0); u:4/5; v:0/4; return: three.vector3(8, 0, 0); u:5/5; v:0/4; return: three.vector3(10, 0, 0); u:0/5; v:1/4; return: three.vector3(0, 0, 2.5); u:1/5; v:1/4; return: three.vector3(2, 0, 2.5); u:2/5; v:1/4; return: three.vector3(4, 0, 2.5); ... u:3/5; v:4/4; return: three.vector3(6, 0, 10); u:4/5; v:4/4; return: three.vector3(8, 0, 10); u:5/5; v:4/4; return: three.vector3(10, 0, 10);
然后,程序通过生成的这些一组一组的点,生成相应的面,再绘制出来。
案例代码
设置slices和stacks为120时,分的层次很多,所以生成的图形很平滑。
如果设置slices和stacks为12,分的层次少,则能够看出来点的关系。
通过上面我们可以看出来程序通过我们生成的点,绘制出来了,相应的图形。
以下是相关案例代码:
<!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="https://johnson2heng.github.io/three.js-demo/lib/three.js"></script> <script src="https://johnson2heng.github.io/three.js-demo/lib/js/controls/orbitcontrols.js"></script> <script src="https://johnson2heng.github.io/three.js-demo/lib/js/libs/stats.min.js"></script> <script src="https://johnson2heng.github.io/three.js-demo/lib/js/libs/dat.gui.min.js"></script> <script> var renderer; function initrender() { renderer = new three.webglrenderer({antialias:true}); //renderer.setclearcolor(new three.color(0xeeeeee, 1.0)); //设置背景颜色 renderer.setsize(window.innerwidth, window.innerheight); document.body.appendchild(renderer.domelement); } var camera; function initcamera() { camera = new three.perspectivecamera(45, window.innerwidth/window.innerheight, 1, 10000); camera.position.set(0, 0, 150); } var scene; function initscene() { scene = new three.scene(); } var light; function initlight() { scene.add(new three.ambientlight(0x404040)); light = new three.directionallight(0xffffff); light.position.set(1,1,1); scene.add(light); } //创建平面模型的方法 var plane = function (u, v) { var x = u*50; var y = 0; var z = v*50; return new three.vector3(x, y, z); }; //创建波浪图形的方法 var radialwave = function (u, v) { var r = 50; var x = math.sin(u) * r; var z = math.sin(v / 2) * 2 * r; var y = (math.sin(u * 4 * math.pi) + math.cos(v * 2 * math.pi)) * 2.8; return new three.vector3(x, y, z); }; var klein = function (u, v) { u *= math.pi; v *= 2 * math.pi; u = u * 2; var x, y, z; if (u < math.pi) { x = 3 * math.cos(u) * (1 + math.sin(u)) + (2 * (1 - math.cos(u) / 2)) * math.cos(u) * math.cos(v); z = -8 * math.sin(u) - 2 * (1 - math.cos(u) / 2) * math.sin(u) * math.cos(v); } else { x = 3 * math.cos(u) * (1 + math.sin(u)) + (2 * (1 - math.cos(u) / 2)) * math.cos(v + math.pi); z = -8 * math.sin(u); } y = -2 * (1 - math.cos(u) / 2) * math.sin(v); return new three.vector3(x, y, z); }; function initmodel() { //轴辅助 (每一个轴的长度) object = new three.axishelper( 50 ); scene.add( object ); var mesh = createmesh(new three.parametricgeometry(klein, 12, 12)); scene.add(mesh); } //生成模型 function createmesh(geom) { //设置当前的模型矩阵沿xy轴偏移,让图片处于显示中心 geom.applymatrix(new three.matrix4().maketranslation(0, 0, 0)); // 创建法向量纹理 var meshmaterial = new three.meshnormalmaterial({ flatshading: three.flatshading, transparent: true, opacity: 0.9 }); // 创建一个线框纹理 var wireframemat = new three.meshbasicmaterial(); wireframemat.wireframe = true; // 创建模型 var mesh = three.sceneutils.createmultimaterialobject(geom, [meshmaterial,wireframemat]); return mesh; } //初始化性能插件 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 = 20; //设置相机距离原点的最远距离 controls.maxdistance = 10000; //是否开启右键拖拽 controls.enablepan = true; } //生成gui设置配置项 var gui; function initgui() { //声明一个保存需求修改的相关数据的对象 gui = {}; var datgui = new dat.gui(); //将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值) //调用生成一次图形 gui.asgeom(); } function render() { renderer.render( scene, camera ); } //窗口变动触发的函数 function onwindowresize() { camera.aspect = window.innerwidth / window.innerheight; camera.updateprojectionmatrix(); render(); renderer.setsize( window.innerwidth, window.innerheight ); } function animate() { //更新控制器 controls.update(); render(); //更新性能插件 stats.update(); requestanimationframe(animate); } function draw() { initrender(); initscene(); initcamera(); initlight(); initmodel(); initcontrols(); initstats(); //initgui(); animate(); window.onresize = onwindowresize; } </script> </html>
上一篇: 小米9王源限量版来了 小米之家已开启预售
下一篇: PHP系统命令函数使用分析