ThreeJS

【ThreeJS】03 - 多级对象、父子节点

2021-04-11  本文已影响0人  itlu

多级结构

  1. 在ThreeJs中每一个模型之间可以存在多级的父子关系,凡是继承了Object3D类的子类都可以使用其add方法将其他模型添加为自己的子对象,添加为子对象之后,在控制父对象的同时可以使子对象一起进行改变。可以对子对象的方位等进行联动改变。但是子对象的改变是不会影响到父对象的改变的。

  2. 使用简单的太阳、地球、月亮的案例简单的解释:可以将地球对象添加到太阳父对象上 、 可以将月球子对象添加到地球父对象上。当它们的父对象的方位等发生改变的时候其子对象也会发生改变。

  3. 多级对象关系:

// 创建材质加载器
                let textureLoader = new TextureLoader()

        /** 多级结构 继承自Object3D的类都是可以拥有父子关系的 可以调用add方法将某个形状添加为自己的子节点
         *
         * 子对象的方位是基于父对象的方位 子对象方位 = 父对象方位 * 子对象方位
         *
         * 父对象影响子对象,子对象不影响父对象
         *
         * **/
        // 创建一个地球
        let earth = new SphereGeometry(5,46,46)
        // 创建地球的材质
        let earthMaterial = new MeshPhongMaterial({
          map:textureLoader.load(require('../../assets/earth.jpeg'))
        })
        // 根据形状和材质创建网格
        this.earthMesh = new Mesh(earth , earthMaterial)
        // 将地球添加到场景中
        // this.scene.add(this.earthMesh)

        // 创建一个月球
        let moon = new SphereGeometry(2,46,46)
        // 创建月球的材质
        let moonMaterial = new MeshPhongMaterial({
          map:textureLoader.load(require('../../assets/moon.jpg'))
        })
        // 根据形状和材质创建网格
        let moonMesh = new Mesh(moon , moonMaterial)
        // 将月球的对象添加到地球中 调用add方法
                this.earthMesh.add(moonMesh)

        // 地址月球的位置
        moonMesh.position.x = 20
        moonMesh.position.z = 20

        // 创建一个太阳
        let sun = new SphereGeometry(8,46,46)
        // 创建太阳的材质
        let sunMaterial = new MeshPhongMaterial({
          map:textureLoader.load(require('../../assets/sun.jpeg'))
        })
        // 根据形状和材质创建
        this.sunMesh = new Mesh(sun,sunMaterial)
        this.sunMesh.add(this.earthMesh)

        // 将太阳添加到场景中
        this.scene.add(this.sunMesh)

        // 设置地球的位置
        this.earthMesh.position.set(40,2,40)

        /** 多级结构结束********************** **/
  1. 整个案例:地球绕太阳转、月球绕地球转,这是一个Vue项目在使用之前需要先安装ThreeJs依赖
npm i three --save
ThreeJs多级结构演示案例
    import {
        AxesHelper,
        HemisphereLight,
        Mesh,
        MeshPhongMaterial,
        PerspectiveCamera,
        Scene,
        SphereGeometry, TextureLoader,
        WebGLRenderer
    } from "three";

    import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'

    export default {
        name: "index",
    data() {
      return {
                // 渲染器
        renderer:null,
        // 相机
        camera:null,
        // 创建一个场景
        scene:null,
        // 创建灯光
        light:null,
        // 地球
        earthMesh:null,
        // 太阳
        sunMesh:null
      }
    },
    methods:{


            /**
       * 初始化方法
             */
     init() {
                // 1. 定义一个渲染器
        this.renderer = new WebGLRenderer({antialias:true})
        // 设置渲染器的尺寸和当前窗口的大小一致
        this.renderer.setSize(window.innerWidth,window.innerHeight)
        this.renderer.setClearColor(0xffffff)

        // 将renderer渲染器的canvas挂载到DOM上
        document.body.appendChild(this.renderer.domElement)

        // 2. 创建一个相机
        this.camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, window.innerWidth / window.innerHeight, 1000)

        // 监听窗口的大小当窗口大小改变的首改变当前相机的宽高比和渲染器的尺寸
        window.addEventListener('resize',() => {
            this.renderer.setSize(window.innerWidth,window.innerHeight)
          // 相机的宽高比
          this.camera.aspect = window.innerWidth / window.innerHeight
          // 更新相机的aspect之后必须更新相机的投影矩阵
          this.camera.updateProjectionMatrix()
        })

        // 设置相机的位置
        this.camera.position.set(0,0,50)

        // 3. 创建一个场景
        this.scene = new Scene()

        // 定义辅助线
        let auxLine = new AxesHelper(10000)
        // this.scene.add(auxLine)

        // 4. 创建场景的灯光
        this.light = new HemisphereLight(0xeeeeee, 0xffffff)
        // 将灯光添加到场景中
        this.scene.add(this.light)


        // 创建材质加载器
        let textureLoader = new TextureLoader()

        /** 多级结构 继承自Object3D的类都是可以拥有父子关系的 可以调用add方法将某个形状添加为自己的子节点
         *
         * 子对象的方位是基于父对象的方位 子对象方位 = 父对象方位 * 子对象方位
         *
         * 父对象影响子对象,子对象不影响父对象
         *
         * **/
        // 创建一个地球
        let earth = new SphereGeometry(5,46,46)
        // 创建地球的材质
        let earthMaterial = new MeshPhongMaterial({
          map:textureLoader.load(require('../../assets/earth.jpeg'))
        })
        // 根据形状和材质创建网格
        this.earthMesh = new Mesh(earth , earthMaterial)
        // 将地球添加到场景中
        // this.scene.add(this.earthMesh)

        // 创建一个月球
        let moon = new SphereGeometry(2,46,46)
        // 创建月球的材质
        let moonMaterial = new MeshPhongMaterial({
          map:textureLoader.load(require('../../assets/moon.jpg'))
        })
        // 根据形状和材质创建网格
        let moonMesh = new Mesh(moon , moonMaterial)
        // 将月球的对象添加到地球中 调用add方法
                this.earthMesh.add(moonMesh)

        // 地址月球的位置
        moonMesh.position.x = 20
        moonMesh.position.z = 20

        // 创建一个太阳
        let sun = new SphereGeometry(8,46,46)
        // 创建太阳的材质
        let sunMaterial = new MeshPhongMaterial({
          map:textureLoader.load(require('../../assets/sun.jpeg'))
        })
        // 根据形状和材质创建
        this.sunMesh = new Mesh(sun,sunMaterial)
        this.sunMesh.add(this.earthMesh)

        // 将太阳添加到场景中
        this.scene.add(this.sunMesh)

        // 设置地球的位置
        this.earthMesh.position.set(40,2,40)

        /** 多级结构结束********************** **/

        // 使用渲染器渲染场景和相机
        this.renderer.render(this.scene,this.camera)
        // 创建一个控制器进行控制
        let control = new OrbitControls(this.camera , this.renderer.domElement)

        // 调用不断更新的方法
        this.update()
      },

      update() {
        this.renderer.render(this.scene,this.camera)
        // 进行每秒旋转的角度
        this.earthMesh.rotation.y += 0.003
        this.sunMesh.rotation.y += 0.001
        requestAnimationFrame(this.update)
      }
    },
    created() {
        this.init()
    }
    }
上一篇 下一篇

猜你喜欢

热点阅读