项目基础代码
项目初始化
引入three
import * as THREE from 'three';
场景
const scene = new THREE.Scene();
照相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(2, 2, 5);
渲染器
const renderer = new THREE.WebGLRenderer({
antialias: true,
})
renderer.setSize(window.innerWidth, window.innerHeight);
控制器
// 添加控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0, 0); // 轨道控制器可以使得相机围绕目标进行轨道运动, 注意这个位置要确定好
controls.enableDamping = true
controls.update();
渲染函数
const render = () => {
requestAnimationFrame(render);
controls.update();
renderer.render(scene, camera);
}
画布添加到body
<div class="canvas-container" ref="canvasDemo">
let canvasDemo = ref(null);
onMounted(() => {
console.log(canvasDemo.value);
canvasDemo.value.appendChild(renderer.domElement);
})
添加网格地面
const gridHelper = new THREE.GridHelper(10, 10);
gridHelper.material.opacity = 0.2;
gridHelper.material.transparent = true;
scene.add(gridHelper);
模型的加载与展示灯光
模型导入
onMounted(async () => {
let gltfUrl = './model/bmw01.glb';
await loadGLTFModel(gltfUrl);
})
// 解码器的版本一般去本地导入的three复制,不然版本对应不上
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath("./draco/"); // 先把 Draco 解码器文件放置在指定路径./draco/下
dracoLoader.preload();
const gltfLoader = new GLTFLoader();
gltfLoader.setDRACOLoader(dracoLoader);
function loadGLTFModel(url) {
return new Promise((resolve, reject) => {
gltfLoader.load(url, (gltf) => {
const bmw = gltf.scene;
scene.add(bmw);
resolve(); // onLoad callback
}),
undefined, //onProcess callback 不需要可以传undefined
(error) => { // onError callback
reject(error);
}
})
}
展示灯光
function addLight() {
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);
light2.position.set(10, 0, 0);
scene.add(light3);
const light4 = new THREE.DirectionalLight(0xffffff, 1);
light2.position.set(-10, 0, 0);
scene.add(light4);
const light5 = new THREE.DirectionalLight(0xffffff, 1);
light2.position.set(0, 10, 0);
scene.add(light5);
const light6 = new THREE.DirectionalLight(0xffffff, 1);
light2.position.set(5, 10, 0);
scene.add(light6);
const light7 = new THREE.DirectionalLight(0xffffff, 1);
light2.position.set(5, -10, 0);
scene.add(light7);
const light8 = new THREE.DirectionalLight(0xffffff, 1);
light2.position.set(0, -10, 5);
scene.add(light8);
const light9 = new THREE.DirectionalLight(0xffffff, 1);
light2.position.set(0, -10, 0);
scene.add(light9);
}
动态设置车的颜色与材质事件
初始化车的各个对象和各种材质
const bodyMaterial = new THREE.MeshStandardMaterial({
color: 0xff0000,
metalness: 1,
roughness: 0.5,
clearcoat: 1,
clearcoatRoughness: 0,
})
const frontMaterial = new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 1,
roughness: 0.5,
clearcoat: 1,
clearcoatRoughness: 0,
})
const hoodMaterial = new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 1,
roughness: 0.5,
clearcoat: 1,
clearcoatRoughness: 0,
})
const wheelsMaterial = new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 1,
roughtness: 0.1,
})
const glassMaterial = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
metalness: 0.01,
roughness: 0,
transmission: 1,
transparent: true,
})
let carBody, frontCar, hoodCar, glassCar;
let wheels = [];
获取车各部分的对象并设置初始颜色
const bmw = gltf.scene;
bmw.traverse((child) => {
if (child.isMesh) {
console.log(child.name);
}
// 判断是否是轮毂
if (child.isMesh && child.name.includes("轮毂")) {
child.material = wheelsMaterial;
wheels.push(child);
}
// 判断是否是车身
if(child.isMesh && child.name.includes("Mesh002")) {
carBody = child;
carBody.material = bodyMaterial;
}
// 判断是否是前脸
if(child.isMesh && child.name.includes("前脸")) {
frontCar = child;
frontCar.material = frontMaterial;
}
// 判断是否是引擎盖
if(child.isMesh && child.name.includes("引擎盖_1")) {
hoodCar = child;
hoodCar.material = hoodMaterial;
}
// 判断是否是挡风玻璃
if(child.isMesh && child.name.includes("挡风玻璃")) {
glassCar = child;
glassCar.material = glassMaterial;
}
})
切换车的颜色
html
<div class="home-content-title">
<h1>汽车展示与选配</h1>
</div>
<div>
<h2>选择车身颜色</h2>
</div>
<div class="select">
<div class="select-item" v-for="[index, item] of colors.entries()" :key="index" @click="selectColor(index)">
<div class="select-item-color" :style="{backgroundColor: item}"></div>
</div>
</div>
js
let colors = ref([]);
colors.value = [
"red",
"blue",
"green",
"gray",
"orange",
"purple"
];
let selectColor = (index) => {
console.log(index, "11");
bodyMaterial.color.set(colors.value[index]);
frontMaterial.color.set(colors.value[index]);
hoodMaterial.color.set(colors.value[index]);
wheelsMaterial.color.set(colors.value[index]);
glassMaterial.color.set(colors.value[index]);
}
切换车的材质
html
<div><h2>选择贴膜材质</h2></div>
<div class="select">
<div class="select-item" v-for="(item, index) in materials" :key="index" @click="selectMaterials(index)">
<div class="select-item-text"> {{ item.name }} </div>
</div>
</div>
js
let materials = ref([]);
materials = [
{name: "磨砂", value: 1},
{name: "冰晶", value: 0}
];
let selectMaterials = (index) => {
bodyMaterial.clearcoatRoughness = materials[index].value;
frontMaterial.clearcoatRoughness = materials[index].value;
hoodMaterial.clearcoatRoughness = materials[index].value;
}
源码地址
https://github.com/chenyina1999/christmas-card-3d