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>

完结

相关推荐
崔庆才丨静觅6 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅7 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅8 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment8 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅8 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊8 小时前
jwt介绍
前端
爱敲代码的小鱼8 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax