Three.js开发必备:模型对象和材质详解

Three.js开发必备:模型对象和材质详解

介绍

ThreeJS中,模型对象和材质(Material)是创建3D场景的基本组成部分,一个3D模型通常由几何体(Geometry)和材质(material)组合而成,并通过mesh对象标识。three支持多种类型的集合体如BoxGeometry立方体、SphereGeometry球体、PlaneGeometry平面、CylinderGeometry圆柱体、TorusGeometry环面等。

三维向量Vector3

三维向量Vector3xyz三个分量,threeJS中会用三维向量Vector3表示很多种数据,比如位置.position和缩放.Scale属性等,Vector3对象具有.x.y.z,还具有.set等方法。

定义三维向量Vector3

typescript 复制代码
// 创建一个三维向量
const v3 = new THREE.Vector3(100,100,100)

scale缩放属性

typescript 复制代码
mesh.scale.set(2,2,2)

position 属性

typescript 复制代码
mesh.position.set(100,100,100)
mesh.position.x = 100
mesh.position.y = 100
mesh.position.z = 100

translateX平移

typescript 复制代码
mesh.translateX(100);
mesh.translateY(100);
mesh.translateZ(100);
typescript 复制代码
// 创建一个三维向量
const v3 = new THREE.Vector3(1,1,1)
v3.normalize() // 转化为单位向量
mesh.translateOnAxis(v3,100)

欧拉Euler与角度属性

模型的角度属性.rotation和四元数属性.quaternion都是表示模型的角度状态,指标是方法不同,.rotation属性值是欧拉对象Euler.quaternion属性值是四元数对象Quaternion

javascript 复制代码
// 创建一个欧拉对象
const eu = new THREE.Euler(0,Math.PI,0)
eu.x = Math.PI
console.log("eu:",eu)

改变角度属性

角度属性.rotation的值是欧拉对象Euler,意味着你想改变属性.rotation

javascript 复制代码
const mesh = new THREE.Mesh(geometry,material)
mesh.rotation.y += Math.PI/8;
mesh.rotation.y += Math.PI/8;

旋转方法rotateX()...

模型执行.rotateX().rotateY(),等旋转方法,该面模型的角度属性.rotation

javascript 复制代码
const mesh = new THREE.Mesh(geometry,material)
mesh.rotateX(Math.PI/4)
mesh.rotateY(Math.PI/4)
mesh.rotateZ(Math.PI/4)

旋转动画

javascript 复制代码
function render() {
    mesh.rotateY(0.01)
    mesh.rotateY(0.01)
    mesh.rotateZ(0.02)
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}

模型材质颜色Color对象

如果想修改材质的颜色属性.color,颜色对象有三个属性分别是.r.g.b,表示颜色RGB的三个分量。

基本设置

javascript 复制代码
// 创建一个颜色对象
const color = new THREE.Color(); // 默认是纯白色
color.r = 0;
color.g = 255;
color.b = 0;
material.color = color
const mesh = new THREE.Mesh(geometry,material)

基本方法

javascript 复制代码
const color = new THREE.Color(); // 默认是纯白色
color.setRGB(0,1,1)
material.color = color
javascript 复制代码
// 创建一个颜色对象
const color = new THREE.Color(); // 默认是纯白色
color.setStyle('#00ff00')  
// color.set('#00ff00')	
material.color = color
const mesh = new THREE.Mesh(geometry,material)

模型材质父类Material

父类Material

threeJS官网中,基础网格材质MeshBasicMaterial,漫反射网格材质MeshLambertMaterial,高光网格材质MeshPhongMaterial等网络材质都有一个共同的父类Material

网格材质继承父类属性

JS中,子类都会继承父类的属性和方法,threeJS中的材质同样也是这样,MeshBasicMaterialMeshLambertMaterialMeshPhongMaterial等子类网格材质都会从父类Material继承一些属性和方法,如透明度属性.opcity,面属性.side,是否透明属性.transparent

材质半透明设置

javascript 复制代码
import * as THREE from 'three'
const geometry = new THREE.BoxGeometry(50,50,50)
const material = new THREE.MeshLambertMaterial({
    color:0xffff00
})
material.transparent = true;//开启透明
material.opacity = 0.5;//设置透明度
const mesh = new THREE.Mesh(geometry,material)
export default mesh;

材质面属性.side

材质面属性side默认值是THREE.FrontSide,表示i网格模型正面可以看到,THREE.BackSide表示背面可以看到,THREE.DoubleSide表示双面可以看到。

javascript 复制代码
material.side = THREE.FrontSide // 背面不可见
javascript 复制代码
material.side = THREE.BackSide;//背面可以看到
javascript 复制代码
material.side = THREE.DoubleSide;//双面可见

模型对象的材质和几何体属性

打印msh,geometrys,materials查看属性

javascript 复制代码
	// 创建平面
	const geometrys = new THREE.BoxGeometry(1, 1, 1);
	const materials = new THREE.MeshLambertMaterial({
	  color: 0xffffff,
	  metalness: 0.1,
	  roughness: 0.5,
	});
	const mesh = new THREE.Mesh(geometrys, materials);
	mesh.receiveShadow = true;
	mesh.rotation.x = -0.5 * Math.PI;
	mesh.position.x = 0;
	mesh.position.y = 0;
	mesh.position.z = 0;
	this.scene.add(mesh);
    console.log("mesh", mesh);
    console.log("mesh.geometry", mesh.geometry);
    console.log("mesh.materials", mesh.material);

访问改变模型材质属性

javascript 复制代码
 // 创建平面
    const geometrys = new THREE.BoxGeometry(1, 1, 1);
    const materials = new THREE.MeshLambertMaterial({
      color: 0xffffff,
      metalness: 0.1,
      roughness: 0.5,
    });
    const mesh = new THREE.Mesh(geometrys, materials);
    mesh.receiveShadow = true;
    mesh.rotation.x = -0.5 * Math.PI;
    mesh.position.x = 0;
    mesh.position.y = 0;
    mesh.position.z = 0;
    this.scene.add(mesh);
    mesh.material.color.set(0xffff00);

访问改变模型几何体属性

javascript 复制代码
// 创建平面
const geometrys = new THREE.BoxGeometry(1, 1, 1);
 const materials = new THREE.MeshLambertMaterial({
   color: 0xffffff,
   metalness: 0.1,
   roughness: 0.5,
 });
 const mesh = new THREE.Mesh(geometrys, materials);
 mesh.receiveShadow = true;
 mesh.rotation.x = -0.5 * Math.PI;
 mesh.position.x = 0;
 mesh.position.y = 0;
 mesh.position.z = 0;
 this.scene.add(mesh);
 mesh.geometry.translate(0, 1, 0);

材质或几何体共享

javascript 复制代码
const mesh = new THREE.Mesh(geometrys, materials);
const mesh2 = new THREE.Mesh(geometrys, materials);
mesh.receiveShadow = true;
this.scene.add(mesh);
this.scene.add(mesh2);
mesh2.position.x = 2;

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

克隆.clone()和复制.copy()

Threejs大多数对象都有克隆.clone()和复制.copy()两个方法,点模型Points、线模型Line、网格网格模型Mesh一样具有这两个方法。

克隆方法.clone()

A.copy(B)表示B属性的值赋值给A对应属性,是创建一个新对象,它是原对象的深拷贝。

javascript 复制代码
// 创建平面
const geometrys = new THREE.BoxGeometry(1, 1, 1);
const materials = new THREE.MeshLambertMaterial({
  color: 0xffffff,
  metalness: 0.1,
  roughness: 0.5,
});
const mesh = new THREE.Mesh(geometrys, materials);
const mesh2 = mesh.clone();
// 为了确保材质也是独立的,我们需要单独克隆材质
mesh2.material = mesh.material.clone();
// 现在,对mesh2的材质所做的任何更改都不会影响到原始的mesh
mesh.material.color.set(0xff00ff);
mesh2.material.color.set(0xff0000); // 改变mesh2的颜色为红色
this.scene.add(mesh);
this.scene.add(mesh2);

复制方法.copy()

N = M.clone()表示返回一个和M相同的对象赋值给N,是将一个对象的数据复制到另一个已存在的对象中,而不是创建新对象。

javascript 复制代码
// 创建平面
const geometrys = new THREE.BoxGeometry(1, 1, 1);
const materials = new THREE.MeshLambertMaterial({
  color: 0xffffff,
  metalness: 0.1,
  roughness: 0.5,
});
const mesh = new THREE.Mesh(geometrys, materials);
mesh.material.color.set(0xff00ff);
this.scene.add(mesh);

const mesh2 = new THREE.Mesh(); // 创建一个新的空网格对象
mesh2.copy(mesh);

// 然后,为了确保mesh2拥有独立的几何体和材质,我们需要手动克隆它们
mesh2.geometry = mesh.geometry.clone(); // 克隆几何体
mesh2.material = mesh.material.clone(); // 克隆材质

// 现在,你可以自由地修改mesh2的材质或几何体,而不会影响到mesh1。
// 例如,改变mesh2的材质颜色
mesh2.material.color.set(0xff0000); // 改变颜色为红色
mesh2.position.x = 2;
this.scene.add(mesh2);

使用copy方法同时共享一个炫转角度

javascript 复制代码
<template>
  <div id="container"></div>
</template>

<script>
import * as THREE from "three";
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";

export default {
  name: "three15material",
  components: {},
  mounted() {
    window.addEventListener("resize", () => {
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
    });
    this.init();
  },
  data() {
    return {
      camera: null,
      scene: null,
      renderer: null,
      mesh: null,
      controls: null,
      gui: null,
      cameraHelper: null,
      cameraParams: {
        fov: 75,
        aspect: window.innerWidth / window.innerHeight,
        near: 0.1,
        far: 700,
        zoom: 1,
      },
      pointLightPosition: { x: 2, y: 1, z: 2 }, // 初始化点光源的位置
      sphereLight: null, // 球体光源对象
    };
  },
  methods: {
    allView() {
      this.renderer.domElement.requestFullscreen();
    },
    backAllView() {
      this.renderer.domElement.exitFullscreen();
    },
    init() {
      this.gui = new GUI();
      const container = document.body;

      // 场景初始化
      this.scene = new THREE.Scene();

      // 相机初始化
      this.camera = new THREE.PerspectiveCamera(
        this.cameraParams.fov,
        this.cameraParams.aspect,
        this.cameraParams.near,
        this.cameraParams.far
      );
      this.camera.position.set(2, 2, 5);
      this.camera.lookAt(0, 0, 0);

      // 渲染器初始化
      this.renderer = new THREE.WebGLRenderer({
        width: window.innerWidth,
        height: window.innerHeight,
        scale: 1,
        antialias: true,
        tonemapping: THREE.FilmicOperator,
        brightness: 2.5,
      });
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.renderer.shadowMap.enabled = true;
      this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
      container.appendChild(this.renderer.domElement);
      this.scene.background = new THREE.Color(0x1f1f1f);

      // 创建平面
      const geometrys = new THREE.BoxGeometry(1, 1, 1);
      const materials = new THREE.MeshLambertMaterial({
        color: 0xffffff,
        metalness: 0.1,
        roughness: 0.5,
      });
      this.mesh = new THREE.Mesh(geometrys, materials);
      this.mesh.material.color.set(0xff00ff);
      this.scene.add(this.mesh);

      this.mesh2 = new THREE.Mesh(); // 创建一个新的空网格对象
      this.mesh2.copy(this.mesh);
      this.mesh2.position.x = 2;
      this.scene.add(this.mesh2);

      // 访问模型材质,并设置材质的颜色属性
      const ambientLight = new THREE.AmbientLight({
        color: 0xffffff,
        intensity: 0.5,
      });
      this.scene.add(ambientLight);
      // 创建一个AxesHelper实例,参数为长度,这里设置为5个单位长度
      const axesHelper = new THREE.AxesHelper(5);

      // 将AxesHelper添加到场景中
      this.scene.add(axesHelper);
      // 创建轨道控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      this.controls.dampingFactor = 0.05;
      // 动画循环
      this.animate();
    },
    animate() {
      this.mesh.rotateY(0.02); // mesh旋转动画
      this.mesh2.rotation.copy(this.mesh.rotation);
      requestAnimationFrame(this.animate);
      this.controls.update();
      this.renderer.render(this.scene, this.camera);
    },
  },
};
</script>
<style scoped></style>

完结

相关推荐
骆驼Lara2 分钟前
前端跨域解决方案(1):什么是跨域?
前端·javascript
离岸听风5 分钟前
学生端前端用户操作手册
前端
onebyte8bits7 分钟前
CSS Houdini 解锁前端动画的下一个时代!
前端·javascript·css·html·houdini
yxc_inspire12 分钟前
基于Qt的app开发第十四天
前端·c++·qt·app·面向对象·qss
一_个前端19 分钟前
Konva 获取鼠标在画布中的位置通用方法
前端
[email protected]1 小时前
Asp.Net Core SignalR导入数据
前端·后端·asp.net·.netcore
小满zs6 小时前
Zustand 第五章(订阅)
前端·react.js
涵信7 小时前
第一节 基础核心概念-TypeScript与JavaScript的核心区别
前端·javascript·typescript
谢尔登7 小时前
【React】常用的状态管理库比对
前端·spring·react.js
编程乐学(Arfan开发工程师)7 小时前
56、原生组件注入-原生注解与Spring方式注入
java·前端·后端·spring·tensorflow·bug·lua