👨⚕️ 主页: gis分享者
👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨⚕️ 收录于专栏:threejs gis工程师
文章目录
- 一、🍀前言
- 1.1 ☘️THREE.ParametricGeometry
- 1.1.1 ☘️构造函数
- 1.1.2 ☘️属性
- 1.1.3 ☘️方法
- 二、🍀构建THREE.ParametricGeometry参数化函数生成几何体
- 1. ☘️实现思路
- 2. ☘️代码样例
一、🍀前言
本文详细介绍如何基于threejs在三维场景中构建THREE.ParametricGeometry参数化函数生成几何体,亲测可用。希望能帮助到您。一起学习,加油!加油!
1.1 ☘️THREE.ParametricGeometry
THREE.ParametricGeometry生成由参数表示其表面的几何体。
代码示例:
const geometry = new THREE.ParametricGeometry( THREE.ParametricGeometries.klein, 25, 25 );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const klein = new THREE.Mesh( geometry, material );
scene.add( klein );
创建一个波浪曲面:
import { ParametricGeometry } from 'three/addons/geometries/ParametricGeometry.js';// 定义参数化函数(波浪)
function wave(u, v, target) {const x = u * 20 - 10; // u: 0→1 → x: -10→10const y = v * 20 - 10; // v: 0→1 → y: -10→10const z = Math.sin(x * 0.5) * Math.cos(y * 0.5); // 计算波浪高度target.set(x, y, z);
}// 创建几何体(50x50 分段)
const geometry = new ParametricGeometry(wave, 50, 50);// 创建材质和网格
const material = new THREE.MeshPhongMaterial({ color: 0x0099ff, wireframe: true });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
创建一个圆环面:
function torus(u, v, target) {const R = 4; // 主半径const r = 1; // 管道半径const theta = u * Math.PI * 2; // u 对应环绕角度const phi = v * Math.PI * 2; // v 对应管道角度const x = (R + r * Math.cos(phi)) * Math.cos(theta);const y = (R + r * Math.cos(phi)) * Math.sin(theta);const z = r * Math.sin(phi);target.set(x, y, z);
}const geometry = new ParametricGeometry(torus, 64, 32);
1.1.1 ☘️构造函数
ParametricGeometry(func : Function, slices : Integer, stacks : Integer)
func — 一个函数,它接受一个介于 0 和 1 之间的 u 和 v 值,并修改第三个 Vector3 参数。默认是生成曲面的函数。
slices — 用于参数函数的切片数。默认值为 8。
stacks — 用于参数函数的堆栈数。默认值为 8。
1.1.2 ☘️属性
共有属性请参见其基类BufferGeometry。
.parameters : Object
一个包含着构造函数中每个参数的对象。在对象实例化之后,对该属性的任何修改都不会改变这个几何体。
1.1.3 ☘️方法
共有方法请参见其基类BufferGeometry。
二、🍀构建THREE.ParametricGeometry参数化函数生成几何体
1. ☘️实现思路
- 1、初始化renderer渲染器。
- 2、初始化Scene三维场景scene。
- 3、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt。
- 4、创建THREE.SpotLight聚光灯光源spotLight,设置聚光灯光源位置和投影,scene场景加入spotLight。
- 5、加载几何模型:定义klein方法,用于创建克莱因瓶函数。定义radialWave方法,用于创建纵向波函数。创建createMesh方法,使用THREE.MeshPhongMaterial高光材质,创建THREE.ParametricGeometry几何体。传入radialWave函数和其他参数调用createMesh方法创建参数化函数生成几何体网格对象mesh,scene场景添加mesh。定义render方法,实现mesh旋转动画。具体代码参考下面代码样例。
- 6、加入stats监控器,监控帧数信息。
2. ☘️代码样例
<!DOCTYPE html><html><head><title>学习threejs,构建THREE.ParametricGeometry参数化函数生成几何体</title><script type="text/javascript" src="../libs/three.js"></script><script type="text/javascript" src="../libs/stats.js"></script><script type="text/javascript" src="../libs/dat.gui.js"></script><style>body {margin: 0;overflow: hidden;}</style>
</head>
<body><div id="Stats-output">
</div>
<div id="WebGL-output">
</div><!-- Js 代码块 -->
<script type="text/javascript">// 初始化function init() {var stats = initStats();// 创建三维场景var scene = new THREE.Scene();// 创建相机var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);// 创建渲染器并设置颜色、大小和投影var webGLRenderer = new THREE.WebGLRenderer();webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));webGLRenderer.setSize(window.innerWidth, window.innerHeight);webGLRenderer.shadowMapEnabled = true;// 设置相机位置和方向camera.position.x = -30;camera.position.y = 50;camera.position.z = 50;camera.lookAt(new THREE.Vector3(10, -20, 0));var spotLight = new THREE.DirectionalLight();spotLight.position = new THREE.Vector3(-20, 250, -50);spotLight.target.position.x = 30;spotLight.target.position.y = -40;spotLight.target.position.z = -20;spotLight.intensity = 0.3;scene.add(spotLight);// 渲染器绑定html页面元素document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);var step = 0;// 克莱因瓶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);};// 径向波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 mesh = createMesh(new THREE.ParametricGeometry(radialWave, 120, 120, false));scene.add(mesh);render();function createMesh(geom) {geom.applyMatrix(new THREE.Matrix4().makeTranslation(-25, 0, -25));var meshMaterial = new THREE.MeshPhongMaterial({specular: 0xaaaafff,color: 0x3399ff,shininess: 40,metal: true});meshMaterial.side = THREE.DoubleSide;// 创建波浪网格对象var plane = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial]);return plane;}function render() {stats.update();// 网格对象旋转动画mesh.rotation.y = step += 0.01;mesh.rotation.x = step;requestAnimationFrame(render);webGLRenderer.render(scene, camera);}function initStats() {var stats = new Stats();stats.setMode(0);stats.domElement.style.position = 'absolute';stats.domElement.style.left = '0px';stats.domElement.style.top = '0px';document.getElementById("Stats-output").appendChild(stats.domElement);return stats;}}window.onload = init;
</script>
</body>
</html>
效果如下:
径向波:
克莱因瓶: