Vue2中使用three.js导入gltf模型,单击响应变色【学习记录】

背景:在一个vue文件里使用两个gltf模型,并且两个模型直接不存在绑定及依赖关系,即相互独立。
目的:点击单个模型,则该模型变色。另一模型不发生任何变化。
思路处理:按方法来进行一步步导入和处理。

  1. 初始化顺序
 init() {
      this.createScene()  创建场景,可以理解为三维世界,用来展示三维物体
      this.loadGLTF()  加载GLTF模型,三维世界已经建好,那么我们就把三维物体放到三维世界里
      this.createLight()  创建光源,首先光会产生能见度,没有光线自然会出现那种特别暗或者是一片黑的情况,
      第二就是光线能够更好的展示出三维图形的立体感
      this.createCamera()  创建相机,相机就是我们的视角,从哪去看这个三维物体
      this.createRender()  创建渲染器,到目前为止还都是代码,想让这些理论代码显示到网页上就需要渲染器来工作了。
      this.createControls()  创建控件对象,没有它,我们是无法用鼠标来控制模型旋转之类的操作的,
      this.render() 渲染,一切准备就绪,渲染器开始工作
    },

完整代码:

<template>
  <div>
    <div id="container"></div>
  </div>
</template>

<script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
// 引入渲染器通道RenderPass
import { OutlinePass } from "three/addons/postprocessing/OutlinePass.js";
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import * as Three from "three";

var scene,mesh,model1,model2; //这两个变量不要在data(){ }中定义问题即可解决。

export default {
  data() {
    return {
      // publicPath: process.env.BASE_URL,
      // mesh: null,
      camera: null,


      // scene: null,
      renderer: null,

      controls: null
    }
  },
  mounted() {
    this.init()
    window.addEventListener("click", this.onClick, false);

  },

  methods: {
    //事件函数

      onClick(event) {
        const raycaster = new THREE.Raycaster();
        const mouse = new THREE.Vector2();
        // 计算鼠标或触摸点的位置
        const threeModel = document.getElementById("container");
        const width = threeModel.offsetWidth;
        const height = threeModel.offsetHeight;
        let getClientRect = threeModel.getBoundingClientRect();
        mouse.x = ((event.clientX - getClientRect .left) /  width) * 2 - 1;
        mouse.y = -((event.clientY - getClientRect .top) /  height) * 2 + 1;

        console.log(event.clientX)

        // 更新射线   注意——> this.camera 是相机   定义到data里的
        raycaster.setFromCamera(mouse, this.camera);
        // 计算与所有对象的交点
        const intersects = raycaster.intersectObjects(scene.children, true);

        if (intersects.length > 0) {
          // 处理点击事件
          // intersects[0] 包含了第一个
          // 交点
          const clickedObject = intersects[0].object;
          //通过点击到该模型用名字匹配
          if (clickedObject.name === clickedObject.name) {

              // 创建后处理对象,这里我将该对象称作  效果制作器
              mesh = new EffectComposer(this.renderer);
              // 创建渲染器通道
              const renderPass = new RenderPass(scene, this.camera);
              mesh.addPass(renderPass);
              // 创建发光描边对象,model2可选,具体根据gltf导入时所确定的名称,对应修改
              const outlinePass = new OutlinePass(new Three.Vector2(1000, 800), model2, this.camera);

            // 设置发光描边颜色
              outlinePass.visibleEdgeColor.set(0x7CFC00);
              // 设置发光描边厚度
              outlinePass.edgeThickness = 5;
              // 设置发光描边强度
              outlinePass.edgeStrength = 7;
              // 设置闪烁频率
              outlinePass.pulsePeriod = 2;
              const obj = [];
              scene.traverse(item => {
                if(item.isMesh) {
                  obj.push(item);
                }
              })
              outlinePass.selectedObjects = obj;
              mesh.addPass(outlinePass);
              this.renderFun();



          }
        }
      },

    // 初始化
    init() {
      this.createScene() // 创建场景
      this.loadGLTF() // 加载GLTF模型
      this.createLight() // 创建光源
      this.createCamera() // 创建相机
      this.createRender() // 创建渲染器
      this.createControls() // 创建控件对象
      this.render() // 渲染
    },
    //技术来自  http://www.webgl3d.cn/pages/637c91/
    // 1.创建三维场景
    createScene() {
      scene = new THREE.Scene()
    },
    // 加载GLTF模型对象,(别的模型需要单独修改)
    loadGLTF() {
      const loader = new GLTFLoader()
      loader.load(`../gy.gltf`,
          gltf1 => {
          model1=gltf1.scene//用于全局控制变色时的具体对象,变色时选择model1则代表该模型变色
            // 解决模型为黑色的问题
            gltf1.scene.traverse(function(child) {//遍历对象,给其上色
              if (child.isMesh) {
                child.material.emissive = child.material.color;//emissive自发光属性,color默认值是白色
                child.material.emissiveMap = child.material.map;//emissiveMap自发光贴图属性

              }
            });
            gltf1.scene.children[0].scale.set(10, 10, 10)//调整模型整体大小用的,三个数值保持一致即可
        scene.add(model1)
      })
      loader.load(`../gy.gltf`,
          gltf2 => {
            model2=gltf2.scene//用于全局控制变色时的具体对象,变色时选择model2则代表该模型变色

            // 解决模型为黑色的问题
            gltf2.scene.traverse(function(child) {//遍历对象,给其上色
              if (child.isMesh) {
                child.material.emissive = child.material.color;//emissive自发光属性,color默认值是白色
                child.material.emissiveMap = child.material.map;//emissiveMap自发光贴图属性

              }
            });
            gltf2.scene.children[0].scale.set(10, 10, 10)
            gltf2.scene.children[0].position.x=150//平行横向
            gltf2.scene.children[0].position.y=150//平行前后
            gltf2.scene.children[0].position.z=150//平行前后

            scene.add(model2)
          })
    },

    // 创建光源
    createLight() {
      // 环境光
      const ambientLight = new THREE.AmbientLight(0xffffff, 0.1) // 创建环境光
      scene.add(ambientLight) // 将环境光添加到场景
    // 创建聚光灯
      const spotLight = new THREE.SpotLight(0xffffff)
      spotLight.position.set(150, 150, 150)
      spotLight.castShadow = true
      scene.add(spotLight)
    },
    // 创建相机
    createCamera() {
      //先设计坐标系
      const width = 300 // 窗口宽度
      const height = 150 // 窗口高度
      const k = width / height // 窗口宽高比
      //设计相机
      // PerspectiveCamera( fov, aspect, near, far )
      this.camera = new THREE.PerspectiveCamera(75, k, 0.1, 1000)//
      this.camera.position.set(150, 150, 150) // 设置相机位置,主要控制页面显示中的起始大小
      this.camera.lookAt(new THREE.Vector3(10, 40, 0)) // 设置相机方向


      //把相机加到三维场景中
      scene.add(this.camera)


    },
    // 创建渲染器
    createRender() {
      const element = document.getElementById('container')
      //创建WebGL渲染器
      this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
      this.renderer.setSize(element.clientWidth, element.clientHeight) // 设置渲染区域尺寸
      this.renderer.shadowMap.enabled = true // 显示阴影
      this.renderer.shadowMap.type = THREE.PCFSoftShadowMap//设置阴影效果
      this.renderer.setClearColor(null, 1) // 设置背景颜色,null就是透明色

      //three.js执行渲染命令会输出一个canvas画布(HTML元素),你可以插入到web页面中
      element.appendChild(this.renderer.domElement)

    },

    //开始渲染
    render() {
      if (mesh) {
        //加z轴方向旋转弧度,每次旋转0.006个弧度
        mesh.rotation.z += 0.006
      }
      //把三维场景,和照相机开始渲染
      this.renderer.render(scene, this.camera)

      //页面刷新,自动重新渲染话
      requestAnimationFrame(this.render)
      this.camera.updateMatrixWorld()

    },
    renderFun() {
      mesh.render();
      window.requestAnimationFrame(this.renderFun);
    },
    // 创建控件对象
    createControls() {
      this.controls = new OrbitControls(this.camera, this.renderer.domElement)

    }
  }
}
</script>
<style>
#container {
  position: absolute;
  width: 30%;
  height: 40%;
}
</style>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值