THREE加载汽车模型

158 阅读2分钟

三要素 场景 相机 渲染器

物理网格材质(MeshPhysicalMaterial)

<template>
  <div ref="canvasbox">
    <div class="select-box">
      <div class="box">
        <span>车身颜色</span>&nbsp;&nbsp;
        <input type="color" value="#ff0000" @input="changeCarBody">
      </div>
      <div class="box">
        <span>挑选轮毂</span>&nbsp;&nbsp;
        <input type="color" value="#ff0000" @input="changeWhell">
      </div>
    </div>
  </div>
</template>

<script setup>
import { onMounted, ref } from 'vue';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';

const canvasbox = ref(null)
// 车身颜色
const carBody = new THREE.MeshPhysicalMaterial({
  color: 0xff0000,
  metalness: 1, // 金属度
  roughness: 0.5,  //粗糙度
  clearcoat: 1, // 光滑
  clearcoatRoughness: 0, // 粗糙度
})
// 轮毂颜色
const whell = new THREE.MeshPhysicalMaterial({
  color: 0xff0000,
  metalness: 1, // 金属度
  roughness: 0.5,  //粗糙度
  clearcoat: 1, // 光滑
  clearcoatRoughness: 0, // 粗糙度
})
// 前脸
const frontBuilding = new THREE.MeshPhysicalMaterial({
  color: 0xff0000,
  metalness: 1, // 金属度
  roughness: 0.5,  //粗糙度
  clearcoat: 1, // 光滑
  clearcoatRoughness: 0, // 粗糙度
})
// 引擎盖
const engineHood = new THREE.MeshPhysicalMaterial({
  color: 0xff0000,
  metalness: 1, // 金属度
  roughness: 0.5,  //粗糙度
  clearcoat: 1, // 光滑
  clearcoatRoughness: 0, // 粗糙度
})
// 进气口
const airIntake = new THREE.MeshPhysicalMaterial({
  color: 0xff0000,
  metalness: 1, // 金属度
  roughness: 0.5,  //粗糙度
  clearcoat: 1, // 光滑
  clearcoatRoughness: 0, // 粗糙度
})
// 挡风玻璃
const windshield = new THREE.MeshPhysicalMaterial({
  color: 0xffffff,
  metalness: 0,
  transmission: 1,
  roughness: 0,
  transparent: true,
})
// 内饰座椅
const interiorSeats = new THREE.MeshPhysicalMaterial({
  color: 0xffffff,
  metalness: 0,
  transmission: 1,
  roughness: 0,
  transparent: true,
})
const init = () => {
  // 场景
  const scene = new THREE.Scene();
  scene.background = new THREE.Color("#cccccc")
  scene.environment = "#cccccc"

  // 坐标辅助
  // const axesHelper = new THREE.AxesHelper(10)
  // scene.add(axesHelper)

  // 相机
  const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  camera.position.set(0, 2, 4);

  // 渲染器
  const renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.shadowMap.enabled = true;
  canvasbox.value.appendChild(renderer.domElement);

  // 坐标格辅助对象. 坐标格实际上是2维线数组
  const grid = new THREE.GridHelper(30, 30)
  grid.material.opacity = 0.2
  grid.material.transparent = true
  scene.add(grid)

  // 控制器
  const controls = new OrbitControls(camera, renderer.domElement)
  controls.update()


  // 模型加载器
  // 需要解压
  const loader = new GLTFLoader()
  const dracoLoader = new DRACOLoader();
  dracoLoader.setDecoderPath("/draco/gltf/");
  loader.setDRACOLoader(dracoLoader);
  loader.load('/public/baoma/bmw.glb', gltf => {
    console.log(gltf);
    const model = gltf.scene
    model.traverse(child => {
      if (child.isMesh) {
        console.log(child.name);
        if (child.name.includes('Mesh002')) {
          child.material = carBody
        }
        if (child.name.includes('轮毂')) {
          child.material = whell
        }
        if (child.name.includes('前脸')) {
          child.material = frontBuilding
        }
        if (child.name.includes('引擎盖')) {
          child.material = engineHood
        }
        if (child.name.includes('进气口')) {
          child.material = airIntake
        }
        if (child.name.includes('挡风玻璃')) {
          child.material = windshield
        }
        if (child.name.includes('Mesh022')) {
          child.material = interiorSeats
        }
      }
    })
    function animate() {
        requestAnimationFrame(animate);
        model.rotation.y+=0.001
        renderer.render(scene, camera);
      }
      animate();
    scene.add(model)
  }, xhr => { }, err => { console.log(err); })


  // 灯光
  // 前灯光
  const light1 = new THREE.DirectionalLight(0xffffff, 1)
  light1.position.set(0, 0, 10)
  scene.add(light1)
  // 后灯光
  const light2 = new THREE.DirectionalLight(0xffffff, 1)
  light2.position.set(0, 0, -10)
  scene.add(light2)
  // 左灯光
  const light3 = new THREE.DirectionalLight(0xffffff, 1)
  light3.position.set(-10, 0, 0)
  scene.add(light3)
  // 右灯光
  const light4 = new THREE.DirectionalLight(0xffffff, 1)
  light4.position.set(10, 0, 0)
  scene.add(light4)
  // 上灯光
  const light5 = new THREE.DirectionalLight(0xffffff, 1)
  light5.position.set(0, 10, 0)
  scene.add(light5)
  // 下灯光
  const light6 = new THREE.DirectionalLight(0xffffff, 1)
  light6.position.set(0, -10, 0)
  scene.add(light6)
  // 添加光源
  const light7 = new THREE.DirectionalLight(0xffffff, 1);
  light7.position.set(0, 10, 5);
  scene.add(light7);

  // 添加光源
  const light8 = new THREE.DirectionalLight(0xffffff, 1);
  light8.position.set(-5, 10, 0);
  scene.add(light8);

  // 添加光源
  const light9 = new THREE.DirectionalLight(0xffffff, 1);
  light9.position.set(0, 10, -5);
  scene.add(light9);


  // function animate() {
  //   requestAnimationFrame(animate);
  //   renderer.render(scene, camera);
  // }
  // animate();
}

// 车身颜色方法
const changeCarBody = e => {
  const color = e.target.value
  carBody.color.set(color)
  frontBuilding.color.set(color)
  engineHood.color.set(color)
  airIntake.color.set(color)
}
// 轮毂颜色切换
const changeWhell = e => {
  whell.color.set(e.target.value)
}


onMounted(() => { init() })
</script>

<style scoped>
.select-box {
  position: fixed;
  top: 0;
  right: 20px;
  background-color: #e5e5e5;
  border-radius: 10px;
  padding: 20px;
}

.box {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
</style>

image.png