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

场景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, 0, 0, // 顶点4坐标   和顶点1位置相同80, 80, 0, // 顶点5坐标  和顶点3位置相同0, 80, 0, // 顶点6坐标
] );
// 创建属性缓冲区对象 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, // 高光部分的亮度,默认30specular: 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.rhkb.cn/news/401475.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YoloV8改进策略:Block改进|LeYOLO,一种用于目标检测的新型可扩展且高效的CNN架构|复现LeYolo,轻量级Yolo改进

摘要 LeYOLO是在YOLO系列,特别是可能受到YOLOv8启发的基础上进行的一系列改进,旨在提升目标检测模型的高效性、可扩展性和精度。其主要特点包括: 高效骨干网络缩放方法: LeYOLO借鉴了倒置瓶颈(Inverted Bottleneck&am…

大模型学习方法之——大模型技术学习路线

“ 技术学习无非涵盖三个方面,理论,实践和应用**”** 大模型技术爆火至今已经有两年的时间了,而且大模型技术的发展潜力也不言而喻。因此,很多人打算学习大模型,但又不知道该怎么入手,因此今天就来了解一下…

Spring——IOC/DI思想

1、IOC(Inversion of Control)控制反转 何为控制反转? 在业务层中我们如果要调用数据层的方法那么必然牵扯到对象的创建,如果我想要改变上述数据层的方法中的内容,那么我就要改变业务层的代码,重新创建对…

RedisTempate序列化的json字符串,如何反序列化

待转换的字符串 常见工具 Gson json new Gson(); 无法解析,只能有Josn的反序列化来实现 public void onMessage(final Message message, final byte[] pattern) { // RedisMessage redisMessage json.fromJson(message.toString(), RedisMessage.class);//…

从0开始搭建vue + flask 旅游景点数据分析系统(十二)【完结篇】:用户管理之增删改查、用户信息更新

这一期继续完成用户管理的增删改查和登录用户修改自己信息的功能,首先完成后端接口的功能。 1 后端接口 这边有查询列表接口、查询单个接口、新增接口、修改接口、删除接口这5个接口: #** 用户信息的增删改查 *** # 用户列表 main.route(/users, meth…

第36讲:使用Prometheus监控系统全方面监控Ceph集群

文章目录 1.启用Manager组件的Prometheus模块2.部署并配置Prometheus2.1.部署Prometheus服务端2.2.配置Prometheus添加Ceph集群的监控信息2.3.观察Prometheus监控系统中是否能浏览Ceph集群的监控数据 3.部署Grafana用于展示Prometheus的监控数据3.1.部署Grafana仪表盘3.2.Grafa…

开发工具及框架分享

文章目录 前言一、IDEA 开发工具知识分享1.1 功能特点介绍1.2 常见插件使用1.3 快捷键设置1.4 代码调试 二、Maven项目依赖管理介绍2.1 Maven 介绍2.2 Maven 安装及配置2.3 Maven 功能与特性2.4 打包测试 三、Springboot框架介绍3.1 核心特征概述3.2 常用注解介绍3.3 自动装配原…

yolov8/yolov10 MLU370 实现推理/单多卡训练!

文章目录 前言一、平台环境配置二、基础环境配置1.代码下载2.环境安装3.模型下载4.代码修改 三.单卡推理四、单/多卡训练 前言 本章主要操作以yolov8为主,但是yolov10用该操作也能直接适用,开干! 一、平台环境配置 镜像选择:v2…

Python Django 框架 01

1. 以新闻内容为主的网站-Django。CMS 查看django官方网站。查看django源码。查看中文文档。对于Django框架遵循MVC设计,并且有个专用名字:MVT。 model 只适用于关系型数据库。 建议使用谷歌浏览器。 Django环境配置 python 环境 因为Django是需要Py…

Leetcode每日刷题之面试题01.02判断是否互为字符重排(C++)

1. 题目解析 本题判断的是两个字符串,其中一个字符串变换顺序是否可以变化为第二个字符串,即重排后是否为同一字符串 2. 算法原理 这里我的思路是直接统计两字符串中字符出现的次数,然后直接比较即可,我使用了范围for以及字符ASCI…

【系统架构设计】系统性能评价

【系统架构设计】系统性能评价 性能指标对计算机对网络对操作系统对数据库管理系统对Web服务器 性能计算MIPS(百万条指令/秒)计算方法峰值计算等效指令速度 性能设计性能评估 性能指标 对计算机 时钟频率(主频) 指计算机处理器的时钟频率,…

2024 D^3CTF pwn(d3note write_flag_where D3BabyEscape pwnshell)

文章目录 d3note libc 2.37源码exp write_flag_where glibc 2.38源码改scanf利用 改write D3BabyEscape源码exp pwnshellphp堆源码exp d3note libc 2.37 源码 index越界,show也没有检查,直接打印,这里找到got表,直接开搜就行 然后…

asp.net core 调用wps实现word转pdf

安装wps https://www.wps.cn/ 创建.net core控制项目 添加com引用,搜索wps 准备word,名字叫001.docx word转pdf 编写代码 namespace WPSStu01 {internal class Program{static void Main(string[] args){Console.WriteLine("转化开始&q…

日撸Java三百行(day24:二叉树的建立)

目录 一、分析准备 二、代码实现 1.方法创建 2.数据测试 3.完整的程序代码 总结 一、分析准备 在日撸Java三百行(day22:二叉树的存储)中,我们学习的是如何将链表二叉树转换为顺序表二叉树进行存储,而今天我们要…

一套完整的NVR方案与部分NVR录像机GUI源码剖析

一、部分功能展示 1.1 通道管理部分 在NVR系统中,通道管理是核心功能之一。通过通道管理,用户可以对连接的摄像头进行配置和监控。 通道连接使能:用户可以选择开启或关闭特定通道的连接功能,以实现灵活的设备管理。 时间同步&…

Kali Linux 三种网络攻击方法总结(DDoS、CC 和 ARP 欺骗)

一、引言 在当今数字化的时代,网络安全成为了至关重要的议题。了解网络攻击的方法和原理不仅有助于我们增强防范意识,更是网络安全领域专业人员必备的知识。Kali Linux 作为一款专为网络安全专业人员和爱好者设计的操作系统,提供了丰富的工具…

VideoPlayer插件的用法

文章目录 1. 概念介绍2. 使用方法2.1 实现步骤2.2 具体细节 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何获取文件类型"相关的内容,本章回中将介绍如何播放视频.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 播放视频是我们常用…

Windows11下wsl闪退的解决

wsl闪退 1. 原因分析 解释:WSL(Windows Subsystem for Linux)闪退通常指的是在Windows操作系统中运行的Linux环境突然关闭。这可能是由于多种原因造成的,包括系统资源不足、WSL配置问题、兼容性问题或者是Linux内核的问题。&…

【Python学习-UI界面】PyQt5 小部件13-Slider 拖动条

高级布局管理器,允许通过拖动边界来动态改变子小部件的大小。 Splitter控件提供一个手柄,可以拖动以调整控件的大小 样式如下: 常用方法如下: 序号方法描述1addWidget将小部件添加到拆分器的布局中2indexOf返回布局中小部件的索引3insetW…

MySQL架构与数据库基础

文章目录 一、数据库概念二、数据库的简单概念三、SQL四、MySQL架构 一、数据库概念 数据库是一个以某种由组织的方式存储的数据集合。我们可以把数据库想象称为一个文件柜。此文件柜是一个存放数据的物理位置,不管数据是什么以及如何组织的。数据库本质也需要像文…