three.js 几何体、材质和网格模型

news2024/11/15 7:44:13

场景Scene、相机Camera、渲染器Renderer初始化完成之后,可以向场景中添加一个简单的模型进行展示。在此之前需要了解三个概念:几何体、材质、网格模型

  • 几何体:表示物体的几何形状。
  • 材质:表示物体的外观效果。
  • 网格模型:将几何体和材质组合起来,作为three.js的一个基本物体单位,可以添加进场景中。

几何体相关

几何体是指由点、线、面所构成的空间实体。其中,点、线、面是几何体的基本元素,几何体包括球体、立方体、圆柱体、矩形、圆形等。这些几何体都有自己的特定形状和特征,可以应用于各种数学、物理和工程领域。

常见的几何体

在这里插入图片描述

// BoxGeometry:长方体
const geometry = new THREE.BoxGeometry(100, 100, 100);
// SphereGeometry:球体
const geometry = new THREE.SphereGeometry(50);
// CylinderGeometry:圆柱
const geometry = new THREE.CylinderGeometry(50,50,100);
// PlaneGeometry:矩形平面
const geometry = new THREE.PlaneGeometry(100,50);
// CircleGeometry:圆形平面
const geometry = new THREE.CircleGeometry(50);

缓冲类型几何体BufferGeometry

threejs提供的长方体BoxGeometry、球体SphereGeometry等各种形状的几何体都是基于BufferGeometry类构建的,BufferGeometry是一个没有任何形状的空几何体,你可以通过BufferGeometry自定义任何几何形状,具体一点说就是定义顶点数据。

// 创建一个空的几何体对象
const geometry = new THREE.BufferGeometry(); 

缓冲区对象BufferAttribute

BufferAttribute类用于存储与BufferGeometry相关联的 attribute(例如顶点位置向量,面片索引,法向量,颜色值,UV坐标以及任何自定义 attribute )。

BufferAttribute( array, itemSize, normalized )

  • array:与BufferGeometry相关联的数组。必须是TypedArray类型。
  • itemSize:与顶点相关的数据值的大小。如果 attribute 存储的是三元组(例如顶点空间坐标、法向量或颜色值)则itemSize的值应该是3。
  • normalized:指示数据如何与GLSL代码中的数据进行对应。
// 类型化数组创建顶点数据
const vertices = new Float32Array([
    0, 0, 0, // 顶点1坐标
    80, 0, 0, // 顶点2坐标
    80, 80, 0, // 顶点3坐标
    0, 0, 0, // 顶点4坐标   和顶点1位置相同
    80, 80, 0, // 顶点5坐标  和顶点3位置相同
    0, 80, 0, // 顶点6坐标
]);
// 创建属性缓冲区对象
const attribue = new THREE.BufferAttribute(vertices, 3); 

使用BufferGeometry定义一个矩形几何体

一个矩形平面,可以至少通过两个三角形拼接而成。而且两个三角形有两个顶点的坐标是重合的。
注意三角形的正反面问题:保证矩形平面两个三角形的正面是一样的,也就是从一个方向观察,两个三角形都是逆时针或顺时针。

  1. 通过javascript类型化数组Float32Array创建一组xyz坐标数据用来表示几何体的顶点坐标。
// 类型化数组创建顶点数据
const vertices = new Float32Array([
    0, 0, 0, // 顶点1坐标
    80, 0, 0, // 顶点2坐标
    80, 80, 0, // 顶点3坐标
    0, 0, 0, // 顶点4坐标   和顶点1位置相同
    80, 80, 0, // 顶点5坐标  和顶点3位置相同
    0, 80, 0, // 顶点6坐标
]);
  1. 通过threejs的属性缓冲区对象BufferAttribute表示threejs几何体顶点数据。
// 创建属性缓冲区对象
// 3个为一组,表示一个顶点的xyz坐标
const attribue = new THREE.BufferAttribute(vertices, 3); 
  1. 设置几何体的顶点
// 设置几何体attribue属性的位置属性
// geometry.setAttribute( 'position', attribue); 
geometry.attributes.position = attribue;

网格模型Mesh对应的几何体BufferGeometry,拆分为多个三角后,很多三角形重合的顶点位置坐标是相同的,这时候如果你想减少顶点坐标数据量,可以借助几何体顶点索引geometry.index来实现。
在这里插入图片描述
在上面的讲述中可以看出,每个三角形3个顶点坐标,矩形平面可以拆分为两个三角形,也就是6个顶点坐标。如果几何体有顶点索引geometry.index,你就可以把三角形重复的顶点位置坐标删除。

const vertices = new Float32Array([
    0, 0, 0, // 顶点1坐标
    80, 0, 0, // 顶点2坐标
    80, 80, 0, // 顶点3坐标
    0, 80, 0, // 顶点4坐标
]);
  1. 通过javascript类型化数组Uint16Array创建顶点索引.index数据。
// Uint16Array类型数组创建顶点索引数据
const indexes = new Uint16Array([
    // 下面索引值对应顶点位置数据中的顶点坐标
    0, 1, 2, 0, 2, 3,
])
  1. 通过threejs的属性缓冲区对象BufferAttribute表示几何体顶点索引.index数据。
// 索引数据赋值给几何体的index属性
geometry.index = new THREE.BufferAttribute(indexes, 1); // 1个为一组

完整代码

// 创建一个空的几何体对象
const geometry = new THREE.BufferGeometry(); 
// 类型化数组创建顶点数据
const vertices = new Float32Array([
	0, 0, 0, // 顶点1坐标
	80, 0, 0, // 顶点2坐标
	80, 80, 0, // 顶点3坐标
	0, 80, 0, // 顶点4坐标
] );
// 创建属性缓冲区对象 itemSize = 3 因为每个顶点都是一个三元组。 
const attribue = new THREE.BufferAttribute(vertices, 3);
// 设置几何体attribue属性的位置属性
geometry.attributes.position = attribue;
// 创建索引 
const indexes = new Uint16Array([0, 1, 2, 2, 3, 0])
// 索引数据,1个为一组
const index = THREE.BufferAttribute(indexes, 1);
// 索引数据赋值给几何体的index属性
geometry.index = index;

const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } ); 
const mesh = new THREE.Mesh( geometry, material );

几何体方法

BufferGeometry通过.scale().translate().rotateX().rotateY()等方法可以对几何体本身进行缩放、平移、旋转,这些方法本质上都是改变几何体的顶点数据。
在这里插入图片描述

缩放.scale()
// 几何体xyz三个方向都放大2倍
geometry.scale(2, 2, 2);
平移.translate()
// 几何体沿着x轴平移50
geometry.translate(50, 0, 0);
旋转.rotateX().rotateY().rotateZ()
// 几何体绕着x轴旋转45度
geometry.rotateX(Math.PI / 4);
居中.center()
geometry.translate(50, 0, 0);//偏移
// 居中:已经偏移的几何体居中,执行.center(),你可以看到几何体重新与坐标原点重合
geometry.center();

材质Material

在Three.js中,‌Material是所有材质的基类,‌它包含了一系列属性和方法,‌用于控制材质的透明度、‌深度测试、‌颜色、‌渲染面(‌正面、‌背面或双面)‌、‌透明度设置等。
在这里插入图片描述
MeshBasicMaterial、MeshLambertMaterial、MeshPhongMaterial等子类网格材质会从父类Material继承一些属性和方法,比如透明度属性.opacity、面属性.side、是否透明属性.transparent等等。

主要的材质属性:

  • color:基本颜色,通常是一个THREE.Color对象,表示材质的漫反射颜色。
  • map:纹理贴图,是一个THREE.Texture对象,用于为材质添加纹理。
  • opacity:透明度,表示材质的不透明程度,取值范围为 0(完全透明)到 1(完全不透明)。
  • transparent:指示材质是否透明。如果设置为true,则材质将考虑透明度(opacity)的影响。
  • alphaMap:透明度贴图,是一个THREE.Texture对象,用于根据纹理图像的灰度值控制材质的透明度。
  • side:渲染面的方向,可以是THREE.FrontSideTHREE.BackSideTHREE.DoubleSide。默认值是THREE.FrontSide,只渲染正面。
  • emissive:自发光颜色,通常是一个THREE.Color对象,表示材质的自发光颜色。
  • emissiveMap:自发光贴图,是一个THREE.Texture对象,用于为材质添加自发光效果。
  • specular:镜面反射颜色,通常是一个THREE.Color对象,表示材质的镜面反射颜色。这个属性主要应用于具有镜面反射效果的材质,如THREE.MeshPhongMaterial
  • shininess:光泽度,表示材质的光泽程度。这个属性主要应用于具有镜面反射效果的材质,如THREE.MeshPhongMaterial
  • wireframe:布尔值,指示是否以线框模式渲染物体。如果设置为 true,则物体将以线框模式显示。
  • bumpMap:凹凸贴图,是一个THREE.Texture对象,用于为材质添加凹凸效果,以模拟表面的细微凹凸。
  • normalMap:法线贴图,是一个THREE.Texture对象,用于为材质添加法线贴图效果,以模拟表面的细节。
  • displacementMap:位移贴图,是一个THREE.Texture对象,用于根据纹理图像的灰度值改变物体表面的高度。
  • roughness:粗糙度,表示材质表面的粗糙程度。这个属性主要应用于基于物理的渲染(PBR)材质,如THREE.MeshStandardMaterialTHREE.MeshPhysicalMaterial
  • metalness:金属度,表示材质表面的金属质感。这个属性主要应用于基于物理的渲染(PBR)材质,如THREE.MeshStandardMaterialTHREE.MeshPhysicalMaterial
  • roughnessMap:粗糙度贴图,是一个THREE.Texture对象,用于根据纹理图像的灰度值控制材质的粗糙度。这个属性主要应用于基于物理的渲染(PBR)材质。
  • metalnessMap:金属度贴图,是一个THREE.Texture对象,用于根据纹理图像的灰度值控制材质的金属度。这个属性主要应用于基于物理的渲染(PBR)材质。
  • envMap:环境贴图,是一个THREE.Texture对象,用于为材质添加反射和折射效果。
  • refractionRatio:折射率,表示材质的折射程度。这个属性主要应用于具有折射效果的材质,如 THREE.MeshPhysicalMaterial
material.color.set(0x00ffff);
material.transparent = true; // 开启透明
material.opacity = 0.5; // 设置透明度
material.side = THREE.DoubleSide; // 双面可见

受光照影响材质

threejs提供的网格材质,有的受光照影响,有的不受光照影响。Three.js会提供一些的光照模型来模拟物体表面的光照,光照模型就一种模拟光照的计算方法。MeshPhysicalMaterialMeshLambertMaterial一样都是渲染网格模型的材质,但是他们用的光照模型不同,具体点说就是材质模拟Mesh反射光照的代码算法不同,算法不同,自然模拟光照的真实程度也不同。
在这里插入图片描述

  • MeshLambertMaterial:Lambert光照模型(漫反射)光线向四周反射。
  • MeshPhongMaterial:Phong光照模型(漫反射、高光反射),可以提供一个镜面反射效果。
  • MeshStandardMaterial 和 MeshPhysicalMaterial:基于物理的光照模型(微平面理论、能量守恒、菲涅尔反射…)
// 模拟镜面反射,产生一个高光效果
const material = new THREE.MeshPhongMaterial({
    color: 0xff0000,
    shininess: 20, // 高光部分的亮度,默认30
    specular: 0x444444, // 高光部分的颜色
});

网格模型Mesh

网格模型Mesh其实就一个一个三角形(面)拼接构成。使用网格模型Mesh渲染几何体geometry,就是几何体所有顶点坐标三个为一组,构成一个三角形,多组顶点构成多个三角形,就可以用来模拟表示物体的表面。在这里插入图片描述
三个点可以构成一个三角形,从第一个点往第三个点连接。空间中一个三角形有正反两面,你的眼睛(相机)对着三角形的一个面,如果三个顶点的顺序是逆时针方向,该面视为正面,如果三个顶点的顺序是顺时针方向,该面视为反面

Mesh(geometry, material)

  • geometry:物体的结构。BufferGeometry的实例,默认值是一个新的BufferGeometry
  • material:物体的外观。一个Material,或是一个包含有Material的数组,默认是一个新的MeshBasicMaterial
  • isMesh:当前对象是否是网格模型。
const mesh = new THREE.Mesh(geometry, material);
// 获取模型的几何体
console.log('mesh.geometry', mesh.geometry);
// 获取模型的材质
console.log('mesh.material', mesh.material);

访问改变模型材质属性

// 访问模型材质,并设置材质的颜色属性
mesh.material.color.set(0xffff00);

访问改变模型几何体属性

// 访问模型几何体,并平移几何体顶点数据
mesh.geometry.translate(0, 100, 0);

材质或几何体共享

如果两个mesh使用同一个材质material,改变其中一个mesh另一个也会随之改变。

const mesh = new THREE.Mesh(geometry, material);
const mesh2 = new THREE.Mesh(geometry, material);
mesh2.position.x = 100;
// 两个mesh共享一个材质,改变一个mesh的颜色,另一个mesh2的颜色也会跟着改变
// mesh.material和mesh2.material都指向同一个material
// 三者等价:mesh.material、mesh2.material、material
mesh.material.color.set(0xffff00);
// 三者等价:mesh.geometry、mesh2.geometry、geometry
mesh.geometry.translate(0,100,0);

克隆.clone()

通过克隆.clone()获得的新模型和原来的模型共享材质和几何体。改变mesh2的颜色mesh不会被改变。克隆.clone()简单说就是复制一个和原对象一样的新对象。

const mesh2 = mesh.clone();
// 克隆几何体和材质,重新设置mesh2的材质和几何体属性
mesh2.geometry = mesh.geometry.clone();
mesh2.material = mesh.material.clone();
// 改变mesh2颜色,不会改变mesh的颜色
mesh2.material.color.set(0xff0000);

复制.copy()

通过复制.copy()简单说就是把一个对象属性的属性值赋值给另一个对象。也不会随之改变另一个mesh

// 改变mesh的位置,使之位于mesh2的正上方(y),距离100。
mesh.position.copy(mesh2.position); // 复制mesh2的位置属性给mesh
mesh.position.y += 100;// mesh在原来y的基础上增加100

也可使用.copy()让两个模型的姿态角度始终保持一样。

// 渲染循环
function render() {
    mesh.rotateY(0.01);// mesh旋转动画
    // 同步mesh2和mesh的姿态角度一样,不管mesh姿态角度怎么变化,mesh2始终保持同步
    mesh2.rotation.copy(mesh.rotation);
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}
render();

点模型Points

点模型Points用于显示点的类。

Points(geometry, material)

  • geometry:物体的结构。BufferGeometry的实例,默认值是一个新的BufferGeometry
  • material:点的材质。默认是PointMaterial
  • isPoints:当前对象是否是点模型。
// 点渲染模式
const material = new THREE.PointsMaterial({
    color: 0xffff00,
    size: 10.0 // 点对象像素尺寸
}); 
// 点模型对象
const points = new THREE.Points(geometry, material);

线模型Line

线模型Line一条连续的线。

Line(geometry, material)

  • geometry:表示线段的顶点,默认值是一个新的BufferGeometry
  • material:线的材质。默认是LineBasicMaterial
  • isLine:当前对象是否是线模型。
// 线材质对象
const material = new THREE.LineBasicMaterial({
    color: 0xff0000 // 线条颜色
}); 
// 创建线模型对象
const line = new THREE.Line(geometry, material);

threejs线模型除了Line,还提供了LineLoopLineSegments,区别在于绘制线条的规则不同。

// 闭合线条
const lineLoop = new THREE.LineLoop(geometry, material); 
// 非连续的线条
const lineSegments = new THREE.LineSegments(geometry, material);

基础案例使用

创建一个立方体,使其围绕Y轴旋转。

// 创建场景
const scene = new THREE.Scene();
let width = window.innerWidth; // 窗体宽度
let height = window.innerHeight; // 窗体高度
// 创建透视投影相机,视角45度,画幅比例 宽比高,近平面距离0.1,远平面1000
const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 1000);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 渲染器canvas宽高设为与窗口一致
renderer.setSize(width, height);
renderer.setClearColor(0xffffff, 1) // 设置背景颜色
// 将渲染器对应的dom元素添加到body中
document.body.appendChild(renderer.domElement);
// 定义一个几何体
const geometry = new THREE.BoxGeometry(30, 30, 30);
// 定义一种材质,显示为线框
const material = new THREE.MeshBasicMaterial({ color: 0x000000, wireframe: true });
// 网孔(Mesh)是用来承载几何模型的一个对象,可以把材料应用到它上面
const mesh = new THREE.Mesh(geometry, material);
// 把几何模型添加到场景中,对象被添加到原点(0,0,0)坐标。
scene.add(mesh);
camera.position.set(0, 200, 300); // 设置相机位置
camera.lookAt(scene.position); // 设置相机方向(指向的场景对象)
function render() {
    // 渲染循环,以每秒60次的频率来绘制场景
    requestAnimationFrame(render);
    // 设置立方体绕y轴旋转
    mesh.rotation.y += 0.005;
    renderer.render(scene, camera);
}
render();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2046314.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot的学习(一):springboot的基础

简介 springboot的基础的知识点的学习总结 springboot 设计目的是为了简化spring应用的初始搭建和开发过程。 简单例子 new project,一般用这个阿里的地址:https://start.aliyun.com/ 点击next,选择jdk版本 点击next,选择模…

88.SAPUI5 Model Binding的问题-在view更改数据,model却不变

目录 1.背景 2.sap.ui.model.BindingMode sap.ui.model.BindingMode.OneWay sap.ui.model.BindingMode.TwoWay 3.oModel.setDefaultBindingMode 方法说明 execOneWay方法 execTwoWay方法 1.背景 在做一个UI5项目,后台读取sap.ui.model.Model后,把…

Vuex 深度解析 | 面试常问问题案例

Vuex 深度解析 | 面试常问问题案例 Vuex 是 Vue.js 应用程序的状态管理模式和库。它为 Vue.js 应用程序提供了一个集中存储所有组件的共享状态,并以相应的规则保证状态以一种可预测的方式发生变化。接下来,我们将深入探讨 Vuex 的核心概念、使用方式、AP…

项目管理高效秘诀:优选软件大公开

国内外主流的 10 款项目管理系统对比:PingCode、Worktile、Asana、Trello、ClickUp、Zoho Projects、Hive、Teambition、飞书、Tapd。 在寻找完美的项目管理工具时,许多团队都面临一个共同的问题:除了已知的Worktile之外,还有哪些…

“从创建到管理,Linux进程编程是你掌握系统资源的金钥匙!“#Linux系统编程之进程【下】

"从创建到管理,Linux进程编程是你掌握系统资源的金钥匙!"#Linux系统编程之进程【下】 前言预备知识一、 父进程等待子进程退出(一)1.1 为啥要等待子进程退出1.2 父进程等待子进程退出并收集退出状态1.3 编程验证僵尸进程…

【47 Pandas+Pyecharts | 杭州二手房数据分析可视化】

文章目录 🏳️‍🌈 1. 导入模块🏳️‍🌈 2. Pandas数据处理2.1 读取数据2.2 过滤数据2.3 行政区处理2.4 地址处理2.5 房屋信息处理2.6 面积处理2.7 楼层处理2.8 年份处理2.9 房价处理2.10 删除不用的列2.11 数据类型转换2.12 查看…

【数学建模】Matlab 编程

MATLAB是美国MathWorks公司自20世纪80年代中期推出的数学软件,具有优秀的数值计算能力和卓越的数据可视化。由于Maltab编程方便,有大量内部函数和工具箱可以使用,作图也 十分方便,因此在数学实验和数学建模竞赛中,我们…

揭秘紧固件分销网络:如何成为结构安全和社会进步的关键支点?

全球产品分销的历史源远流长,早在国际贸易初期就已形成。在紧固件行业中,随着各行业对紧固件需求的不断增长,市场呈现出积极的发展趋势。紧固件在结构、机械、设备及其他众多组件中扮演着至关重要的角色,确保了整个系统的高效运行…

电子家谱族谱在线制作小程序开发

电子家谱族谱在线制作小程序开发 电子家谱在线制作小程序通常会提供一系列的功能来帮助用户创建和维护家谱。这里是一个基于市场上常见的家谱制作小程序的功能列表示例: 基本信息录入: 用户注册与登录个人信息录入(姓名、性别、出生日期、照…

隐藏你的环境文件!否则你的云存储数据可能会被盗并被勒索

网络犯罪分子正在侵入组织的云存储容器,窃取其敏感数据,并且在一些情况下,受害组织还会向他们支付费用,以确保他们不泄露或出售被盗数据。 研究人员表示:“此次活动背后的攻击者可能利用了广泛的自动化技术来成功且快…

车载网络测试实操源码_使用CAPL脚本对CAN总线上的错误帧进行实时监控

系列文章目录 车载网络测试实操源码_使用CAPL脚本解析hex、S19、vbf文件 车载网络测试实操源码_使用CAPL脚本对CAN报文的Counter、CRC、周期、错误帧进行实时监控 车载网络测试实操源码_使用CAPL脚本模拟发送符合协议要求(Counter和CRC)的CAN报文 车载网络测试实操源码_使用CA…

企业办公室电脑监控软件有什么好用的推荐(闭眼也可入手)

“工欲善其事,必先利其器。” 在今日之商业战场,企业之兴衰,不仅关乎战略眼光与市场布局,更在于内部管理之精细与效率。 信息技术的飞速发展,企业办公室电脑监控软件应运而生,成为了现代企业管理的得力助…

OpenCV Python 图像处理入门

OpenCV入门 OpenCV:轻量、高效、开源。最广泛使用的计算机视觉工具。 下面涉及图片的读取,RGB彩色通道,区域裁剪,绘制图形和文字,均值滤波,特征提取,模板匹配,梯度算法&#xff0c…

黑马Java零基础视频教程精华部分_19_lambda表达式

系列文章目录 文章目录 系列文章目录一、函数式编程二、Lambda表达式的标准格式三、Lambda表达式的省略写法 一、函数式编程 函数式编程(Functional programming)是一种思想特点。 之前的面向对象:先找对象,让对象做事情。如下图所示,这样会有点小麻烦。…

(一)基于自组织结构的多目标粒子群优化算法(SMOPSO)的无人机三维路径规划(MATLAB代码)

一、无人机多目标优化模型 无人机三维路径规划是无人机在执行任务过程中的非常关键的环节,无人机三维路径规划的主要目的是在满足任务需求和自主飞行约束的基础上,计算出发点和目标点之间的最佳航路。 1.1路径成本 无人机三维路径规划的首要目标是寻找…

理解Pytorch中的collate_fn函数

PyTorch中的DataLoader是最常用的类之一,这个类有很多参数(14 个),但大多数情况下,你可能只会使用其中的三个:dataset、shuffle 和 batch_size。其中collate_fn是比较少用的函数,这对初学者来说…

2024年国家数据局第一批20个“数据要素×”典型案例解析

国家数据局首批20个“数据要素”典型案例解析 1、简介1.1 背景简介1.2 典型案例分类 2、案例解析2.1 工业制造领域案例1:数据要素驱动适应多式联运需求的运输装备协同制造案例2:打造工业数据空间 赋能产业链上下游发展 2.2 现代农业领域案例3&#xff1a…

07一阶电路和二阶电路的时域分析

一阶电路和二阶电路的时域分析 时域分析、频域分析、复频域分析本应该在信号与系统,或者数字信号处理这一章节里面进行处理的。 但在电路理论中也有这些知识,那就要好好掌握一下,打个底。详细细致的部分放到信号与系统里面去掌握

Spring Web MVC入门(中)

1. 请求 访问不同的路径, 就是发送不同的请求. 在发送请求时, 可能会带⼀些参数, 所以学习Spring的请求, 主要 是学习如何传递参数到后端以及后端如何接收. 传递参数, 咱们主要是使⽤浏览器和Postman来模拟; 1.1 传递单个参数 接收单个参数,在Spring MV…

七段S型加减速算法原理及其多种形状仿真

1、基本7段S型: 七段S型加减速的位置、速度、加速度、加加速度曲线如下图所示。 加加速度: 加速度: 速度: 位置: 以上是7段S型加减速的最基本公式,在实际应用中还需要考虑到起始和终止速度大于匀速速度的情…