【threejs教程】threejs中的边边角角:几何体详解

简介: 【8月更文挑战第6天】threejs中的几何体详解

简介

本系列教程需要具备threejs的基础入门知识,了场景、几何体、相机等基础概念。
学习本教程之前,建议学习【纹理贴图与环境贴图】的基础知识。

几何体简介

通过前置知识,我们已经对几何体有了初步的认识。
比如最基本的立方体BoxGeometry

// 2、创建几何体Geometry模型
const geometry = new THREE.BoxGeometry(20, 20, 20);

GIF 2023-11-18 23-04-20.gif
还有球形几何体SphereGeometry

// 2、创建球体模型
const sphere = new THREE.SphereGeometry(20);

GIF 2023-11-18 23-04-57.gif
从官方示例图中我们可以看出,几何体都是由面组成的,所以想要深入了解几何体,我们就需要从最基本的开始。

平面几何体PlaneGeometry

Api:https://threejs.org/docs/#api/zh/geometries/PlaneGeometry
PlaneGeometry一个用于生成平面几何体的类。其语法示例

PlaneGeometry(width , height, widthSegments, heightSegments)
  • width — 平面沿着 X 轴的宽度。默认值是 1。
  • height — 平面沿着 Y 轴的高度。默认值是 1。
  • widthSegments — (可选)平面的宽度分段数,默认值是 1。
  • heightSegments — (可选)平面的高度分段数,默认值是 1。

    代码示例

    const geometry = new THREE.PlaneGeometry(40, 40);
    const material = new THREE.MeshBasicMaterial({
         
          color: 0xffff00, side: THREE.DoubleSide });
    const mesh = new THREE.Mesh(geometry, material);
    // 设置模型mesh的xyz坐标
    mesh.position.set(0, 40, 0);
    scene.add(mesh);
    

    side: THREE.DoubleSide 是用来设定材质的哪一面应该被渲染。THREE.DoubleSide 意味着两面都会被渲染。

GIF 2023-11-18 23-14-09.gif

几何体的模型数据

我们在数据层面看看这个最基本的几何体的结构长什么样
GIF 2023-11-18 23-19-22.gif
可以看到,一个几何体的对象包含了非常多的数据
image.png
在Three.js中,geometry 对象的 attributes 属性包含了许多用于定义几何体形状和外观的信息。其中,normal、position 和 uv 是最常用的几种。

  1. normal: 法线(Normal)是三维图形中用来表示表面向外方向的一个矢量。在渲染过程中,光线会根据表面的法线方向来确定如何照亮表面。通过改变法线的方向,可以改变表面受光的方向和形状的阴影效果。
  2. position: 位置(Position)属性定义了每个顶点在三维空间中的坐标。这些坐标被用来确定顶点如何连接以及它们如何形成形状。每个顶点的位置都是相对于原点的,原点(0,0,0)通常在形状的中心。
  3. uv: UV坐标(也称为U、V、V1、V2等)定义了纹理映射的位置和方向。纹理映射是一种将二维图像(纹理)映射到三维形状表面的技术。UV坐标是用来确定纹理如何映射到形状的顶点上的。它们通常被用来实现复杂的表面细节和外观,例如通过将纹理映射到物体的表面上。

这些属性一起定义了物体的形状、外观和光照效果。

上图中,我们可以看到geometry的原型链指向BufferGeometry构造函数,这意味着它具备BufferGeometry的所有属性和方法。

BufferGeometry

我先看看官网是如何定义它的:
image.png
简单来说,它是所有不同几何体的基类,使用它可以创造出所有的几何体,比如立方体BoxGeometry、球体SphereGeometry等等。

使用BufferGeometry创建平面几何体

我们参考官方代码示例,创建一个平面几何体

const geometry = new THREE.BufferGeometry();
// 创建一个简单的矩形. 在这里我们左上和右下顶点被复制了两次。
// 因为在两个三角面片里,这两个顶点都需要被用到。
const vertices = new Float32Array( [
    -1.0, -1.0,  1.0,
     1.0, -1.0,  1.0,
     1.0,  1.0,  1.0,

     1.0,  1.0,  1.0,
    -1.0,  1.0,  1.0,
    -1.0, -1.0,  1.0
] );

// itemSize = 3 因为每个顶点都是一个三元组。
geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
const material = new THREE.MeshBasicMaterial( {
   
    color: 0xff0000 } );
const mesh = new THREE.Mesh( geometry, material );

我们对核心代码也做出一点点调整,方便更好的演示效果

<template>
  <div class="wrap" ref="threeContainer"></div>
</template>

<script setup>
import * as THREE from "three";
import {
   
    onMounted, ref } from "vue";
import {
   
    OrbitControls } from "three/addons/controls/OrbitControls.js";

const threeContainer = ref(null);

// 1、创建3D场景对象Scene
const scene = new THREE.Scene();
// 添加背景颜色
const cubeTexture = new THREE.CubeTextureLoader().setPath("/sky/").load(["posx.jpg", "negx.jpg", "posy.jpg", "negy.jpg", "posz.jpg", "negz.jpg"]);
scene.background = cubeTexture;

// 添加网格地面
const gridHelper = new THREE.GridHelper(200, 10);
scene.add(gridHelper);

// 添加三维坐标轴
const axesHelper = new THREE.AxesHelper(8);
scene.add(axesHelper);

// 2.使用BufferGeometry创建模型
const geometry = new THREE.BufferGeometry();
// 创建一个简单的矩形. 在这里我们左上和右下顶点被复制了两次。
// 因为在两个三角面片里,这两个顶点都需要被用到。
const vertices = new Float32Array([
  -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0,

  1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0,
]);

// itemSize = 3 因为每个顶点都是一个三元组。
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
const material = new THREE.MeshBasicMaterial({
   
    color: 0xff0000 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

// 3、使用虚拟相机观察模型
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 5, 15);
camera.lookAt(0, 0, 0); //坐标原点

// 4、渲染3D场景到DOM上
const width = 800; //宽度
const height = 500; //高度
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
renderer.setAnimationLoop(animation);
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 添加阻尼
controls.enableDamping = true;
controls.dampingFactor = 0.01;

function animation() {
   
   
  controls.update();
  renderer.render(scene, camera);
}

onMounted(() => {
   
   
  threeContainer.value.appendChild(renderer.domElement);
});
</script>

<style scoped></style>

GIF 2023-11-18 23-48-38.gif
我们也许会很好奇,为什么当移动到图形北面时,看不到物体了?其实很简单,和side: THREE.DoubleSide配置有关。

渲染面side设置

API:https://threejs.org/docs/#api/zh/materials/Material.side
语法结构:

.side : Integer

定义将要渲染哪一面 - 正面,背面或两者。 默认为THREE.FrontSide。其他选项有THREE.BackSideTHREE.DoubleSide

// 双面渲染
const material = new THREE.MeshBasicMaterial({ color: 0xff0000, side: THREE.DoubleSide });

GIF 2023-11-18 23-58-51.gif

渲染线框wireframe

之前的章节中,我们做过线框设置GIF 2023-11-19 10-25-38.gif
我们在代码中体现一下

const material = new THREE.MeshBasicMaterial(
  {
   
    
    color: 0xff0000, 
    side: THREE.DoubleSide, 
  + wireframe: true 
  }
);

GIF 2023-11-19 10-30-22.gif

小节

本节课,我们对几何体进行了一些较为深入的了解,知道了所有几何体继承自BufferGeometry基类,通过BufferGeometry我们也可以创建各种各样形状的几何体。因为正常开发中,一个复杂的模型几乎不会使用这种方式创建,而是直接导出其他软件开发好的模型,所以我们不做深入了解。

相关文章
|
前端开发 JavaScript 定位技术
threejs绘制风羽
threejs绘制风羽
270 0
|
2月前
ThreeJs创建球体
这篇文章讲解了如何在Three.js中创建并添加一个球体到场景中,包括定义球体的几何形状、赋予材质以及最终渲染球体的过程。
55 1
|
2月前
ThreeJs场景中添加视频
这篇文章详细说明了如何在Three.js场景中添加并播放视频,包括视频纹理的创建与应用,以及如何将视频流显示在3D模型的表面上。
47 2
ThreeJs场景中添加视频
|
2月前
Threejs绘制圆锥体
这篇文章讲解了如何在Three.js中创建并正确定向圆锥体,确保其在不同场景下的稳定显示,涵盖了生成圆锥体几何体、设置材质和纹理以及解决可能的倾斜显示问题等内容。
47 1
Threejs绘制圆锥体
|
2月前
Threejs使用CubeCamera实现环境映射
这篇文章详细介绍了如何在Three.js中使用CubeCamera来实现环境映射,包括创建CubeCamera、设置反射材质以及实时更新渲染结果的具体步骤。
77 3
|
2月前
|
JavaScript API 图形学
ThreeJS入门-创建一个正方体
这篇文章介绍了如何使用Three.js创建一个基本的正方体模型,并提供了实现这一功能的详细步骤和代码示例。
48 0
ThreeJS入门-创建一个正方体
|
2月前
Threejs绘制传送带
这篇文章详细介绍了如何使用Three.js绘制一个动态的传送带模型,包括传送带的几何体创建、纹理应用以及实现带体循环移动的动画效果。
39 0
Threejs绘制传送带
|
2月前
ThreeJs创建圆环
这篇文章介绍了如何在Three.js中创建一个圆环(torus),包括设置圆环的几何形状、材质以及将其添加到场景中的具体步骤。
57 0
ThreeJs创建圆环
|
2月前
ThreeJs绘制圆柱体
这篇文章介绍了在Three.js中绘制圆柱体的方法,包括创建圆柱体几何体、设置材质以及将其正确放置在三维场景中的技巧。
55 0
ThreeJs绘制圆柱体
|
4月前
|
API