threejs实例之十:汽车模型展览


<template>
    <div>
        <div class="colors">
           <span @click="selectColor(index)" class="item" 
                v-for="(item,index) in colors" 
                :style="{backgroundColor:item.value}">{
     
     {item.name}}</span>
        </div>
        <div class="material">
           <span @click="selectMeterial(index)" class="material-item" 
                v-for="(item,index) in materials" 
                :style="{backgroundColor:item.value}">{
     
     {item.name}}</span>
        </div>
    </div>
  </template>
  
  <script setup>
  import { 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 scene=new THREE.Scene()

  //相机
  const camara=new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000)
  camara.position.set(1,4,10)
  
  //平面
  const grid=new THREE.GridHelper(30,30)
  scene.add(grid)
  
  //颜色数据

    const colors=[
        {name:"粉色",value:"#f8c6fd"},
        {name:"亮红",value:"#f00"},
        {name:"天蓝",value:"#84bbeb"},
        {name:"紫色",value:"#ac84eb"},
    ]

    //材质
    const materials=[
        {name:"磨砂",value:1},
        {name:"烤漆",value:0},
    ]

  //几何体
//   const cube=new THREE.Mesh(
//       new THREE.BoxGeometry(2,2,2),
//       new THREE.MeshBasicMaterial({color:"#f90"})
//   )
//   cube.position.set(0,1,0)
//   scene.add(cube)



//创建材质

let bodyMaterial=new THREE.MeshPhysicalMaterial({
    color:"#f00",
    metalness:1,
    roughness:0.5,
    clearcoat:1,
    clearcoatRoughness:0
})
let frontMaterial=new THREE.MeshPhysicalMaterial({
    color:"#f00",
    metalness:1,
    roughness:0.5,
    clearcoat:1,
    clearcoatRoughness:0
})
let hoodMaterial=new THREE.MeshPhysicalMaterial({
    color:"#f00",
    metalness:1,
    roughness:0.5,
    clearcoat:1,
    clearcoatRoughness:0
})
let wheelMaterial=new THREE.MeshPhysicalMaterial({
    color:"#f00",
    metalness:1,
    roughness:0.1,
})

let glassMaterial=new THREE.MeshPhysicalMaterial({
    color:"#fff",
    metalness:0,
    roughness:0.1,
    transmission:1,
    transparent:true
})
//加载模型

const loader=new GLTFLoader()
const dracoLoader=new DRACOLoader()
dracoLoader.setDecoderPath("public/draco/")
loader.setDRACOLoader(dracoLoader)

loader.load("model/bmw01.glb",(texture)=>{
    let bmw=texture.scene
    bmw.traverse((child)=>{

        if(child.isMesh&&child.name.includes("轮毂")){
            wheels.push(child)
            child.material=wheelMaterial
        }
        //车身
        if(child.isMesh&&child.name.includes("Mesh002")){
            carBody=child
            carBody.material=bodyMaterial
        }
        //前脸
        if(child.isMesh&&child.name.includes("前脸")){
            frontCar=child
            frontCar.material=frontMaterial
        }
        //引擎盖1
        if(child.isMesh&&child.name.includes("引擎盖")){
            hoodCar=child
            hoodCar.material=hoodMaterial
        }
        //挡风玻璃
        if(child.isMesh&&child.name.includes("挡风玻璃")){
            glassCar=child;
            glassCar.material= glassMaterial
        }
    })
    scene.add(bmw)

})

  //光源
let light1=new THREE.DirectionalLight("#fff",1)
light1.position.set(0,0,10)
scene.add(light1)
let light2=new THREE.DirectionalLight("#fff",1)
light2.position.set(0,0,-10)
scene.add(light2)
let light3=new THREE.DirectionalLight("#fff",1)
light3.position.set(-10,0,0)
scene.add(light3)
let light4=new THREE.DirectionalLight("#fff",1)
light4.position.set(0,10,0)
scene.add(light4)
let light5=new THREE.DirectionalLight("#fff",0.3)
light5.position.set(0,-10,0)
scene.add(light5)
let light6=new THREE.DirectionalLight("#fff",0.3)
light6.position.set(5,10,0)
scene.add(light6)
let light7=new THREE.DirectionalLight("#fff",0.3)
light7.position.set(0,10,5)
scene.add(light7)
let light8=new THREE.DirectionalLight("#fff",1)
light8.position.set(-5,10,5)
scene.add(light8)

//
let wheels=[]
let carBody,frontCar,hoodCar,glassCar







  //渲染器
  const renderder=new THREE.WebGLRenderer({
      antialias:true
  })
  renderder.setSize(window.innerWidth,window.innerHeight)
  renderder.setClearColor("#ccc")
  document.body.appendChild(renderder.domElement)
  
  //控制器
  const control=new OrbitControls(camara,renderder.domElement)
  
  
  //动画

  
  //渲染函数
  const render=()=>{
      renderder.render(scene,camara)
      requestAnimationFrame(render)
  }
  render()
  
  
  window.addEventListener("resize",()=>{
      camara.aspect=window.innerWidth/window.innerHeight;
      camara.updateProjectionMatrix()
  })
  
  const selectColor=(index)=>{
    console.log("colors[index]:",index)
    // bodyMaterial.color.set(colors[index].value.value)
    // frontMaterial.color.set(colors[index].value.value)
    // hoodMaterial.color.set(colors[index].value.value)

    bodyMaterial.color.set(colors[index].value)
    frontMaterial.color.set(colors[index].value)
    hoodMaterial.color.set(colors[index].value)
  }

  const selectMeterial=(index)=>{
    console.log("material[index]:",index)
    bodyMaterial.clearcoatRoughness=materials[index].value
    frontMaterial.clearcoatRoughness=materials[index].value
    hoodMaterial.clearcoatRoughness=materials[index].value
  }

  </script>
  <style  scoped>
  .a{
    color:#ac84eb
  }
  .colors{
    width: 600px;
    position:absolute;
    top:20px;
    right:0;
    z-index: 10;
    display: flex;
    justify-content: flex-end;
    padding-right:20px
  }
  .item{
    display: inline-block;
    padding: 3px 10px;
    margin-left:6px;
    text-align: center;
    color:#fff;
    border-radius:24px;
  }
  .material{
    width: 600px;
    position:absolute;
    top:60px;
    right:0;
    z-index: 10;
    display: flex;
    justify-content: flex-end;
    padding-right:20px
  }
  .material-item{
    display: inline-block;
    padding: 3px 10px;
    margin-left:6px;
    text-align: center;
    background:#333;
    color:#fff;
    border-radius:24px;
  }
  </style>

这里有一点要注意:就是载入模型的路径问题:

const loader = new GLTFLoader();
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath("public/");
dracoLoader.preload();

loader.setDRACOLoader(dracoLoader);
loader.load("bmw01.glb", glb => {
  console.log("glb", glb);
  mesh = new THREE.Mesh(glb, new THREE.MeshStandardMaterial({ color: "#fff" }));
  scene.add(mesh);
  renderder.render(scene, camara);
});

本案例中public文件夹下存在四个文件,分别是draco_decoder,draco_decoder.wasm,draco_encoder.js,draco_wasm_wrapper.js,他们用来解析模型,一定要注意这四个文件一定要放到dracoLoader.setDecoderPath("");的目录下。特别注意,这里的是setDecoderPath()而不是setPath(),之前就是因为不小心自动补全写成了setPath导致模型加载一直报404,如果设置解析的目录dracoLoader.setDecoderPath("public/model");那么这四个文件就必须要在public/model目录下,第二点:注意这四个文件的版本与当前项目的three.js版本是否一致。否则会无法解析。最好的办法是安装最新的three.js包。同时在three.js的github找到dev分支找到exa,ples/jsm/libs/draco目录,抽取该目录下的四个js文件,也就是draco_decoder,draco_decoder.wasm,draco_encoder.js,draco_wasm_wrapper.js,放到dracoLoader.setDecoderPath("");所设置的目录下,

猜你喜欢

转载自blog.csdn.net/baidu_41601048/article/details/128618763