three.js 项目篇 之 汽车展示与控制车身颜色与贴膜材质

three.js 项目篇 之 汽车展示与操作

创建项目

  • yarn add three gsap

App.vue 代码

<template>
  <div class="home">
    <div class="canvas-container" ref="canvasDom"></div>
    <div class="home-content">
      <div class="home-content-title">
        <h1>汽车展示与选配</h1>
      </div>
      <h2>选择车身颜色</h2>
     <div class="select">
        <div
          class="select-item"
          v-for="(item, index) in colors"
          :key="index"
          @click="selectColor(index)"
        >
          <div
            class="select-item-color"
            :style="{ backgroundColor: item }"
          ></div>
        </div>
      </div>

      <h2>选择贴膜材质</h2>
      <div class="select">
        <div
          class="select-item"
          v-for="(item, index) in materials"
          :key="index"
          @click="selectMaterial(index)"
        >
          <div class="select-item-text" style="margin-right: 5px;">{{ item.name }} </div>
        </div>
      </div> 
    </div>
  </div>
  
</template>

<script setup>
import { ref, onMounted } from 'vue'
import * as THREE from "three"
// 导入轨道控制器 - 控制物体的左右上下移动( 可以设置xyz轴 )
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
// 导入gltf载入库 - 用于创出模型
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
// // import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
let controls;
// 初始化场景
const scene = new THREE.Scene()
// 初始化相机 - 透视相机
const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000)
// 设置相机位置 x y z
camera.position.set(0, 2, 6) 
// 设置宽高比例
camera.aspect = window.innerWidth / window.innerHeight
// 更新相机矩阵
camera.updateProjectionMatrix()
// 把相机添加到场景之中
scene.add( camera );

// 设置渲染器
const renderer = new THREE.WebGL1Renderer({
  // 设置抗锯齿 - 更理想的渲染
  antialias:true,
})
renderer.outputEncoding = THREE.sRGBEncoding; // 设置编码
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth,window.innerHeight)

// // 监听画面变化,更新渲染画面
// window.addEventListener('resize',()=>{
//   // 更新摄像头
//   camera.aspect = window.innerWidth / window.innerHeight
//   // 更新摄像头的头部矩阵
//   camera.updateProjectionMatrix()
//   // 更新渲染器
//   renderer.setSize(window.innerWidth, window.innerHeight)
// })


// 渲染函数 - 每一帧渲染一次
function render() {
  // 渲染下一帧 的时候 会调用 animate 函数
	requestAnimationFrame( render );
	renderer.render( scene, camera );
  controls && controls.update() // 控制器的更新
}

let wheels = []; // 汽车轮毂  
let cartBody,frontCar,hoodCar,glassCar;// cartBody-车身 frontCar-前 hoodCar glassCar-挡风玻璃
// 创建材质
const wheelsMaterial = new THREE.MeshPhysicalMaterial({
  color:0xff0000,
  roughness:0.5,
  metalness:0.1,
})
const cartMaterial = new THREE.MeshPhysicalMaterial({
  color:0xff0000,
  roughness:0.5,
  metalness:1,
  clearcoat:1, // 清洁度
  clearcoatRoughness:0,
})
const frontMaterial = new THREE.MeshPhysicalMaterial({
  // color:0xff0000,
  color:0xff00ff,
  roughness:0.5,
  metalness:1,
  clearcoat:1, // 清洁度
  clearcoatRoughness:0,
})
const hoodMaterial = new THREE.MeshPhysicalMaterial({
  color:0xff0000,
  roughness:0.5,
  metalness:1,
  clearcoat:1, // 清洁度
  clearcoatRoughness:0,
})
const glassMaterial = new THREE.MeshPhysicalMaterial({
  color:0xffffff,
  transimission:1, // 完全通透
  transparent:true,
  roughness:0.1,
  metalness:1,
})

// 设置车身颜色
let colors = ["red", "blue", "green", "gray", "orange", "purple"];
let selectColor = (index) => {
  cartMaterial.color.set(colors[index]);
  frontMaterial.color.set(colors[index]);
  hoodMaterial.color.set(colors[index]);
  wheelsMaterial.color.set(colors[index]);
  // glassMaterial.color.set(colors[index]);
};

// 设置车身 贴膜材质
let materials = [
  { name: "磨砂", value: 1 },
  { name: "冰晶", value: 0 },
];
let selectMaterial = (index) => {
  cartMaterial.clearcoatRoughness = materials[index].value;
  frontMaterial.clearcoatRoughness = materials[index].value;
  hoodMaterial.clearcoatRoughness = materials[index].value;
};

// 将webgl渲染的canvas内容添加到div上
const canvasDom = ref(null)
// dom节点挂载之后 渲染dom节点
onMounted(()=>{
  canvasDom.value.appendChild(renderer.domElement)
  // 初始化渲染背景
  renderer.setClearColor("#000")
  scene.background = new THREE.Color("#ccc")
  scene.enviroment - new THREE.Color("#ccc")
  render() // 渲染函数
  // 添加地面网格
  const gridHelper = new THREE.GridHelper(10,10)
  gridHelper.material.opacity = 0.2
  gridHelper.material.transparent = true
  scene.add(gridHelper)

  // 创建轨道控制器
  controls = new OrbitControls(camera,renderer.domElement)
  controls.update()

  // 添加汽车模型 gltf
  // 实例化gltf载入库
  const loader = new GLTFLoader();
  // 实例化draco载入库
  const dracoLoader = new DRACOLoader();
  // 添加draco载入库
  dracoLoader.setDecoderPath("./draco/gltf/");
  // 添加draco载入库
  loader.setDRACOLoader(dracoLoader);
  // 加载模型
  loader.load("./model/bmw01.glb", (gltf) => {
    const cartMedul = gltf.scene
    cartMedul.traverse((child)=>{
      // if ( child.isMesh ) { // 是否为物体
      //   console.log("child",child.name);
      // }
      // 判断是否为轮毂
      if (child.isMesh && child.name.includes('轮毂')  ) {
        child.material = wheelsMaterial
        wheels.push(child)
      }
      // 判断是否为车身
      if (child.isMesh && child.name.includes('Mesh002')  ) {
        child.material = cartMaterial
        cartBody = child
      }
      // 判断是否为前脸
      if (child.isMesh && child.name.includes('前脸') ) {
        child.material = frontMaterial
        frontCar = child
      }
      // 判断是否为引擎盖
      if (child.isMesh && child.name.includes('引擎盖_1') ) {
        child.material = hoodMaterial
        hoodCar = child
      }
      // 判断是否为挡风玻璃
      if (child.isMesh && child.name.includes('挡风玻璃') ) {
        child.material = glassMaterial
        glassCar = child
      }


    })
    //设置模型大小
    // medul.scale.set(0.1, 0.1, 0.1);
    // medul.position.set(0,-1,0)
    // medul.rotation.y = Math.PI / 2
    cartMedul.material = new THREE.MeshPhongMaterial({
      color:0xfffff,
      // envMap:bgTexture,
      refractionRatio:0.7, // 折射率
      reflectivity:0.99, // 反射率
    })
    scene.add(cartMedul)
  });

  // 添加平行光 6个方向都添加灯光
  const light1 = new THREE.DirectionalLight(0xffffff, 1);
  light1.position.set(0, 0, 10); // z轴正前方的灯光
  scene.add(light1);
  const light2 = new THREE.DirectionalLight(0xffffff, 1);
  light2.position.set(0, 0, -10); // z轴负前方的灯光
  scene.add(light2);
  const light3 = new THREE.DirectionalLight(0xffffff, 1);
  light3.position.set(0, 10, 0); // y轴正前方的灯光
  scene.add(light3);
  const light4 = new THREE.DirectionalLight(0xffffff, 1);
  light4.position.set(0, -10, 0); // y轴负前方的灯光
  scene.add(light4);
  const light5 = new THREE.DirectionalLight(0xffffff, 1);
  light5.position.set(10, 0, 0); // x轴负前方的灯光
  scene.add(light5);
  const light6 = new THREE.DirectionalLight(0xffffff, 1);
  light6.position.set(-10, 0, 0); // x轴负前方的灯光
  scene.add(light6);

  // 设置控制器阻尼,让控制器更具有真是效果
  // controls.enableDamping = true
})
</script>

<style lang="scss" scoped>
* {
  padding:0;
  margin: 0;
}
.home {
  height:100;
  width:100%;
  background:'#f0f0f0';
  overflow: hidden;
}
.home-content {
  position: fixed;
  top: 0;
  right: 20px;
}

.select-item-color {
  width: 50px;
  height: 50px;
  border: 1px solid #ccc;
  margin: 10px;
  display: inline-block;
  cursor: pointer;
  border-radius: 10px;
}
.select {
  display: flex;
}

</style>

效果

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值