threejs+vue/01 glb模型导入,改变汽车车身颜色

725

一、import引入相关功能

import * as THREE from "three"; // 引入threejs
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; // 引入控制器
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; // 引入GLTFLoader加载器
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader"; // 引入DRACOLoader加载器配合GLTFLoader一起使用

二、场景搭建

let scene, camera, renderer, controls, container; // 定义变量
container = this.$refs.three;  // 容器

// 场景
scene = new THREE.Scene();
scene.background = new THREE.Color("#ccc"); // 设置场景背景颜色
scene.environment = new THREE.Color("#ccc"); // 设置环境光颜色

// 相机
camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
); //透视相机 fov, aspect, near, far 视角,宽高比,近平面,远平面
camera.position.set(0, 2, 6); // 设置相机位置
camera.lookAt(scene.position); // 相机视点

// 渲染器
renderer = new THREE.WebGLRenderer({ antialias: true }); //antialias 抗锯齿
renderer.setSize(window.innerWidth, window.innerHeight); // 画面宽高
renderer.setClearColor("#000"); // 设置画面颜色
container.appendChild(renderer.domElement); // 将画面添加到容器中

// 添加网格地面
let gridHelper = new THREE.GridHelper(10, 10); // 创建一个网格帮助器,参数为网格的宽度和高度
scene.add(gridHelper);
gridHelper.material.transparent = true; // 开启网格帮助器的透明度
gridHelper.material.opacity = 0.5; // 设置网格帮助器的透明度

// 添加控制器
controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // 启用阻尼
controls.minPolarAngle = 0.5; // 最小绕y轴角度
controls.maxPolarAngle = 1.35; // 最大绕y轴角度
controls.zoomSpeed = 0.3; // 缩放速度

// 添加灯光
let light1 = new THREE.DirectionalLight(0xffffff, 1); // 创建一个方向光,参数为光的颜色和强度
light1.position.set(0, 0, 10);
scene.add(light1);
let light2 = new THREE.DirectionalLight(0xffffff, 1);
light2.position.set(0, 0, -10);
scene.add(light2);
let light3 = new THREE.DirectionalLight(0xffffff, 1);
light3.position.set(10, 0, 0);
scene.add(light3);
let light4 = new THREE.DirectionalLight(0xffffff, 1);
light4.position.set(-10, 0, 0);
scene.add(light4);
let light5 = new THREE.DirectionalLight(0xffffff, 1);
light5.position.set(0, 10, 0);
scene.add(light5);
let light6 = new THREE.DirectionalLight(0xffffff, 1);
light6.position.set(0, -10, 0);
scene.add(light6);
let light7 = new THREE.DirectionalLight(0xffffff, 1);
light7.position.set(10, 10, 10);
scene.add(light7);
let light8 = new THREE.DirectionalLight(0xffffff, 1);
light8.position.set(10, 10, -10);
scene.add(light8);
let light9 = new THREE.DirectionalLight(0xffffff, 1);
light9.position.set(-10, 10, 10);
scene.add(light9);
let light10 = new THREE.DirectionalLight(0xffffff, 1);
light10.position.set(-10, 10, -10);
scene.add(light10);

const render = () => {
  renderer.render(scene, camera);
  controls && controls.update();
  requestAnimationFrame(render);
};

render();

一个简单的场景就搭好了,效果如下

Snipaste_2022-07-19_15-41-59.png

三、导入gltf模型

!!! 模型文件要放在public目录下

DRACOLoader需要使用到draco文件夹,可以直接从node_modules文件中复制,!!!同样要放到public目录下面

类似这样

Snipaste_2022-07-19_15-57-27.png

let loader = new GLTFLoader(); // 创建GLTFLoader加载器
let dracoLoader = new DRACOLoader(); // 创建DRACOLoader加载器
dracoLoader.setDecoderPath("./draco/gltf/"); // 设置draco加载器的路径
loader.setDRACOLoader(dracoLoader); // 设置加载器的draco加载器
loader.load(
  "./model/untitled.glb", // 加载模型的路径
  (glb) => {
    let object = glb.scene; // 获取模型的场景
    let rotate = () => {
      object.rotation.y -= 0.001;
      requestAnimationFrame(rotate);
    };
    rotate(); // 为模型添加自动旋转

    object.position.set(0, 0.7, 0); // 设置模型的位置
    scene.add(object); // 添加模型到场景
  }
);

此时模型就已经出来了

Snipaste_2022-07-19_16-11-43.png

四、获取车身模块

将以下代码加入到上面的loader.load中

Object3d traverse方法遍历模型的子节点

object.traverse((child) => {
    if (child.isMesh && child.name.includes("boot001")) { //通过模型名字找到车身
      this.carBody = child; // 保存到本地做修改颜色交互
    }
});

五、车身颜色修改交互

data中定义颜色数组

colors: ["red","green","blue","yellow","pink","purple","black","white"]

页面中加入交互元素

<div class="color-set">
  <h1>修改车身颜色</h1>
  <div class="color-container">
    <div v-for="(item, index) in colors" :key="index">
      <div
        class="color-item"
        :style="{ backgroundColor: item }"
        @click="changeColor(item)"
      ></div>
    </div>
  </div>
</div>

methods中定义方法

changeColor(item) {
  this.carBody.material.color.set(item);
},

六、最终效果

GIF 2022-7-19 15-20-05.gif

七、知识点总结

1.GLTFLoader和DRACOLoader的搭配使用

new DRACOLoader().setDecoderPath //设置解码器路径
new GLTFLoader().setDRACOLoader // 设置加载器的draco加载器

new GLTFLoader.load( url : String, onLoad : [Function](), onProgress : [Function](), onError : [Function]() )
[url] — 包含有 .gltf/ .glb文件路径/URL的字符串。\
[onLoad] — 加载成功完成后将会被调用的函数。该函数接收[parse](<> "Function")所返回的已加载的JSON响应。\
[onProgress] — (可选)加载正在进行过程中会被调用的函数。其参数将会是XMLHttpRequest实例,包含有总字节数.[total](<> "Integer")与已加载的字节数.[loaded](<> "Integer")。\
[onError] — (可选)若在加载过程发生错误,将被调用的函数。该函数接收error来作为参数

2.Object3D.traverse

遍历模型对象

3.color

color.set() //用于设置该颜色的值