ThreeJS 几何体顶点position、法向量normal及uv坐标 | UV映射 - 法向量 - 包围盒

文章目录

  • 几何体的顶点position、法向量normal及uv坐标
    • UV映射
      • UV坐标系
      • UV坐标与顶点坐标
      • 设置UV坐标
        • 案例1:使用PlaneGeometry创建平面缓存几何体
        • 案例2:使用BufferGeometry创建平面缓存几何体
    • 法向量 - 顶点法向量光照计算
      • 案例1:不设置顶点法向量平面几何体与自带顶点法向量的平面几何体对比
      • 案例2:设置法向量
        • 方式1 computeVertexNormals方法
        • 方式2:自定义normal属性值
        • 引入顶点法向量辅助器VertexNormalsHelper
    • 几何体的移动、旋转和缩放
      • 移动几何体的顶点 bufferGeometry.translate
        • 几何体平移与物体平移
      • 几何体旋转与模型旋转(缩放同理)

几何体的顶点position、法向量normal及uv坐标

UV映射

UV映射是一种将二维纹理映射到三维模型表面的技术。
在这个过程中,3D模型上的每个顶点都会被赋予一个二维坐标(U, V)
这些坐标用于将纹理图像上的像素与模型表面上的点进行对应。

UV坐标系

U和V分别表示纹理坐标的水平和垂直方向,使用UV来表达纹理的坐标系。
UV坐标的取值范围是0~1,纹理贴图左下角对应的UV坐标是(0,0),右上角对应的坐标(1,1)。
在这里插入图片描述

UV坐标与顶点坐标

类型含义属性
UV坐标该顶点在纹理上的二维坐标(U, V)geometry.attributes.uv
顶点坐标3D/2D模型中每个顶点的空间坐标(x, y, z)geometry.attributes.position
  • 位置关系是一一对应的,每一个顶点位置对应一个纹理贴图的位置
  • 顶点位置用于确定模型在场景中的形状,而UV坐标用于确定纹理在模型上的分布。

设置UV坐标

案例1:使用PlaneGeometry创建平面缓存几何体
// 图片路径public/assets/panda.png
let uvTexture = new THREE.TextureLoader().load("/assets/panda.png");// 创建平面几何体
const planeGeometry = new THREE.PlaneGeometry(100, 100);
console.log("planeGeometry.attributes.position",planeGeometry.attributes.position.array);
console.log("planeGeometry.attributes.uv",planeGeometry.attributes.uv.array);
console.log("planeGeometry.index",planeGeometry.index.array);// 创建材质
const planeMaterial = new THREE.MeshBasicMaterial({map: uvTexture,
});
// 创建平面
const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
// 添加到场景
scene.add(planeMesh);
planeMesh.position.x = -3;

在这里插入图片描述
贴图正确显示,查看positionuv发现设置贴图时已自动计算出uv坐标
在这里插入图片描述

案例2:使用BufferGeometry创建平面缓存几何体

1.使用BufferGeometry创建平面缓存几何体,通过map设置贴图。

let uvTexture = new THREE.TextureLoader().load("/assets/panda.png");
// 创建平面几何体
const geometry = new THREE.BufferGeometry();
// 使用索引绘制
const vertices = new Float32Array([-50, 50, 0, 50, 50, 0, -50, -50, 0,50, -50,0
]);
// 创建顶点属性
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
// 创建索引
const indices = new Uint16Array([0, 2, 1, 2, 3, 1]);
// 创建索引属性
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
// 创建材质
const material = new THREE.MeshBasicMaterial({map: uvTexture,
});
const plane = new THREE.Mesh(geometry, material);
scene.add(plane);
plane.position.x = 3;
console.log("geometry.attributes.position",geometry.attributes.position.array);
console.log("geometry.attributes.uv",geometry.attributes.uv);
console.log("geometry.index",geometry.index.array);

贴图并没有生效,通过打印发现BufferGeometry没有uv坐标,需要自定义uv坐标
在这里插入图片描述

2.根据纹理坐标将纹理贴图的对应位置裁剪映射到几何体的表面上


let uvTexture = new THREE.TextureLoader().load("/assets/panda.png");
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([-50, 50, 0, 50, 50, 0, -50, -50, 0,50, -50,0
]);
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
const indices= new Uint16Array([0, 2, 1, 2, 3, 1]);
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
const material = new THREE.MeshBasicMaterial({map: uvTexture,
});
const plane = new THREE.Mesh(geometry, material);
scene.add(plane);
plane.position.x = 3;
const uv = new Float32Array([0,1,1,1,0,0,1,0
]);
geometry.attributes.uv = new THREE.BufferAttribute(uv, 2);

法向量 - 顶点法向量光照计算

太阳光照在一个物体表面,物体表面与光线夹角位置不同的区域明暗程度不同。

法向量 用于根据光线与物体表面入射角,计算得到反射角(光从哪个角度反射出去)。光照和法向量的夹角决定了平面反射出的光照强度。
在这里插入图片描述

在Threejs中表示物体的网格模型Mesh的曲面是由一个一个三角形构成,所以为了表示物体表面各个位置的法线方向,可以给几何体的每个顶点定义一个方向向量,通过属性geometry.attributes.normal设置。

一个三角面只会有一个法向量。一个顶点会属于不同的三角面,因此一个顶点会有多个法向量。红色短线表示顶点法向量,绿色短线表示面法向量

在这里插入图片描述

案例1:不设置顶点法向量平面几何体与自带顶点法向量的平面几何体对比

1.准备两个平面几何,使用同一个材质。一个使用已经设置了法向量的PlaneGeometry创建,另一个使用默认没设置法向量的BufferGeometry创建

// 没设置法向量的BufferGeometry
const bufferGeometry = new THREE.BufferGeometry();
const vertices = new Float32Array([-50, 50, 0, 50, 50, 0, -50, -50, 0,50, -50,0
]);
bufferGeometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
const indices = new Uint16Array([0, 2, 1, 2, 3, 1]);
bufferGeometry.setIndex(new THREE.BufferAttribute(indices, 1));
const material = new THREE.MeshBasicMaterial({map: uvTexture,
});
const bufferPlane = new THREE.Mesh(bufferGeometry, material);
scene.add(bufferPlane);
bufferPlane.position.x = -100;
const uv = new Float32Array([0,1,1,1,0,0,1,0
]);
bufferGeometry.attributes.uv = new THREE.BufferAttribute(uv, 2);
// 自带法向量的PlaneGeometry
const planeGeometry = new THREE.PlaneGeometry(100, 100);
const planeMesh = new THREE.Mesh(planeGeometry, material);
scene.add(planeMesh);
planeMesh.position.x = 100;

2.给模型设置环境贴图后,可以将光反射的环境部分映射到模型上(类似镜子将人反射在镜子上面),法向量用于计算,光从哪里反射出去。

// 设置环境贴图
const loader = new THREE.TextureLoader();
loader.load("/assets/test.jpg",(envMap)=>{envMap.mapping = THREE.EquirectangularReflectionMapping;// 设置反射的方式material.envMap = envMap; // 设置环境贴图scene.background = envMap; // 将这幅图设置为环境(可选)
})

可以发现,没有法向量的平面几何体没有对光进行反射
在这里插入图片描述

案例2:设置法向量

方式1 computeVertexNormals方法

bufferGeometry.computeVertexNormals () 提供了计算顶点法向量的方法,所以只需要让BufferAttribute创建的平面几何体计算顶点法向量即可

const bufferGeometry = new THREE.BufferGeometry();
const vertices = new Float32Array([-50, 50, 0, 50, 50, 0, -50, -50, 0,50, -50,0
]);
bufferGeometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
const indices = new Uint16Array([0, 2, 1, 2, 3, 1]);
bufferGeometry.setIndex(new THREE.BufferAttribute(indices, 1));
const material = new THREE.MeshBasicMaterial({map: uvTexture,
});
const bufferPlane = new THREE.Mesh(bufferGeometry, material);
scene.add(bufferPlane);
bufferPlane.position.x = -100;
const uv = new Float32Array([0,1,1,1,0,0,1,0
]);
bufferGeometry.attributes.uv = new THREE.BufferAttribute(uv, 2);
bufferGeometry.computeVertexNormals(); // 增加

在这里插入图片描述

方式2:自定义normal属性值

本来矩形由2个三角形组成,也就是6个顶点。但有些顶点重复,为了复用我们也设置了顶点索引。所以这里的法向量也按照顶点索引来设置。

// 顶点索引 [0, 2, 1, 2, 3, 1]const normals = new Float32Array([0, 0, 1,0, 0, 1,        0, 0, 1,0, 0, 1
])
bufferGeometry.setAttribute("normal", new THREE.BufferAttribute(normals, 3));
引入顶点法向量辅助器VertexNormalsHelper

语法:new VertexNormalsHelper( object : Object3D, size : Number, color : Hex, linewidth : Number )
object:要渲染顶点法线辅助的对象
size (可选的)箭头的长度,默认为 1
color 16进制颜色值. 默认为 0xff0000
linewidth (可选的) 箭头线段的宽度,默认为 1
继承链:Object3D → Line → VertexNormalsHelper

为了更方便调试,可以引入顶点法向量辅助器

import { VertexNormalsHelper } from 'three/addons/helpers/VertexNormalsHelper.js';// 这里的参数是模型,不是几何体
const vertexNormalsHelper= new VertexNormalsHelper(bufferPlane, 8.2, 0xff0000);
scene.add(vertexNormalsHelper);

在这里插入图片描述

几何体的移动、旋转和缩放

BufferGeometry重写了Object3D的同名方法,几何变换的本质是改变几何体的顶点数据

在这里插入图片描述

方法描述
bufferGeometry.scale ( x : Float, y : Float, z : Float )从几何体原始位置开始缩放几何体
bufferGeometry.translate ( x : Float, y : Float, z : Float )从几何体原始位置开始移动几何体,本质改变的是顶点坐标
bufferGeometry.rotateX/rotateY/rotateZ( radians : Float )沿着对象坐标系(局部空间)的主轴旋转几何体,参数是弧度

移动几何体的顶点 bufferGeometry.translate

这里需要区分移动几何体的顶点和移动物体,一般情况下选择移动物体,当顶点本身就偏离需要将几何体中心移动到原点时选择移动几何体(消除中心点偏移)。

几何体的变换由于直接将最终计算结果设置为顶点坐标,所以很难追逐到是否发生了变换。

-使用描述
移动几何体的顶点bufferGeometry.translate ( x : Float, y : Float, z : Float )改变几何体的 ,geometry.attributes.position属性
移动物体object3D.position : Vector3移动对象的局部位置
  • 任何一个模型的本地坐标(局部坐标)就是模型的.position属性。
  • 一个模型的世界坐标,模型自身.position和所有父对象.position累加的坐标。

案例

const bufferGeometry = new THREE.BufferGeometry();
const vertices = new Float32Array([-50, 50, 0, 50, 50, 0, -50, -50, 0,50, -50,0
]);
bufferGeometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
const indices = new Uint16Array([0, 2, 1, 2, 3, 1]);
bufferGeometry.setIndex(new THREE.BufferAttribute(indices, 1));
const material = new THREE.MeshBasicMaterial();
const bufferPlane = new THREE.Mesh(bufferGeometry, material);
// 移动顶点
bufferGeometry.translate(50,0,0) 
scene.add(bufferPlane);
// 物体的局部坐标仍然在(0,0,0)  几何体的顶点坐标x轴都加了50
console.log(bufferPlane.position,bufferGeometry.attributes.position)

在这里插入图片描述

几何体平移与物体平移

几何体平移geometry.translate(50,0,0) 移动几何体
1.世界坐标没变化,还是(0,0,0)
2.本质是改变了顶点坐标
在这里插入图片描述

模型平移mesh.ttanslateX(50) 沿X轴移动50个单位
1.世界坐标变为(50,0,0)
2.对象坐标系(局部空间/几何对象坐标系)跟随,整体移动
在这里插入图片描述

几何体旋转与模型旋转(缩放同理)

-方法本质修改
几何体旋转bufferGeometry.rotateX( rad : Float)顶点坐标
物体旋转object3D…rotateX/.rotateY /.rotateZ ( rad : Float)rotation

几何体旋转

const bufferGeometry = new THREE.BufferGeometry();
const vertices = new Float32Array([-50, 50, 0, 50, 50, 0, -50, -50, 0,50, -50,0
]);
bufferGeometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
const indices = new Uint16Array([0, 2, 1, 2, 3, 1]);
bufferGeometry.setIndex(new THREE.BufferAttribute(indices, 1));
const material = new THREE.MeshBasicMaterial();
const bufferPlane = new THREE.Mesh(bufferGeometry, material);
// 几何体旋转
bufferGeometry.rotateX(Math.PI / 2);
scene.add(bufferPlane);
console.log(bufferPlane.rotation,bufferGeometry.attributes.position)

在这里插入图片描述
物体旋转

const bufferGeometry = new THREE.BufferGeometry();
const vertices = new Float32Array([-50, 50, 0, 50, 50, 0, -50, -50, 0,50, -50,0
]);
bufferGeometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
const indices = new Uint16Array([0, 2, 1, 2, 3, 1]);
bufferGeometry.setIndex(new THREE.BufferAttribute(indices, 1));
const material = new THREE.MeshBasicMaterial();
const bufferPlane = new THREE.Mesh(bufferGeometry, material);
// 物体旋转
bufferPlane.rotateX(Math.PI / 2) 
scene.add(bufferPlane);
console.log(bufferPlane.rotation,bufferGeometry.attributes.position)

在这里插入图片描述

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

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

相关文章

python 3.7.3的安装

参考 Linux安装Python3.7-良许Linux教程网 (lxlinux.net) 1、Index of /ftp/python/3.7.9/ 1、安装gcc,yum -y install gcc 2、 yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel…

记录 re:Invent 大会,使用 PartyRock 编写我们第一个 AI 应用以及心得

如果说 2023 年什么应用技术最火,那么说是 OpenAI 为代表的 ChatGPT 在 AI 方面的突破和发展,是完全没有任何的争议的。 随后,各大云厂商以及应用集成商甚至垂直领域的服务提供商都有了对应的 AI 模型。我们开玩笑的说,这个好比多…

Windows 远程控制 Mac 电脑怎么操作

要从 Windows 远程控制 Mac 电脑,您可以使用内置 macOS 功能或第三方软件解决方案。以下是一些方法: 一、使用内置 macOS 功能(屏幕共享) 1、在 macOS 上启用屏幕共享 转至系统偏好设置 > 共享;选中“屏幕共享”…

ISO26262 --- FSC功能安全概念

一、目的 a)按照安全目标,定义相关项功能行为或降级的功能行为 b)按照安全目标,定义用于合理,及时地探测和控制相关故障的约束条件 c)定义相关项层面的策略或者措施,通过相关项自身,驾驶员或外部措施来实现要求的故…

【微服务生态】Elasticsearch

文章目录 一、概述二、下载和部署2.1 单机部署2.2 集群部署2.2.1 环境配置2.2.2 安装及部署 三、基本操作3.1 概述3.2 HTTP 操作3.2.1 索引操作3.2.2 文档操作3.2.3 关系映射3.2.4 高级查询 3.3 Java API 操作 四、Elasticsearch 进阶4.1 核心概念4.2 系统架构4.3 分布式集群4.…

02_第二章 HTMLCSS

文章目录 第二章 HTML&CSS一 HTML入门1.1 HTML&CSS&JavaScript的作用1.2 什么是HTML1.3 什么是超文本1.4 什么是标记语言1.5 HTML基础结构1.6 HTML的入门程序1.7 HTML概念词汇解释1.8 HTML的语法规则1.9 开发工具VsCode的安装和使用1.10 在线帮助文档 二 HTML常见标…

Phind-70B-运行速度提高4倍的同时,缩小了与GPT-4 Turbo在代码质量上的差距

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

「Web架构模式」模式:前端的后端(BFF)

面向用户界面和外部方的单用途边缘服务 介绍 随着web的出现和成功,交付用户界面的实际方式已经从厚客户端应用程序转变为通过web交付的界面,这一趋势也使基于SAAS的解决方案总体上得以发展。通过web提供用户界面的好处是巨大的——主要是因为发布新功能的…

CMake管理CUDA并使用cuSOLVER等

一、出现问题 我在使用官方案例的时候,使用VS2022CMake管理编译的时候出现如下的错误: 官方CMakeLists.txt: cmake_minimum_required(VERSION 3.9)set(ROUTINE bicgstab)project("${ROUTINE}_example"DESCRIPTION "GPU-Acce…

软件版本号解读(语义化SemVer、日历化CalVer及标识符)

1. 版本控制规范 1.1. 语义化版本(SemVer) 版本格式:主版本号.次版本号.修订号,版本号递增规则: 主版本号(MAJOR version):添加了不兼容的 API 修改,次版本号(MINOR version):添加…

第3部分 原理篇2去中心化数字身份标识符(DID)(3)

3.2.2.4. DID文档 (DID Document) 本聪老师:DID标识符和DID URL还都只是ID,必须为它附加一个基本属性才可以证明是该主体独有的。这个就是我们下面介绍的DID文档。 本聪老师:每个DID标识符都唯一对应一个DID文档,也可以说&#x…

【前端素材】推荐优质后台管理系统Symox模板(适用电商,附带源码)

一、需求分析 后台管理系统是一种用于管理网站、应用程序或系统的工具,它通常作为一个独立的后台界面存在,供管理员或特定用户使用。下面详细分析后台管理系统的定义和功能: 1. 定义 后台管理系统是一个用于管理和控制网站、应用程序或系统…

【C语言】内存操作,内存函数篇---memcpy,memmove,memset和memcmp内存函数的使用和模拟实现【图文详解】

欢迎来CILMY23的博客喔,本篇为​【C语言】内存操作,内存函数篇---memcpy,memmove,memset和memcmp内存函数的使用和模拟实现【图文详解】,图文讲解四种内存函数,带大家更深刻理解C语言中内存函数的操作&…

Seurat包学习:如何查看R包函数源代码

​我们很多时候都很好奇作者的r包是如何写出来的,手痒的时候就想学习一下源码,顺便改一改 问题来源 为什么要写今天这个推文呢? 起因是因为我想使用seurat自带函数画热图,奈何这个图不是那么好看 DoHeatmap(pbmc,features fea…

[HTML]Web前端开发技术28(HTML5、CSS3、JavaScript )JavaScript基础——喵喵画网页

希望你开心,希望你健康,希望你幸福,希望你点赞! 最后的最后,关注喵,关注喵,关注喵,佬佬会看到更多有趣的博客哦!!! 喵喵喵,你对我真的…

编译GreatSQL with RocksDB引擎

GreatSQL里也能用上RocksDB引擎 1. 前言 RocksDB 是基于Facebook 开源的一种支持事务的、高度可压缩、高性能的MyRocks存储引擎,特别适用于高度压缩和大容量的数据。以下是一些关键特点: 高性能: LSM 树结构使得RocksDB在写入密集型负载下表现…

2024-02-23 作业

作业要求: 1.自己实现单向循环链表的功能 2.整理思维导图 3.复习前面顺序表和链表的代码,重写链表逆置函数 1.自己实现单向循环链表的功能 运行代码: main.c #include "loop_list.h" int main(int argc, const char *argv[]) {loop_p H cr…

07 STL 简介

目录 什么是STLSTL的版本STL的六大组件STL的重要性如何学习STLSTL的缺陷 1. 什么是STL c标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构和算法的软件框架 2. STL的版本 原始版本 Alexander Stepanov、Meng Lee在惠普实验室的…

【Python笔记-设计模式】装饰器模式

一、说明 装饰器模式是一种结构型设计模式,旨在动态的给一个对象添加额外的职责。 (一) 解决问题 不改变原有对象结构的情况下,动态地给对象添加新的功能或职责,实现透明地对对象进行功能的扩展。 (二) 使用场景 如果用继承来扩展对象行…