<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 4개의 파일이 있으며, 이는 모델을 구문 분석하는 데 사용됩니다. 이 4개의 파일은 dracoLoader에 있어야 한다는 점에 유의해야 합니다. .setDecoderPath(" "); 디렉토리. setPath() 대신 setDecoderPath() 에 특히 주의하세요 . 이전에는 자동 완성이 실수로 setPath로 작성되어 모델 로딩이 항상 404를 보고했기 때문이었습니다. 구문 분석된 디렉터리가 설정된 경우 dracoLoader.setDecoderPath("public/ model"); 그런 다음 이 4개 파일은 public/model 디렉터리에 있어야 합니다. 두 번째 사항: 이 4개 파일의 버전이 현재 프로젝트의 three.js 버전과 일치하는지 주의하세요. 그렇지 않으면 구문 분석되지 않습니다. 가장 좋은 방법은 최신 three.js 패키지를 설치하는 것입니다. 동시에 three.js의 github에서 dev 브랜치를 찾고 exa, ples/jsm/libs/draco 디렉터리를 찾고 이 디렉터리에서 4개의 js 파일, 즉 draco_decoder, draco_decoder.wasm, draco_encoder.js를 추출합니다. draco_wasm_wrapper.js를 작성하고 dracoLoader.setDecoderPath("")에 넣습니다. 디렉토리 세트에서,