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

<script>
import * as Three from 'three'
import { DoubleSide, TextureLoader } from 'three'
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
 

  export default {
    data () {
      return {
        camera: null,
        scene: null,
        renderer: null,
        mesh: null,
        controls: null
      }
    },
 

    mounted () {
      this.init()
      this.drawBox()
      this.drawSkyBox()
      this.drawLine()
      this.animate()
 

      window.addEventListener("resize", this.onWindowResize, false); //添加窗口监听事件(resize-onresize即窗口或框架被重新调整大小)
    },
 

    methods: {
 

      //初始化
      init() {
        let container = document.getElementById('container')                                                                    // 获取页面元素
        this.camera = new Three.PerspectiveCamera(70, container.clientWidth / container.clientHeight, 0.01, 100)                // 创建像机(视野角度, 长宽比, 近截面, 远截面)
        this.camera.position.z = 2                                                                                              // 相机移动
        this.scene = new Three.Scene()                                                                                          // 创建场景
        // let geometry = new Three.BoxGeometry(0.2, 0.2, 0.2)                                                                  // 创建立方体
        // let material = new Three.MeshNormalMaterial()                                                                        // 创建材质
        // this.mesh = new Three.Mesh(geometry, material)                                                                       // 创建网格
        // this.scene.add(this.mesh)                                                                                            // 将网格加入场景
 

        this.renderer = new Three.WebGLRenderer({antialias: true})                                                              // 创建渲染器 antialias: true消除锯齿
        this.renderer.setSize(container.clientWidth, container.clientHeight)                                                    // 设置渲染器尺寸
        container.appendChild(this.renderer.domElement)                                                                         // 将渲染器的dom元素添加到页面中
 

        //初始化控制器
        this.controls = new OrbitControls(this.camera, this.renderer.domElement);
        this.controls.target.set(0, 0, 0);
        this.controls.update();
      },
     
      // 添加贴图
      setLoader() {
        let textureLoader = new Three.TextureLoader
 

        var boxImg = require('../assets/box.jpg')
        let boxTexture = textureLoader.load(boxImg)
        return boxTexture
      },
 

      drawBox() {
        let boxTexture = this.setLoader()
       
        let geometry = new Three.BoxGeometry(0.2, 0.2, 0.2)                                                                     // 创建立方体
        let material = new Three.MeshBasicMaterial({ map: boxTexture, side: DoubleSide })                       // 创建材质 map: boxTexture使用贴图boxTexture side: doubleSide双面渲染
        this.mesh = new Three.Mesh(geometry, material)                                                                          // 创建网格
        this.mesh.name = 'box'                                                                                                  // 网格命名,方便之后调用
        this.scene.add(this.mesh)
      },
 

      // 绘制天空盒子(四面材质不同并且双面渲染的巨型盒子, 暂时用随意的图片替代)
      drawSkyBox() {
        let skyBox = new Three.BoxGeometry(10, 10, 10)                                                                       // 创建立方体
 

        let textureLoader = new Three.TextureLoader
        var boxImg = require('../assets/box.jpg')
        let boxTexture = textureLoader.load(boxImg)
        var catImg = require('../assets/cat.jpg')
        let catTexture = textureLoader.load(catImg)
       
        let skyBoxMaterialList = [
          new Three.MeshBasicMaterial({ map: boxTexture, side: DoubleSide }),
          new Three.MeshBasicMaterial({ map: boxTexture, side: DoubleSide }),
          new Three.MeshBasicMaterial({ map: boxTexture, side: DoubleSide }),
          new Three.MeshBasicMaterial({ map: boxTexture, side: DoubleSide }),
          new Three.MeshBasicMaterial({ map: boxTexture, side: DoubleSide }),
          new Three.MeshBasicMaterial({ map: catTexture, side: DoubleSide })
        ]
       
        let sky = new Three.Mesh(skyBox, skyBoxMaterialList)                                                                          // 创建网格
        this.scene.add(sky)
      },
 

      drawLine() {
        let material = new Three.LineBasicMaterial( { color: 0x0000ff } );
        let geometry = new Three.Geometry();
        geometry.vertices.push(new Three.Vector3( -1, 0, 0) );                                                                   // 设置线条顶点
        geometry.vertices.push(new Three.Vector3( 0, 1, 0) );
        geometry.vertices.push(new Three.Vector3( 1, 0, 0) );
        geometry.vertices.push(new Three.Vector3( 0, -1, 0) );
        geometry.vertices.push(new Three.Vector3( -1, 0, 0) );
        var line = new Three.Line( geometry, material );
        this.scene.add(line)
      },
 

      //渲染及动画效果
      animate() {
        requestAnimationFrame(this.animate)                                                                                       // 动画循环
        // // let box = this.scene.getObjectByName('box')                                                                            // 使用mesh命名操作mesh,效果同下
        // // box.rotation.x += 0.01
        // // box.rotation.y += 0.02
 

        // this.mesh.rotation.x += 0.01
        // this.mesh.rotation.y += 0.02
        this.renderer.render(this.scene, this.camera)
      },
 

      //窗口监听函数
      onWindowResize() {
        // 模型比例调整
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
       
        this.renderer.setSize(window.innerWidth, window.innerHeight);
      },
    }
  }
</script>
<style scoped>
  #container {
    height: 100vh;
  }
</style>

 

posted on 2021-12-15 10:54  occc  阅读(183)  评论(0编辑  收藏  举报