学习threejs,构建THREE.ParametricGeometry参数化函数生成几何体
👨⚕️ 主页: 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→10
const y = v * 20 - 10; // v: 0→1 → y: -10→10
const 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>
效果如下:
径向波:
克莱因瓶: