Use vue to learn three.js to load advanced geometry-save and load objects in JSON format

1.demo effect

Insert picture description here

As shown above, the demo supports the following functions:

  1. The parameters can be adjusted to create different torus kinks.
  2. You can click the saveToJSON button to save the current grid object in JSON format to the page cache
  3. You can click loadJSON to load the grid object in JSON format saved in the page cache to the current page

2. Implementation points

2.1 Save the mesh object as JSON format

Here we first create a torus knotted mesh object, then convert it into JSON format, and then save it in the page cache, as follows:

 // 创建环面扭结
 const geom = new THREE.TorusKnotGeometry(
   this.properties.radius.value,
   this.properties.tube.value,
   this.properties.radialSegments.value,
   this.properties.tubularSegments.value,
   this.properties.p.value,
   this.properties.q.value
 )
 // 创建材质
 const meshMaterial = new THREE.MeshBasicMaterial({
    
    
   vertexColors: THREE.VertexColors,
   wireframe: true,
   wireframeLinewidth: 2,
   color: 0xaaaaaa
 })

 // 添加组合材质
 this.mesh = new THREE.Mesh(geom, meshMaterial)
 // 网格对象转为json格式
 const json = this.mesh.toJSON()
 // 保存在localStorege缓存中
 localStorage.setItem('json', JSON.stringify(json))

2.2 Load the grid object saved in JSON format

In the above steps, we convert a grid object into JSON format and save it to the page cache. Here we need to get the content in the page cache, convert it into a grid object and add it to the scene

// 导入json格式的网格对象
loadJSON () {
    
    
  this.removeMesh()
  const json = localStorage.getItem('json')

  if (json) {
    
    
    const loadedGeometry = JSON.parse(json)
    const loader = new THREE.ObjectLoader()
    const loadedMesh = loader.parse(loadedGeometry)
    this.scene.add(loadedMesh)
  }
}

3.demo code

<template>
  <div>
    <div id="container"></div>
    <div class="controls-box">
      <section>
        <el-row>
          <div v-for="(item,key) in properties" :key="key">
            <div v-if="item&&item.name!=undefined">
              <el-col :span="8">
                <span class="vertice-span">{
    
    {
    
    item.name}}</span>
              </el-col>
              <el-col :span="13">
                <el-slider v-model="item.value" :min="item.min" :max="item.max" :step="item.step" :format-tooltip="formatTooltip" @change="redraw"></el-slider>
              </el-col>
              <el-col :span="3">
                <span class="vertice-span">{
    
    {
    
    item.value}}</span>
              </el-col>
            </div>
          </div>
        </el-row>
        <el-row>
          <el-button @click="loadJSON">loadJSON</el-button>
        </el-row>
        <el-row>
          <el-button @click="saveToJSON">saveToJSON</el-button>
        </el-row>
      </section>
    </div>
  </div>
</template>

<script>
import * as THREE from 'three'
import {
    
     OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
export default {
    
    
  data () {
    
    
    return {
    
    
      properties: {
    
    
        radius: {
    
    
          name: 'radius',
          value: 18,
          min: 0,
          max: 60,
          step: 1
        },
        tube: {
    
    
          name: 'tube',
          value: 2,
          min: 0,
          max: 20,
          step: 0.1
        },
        radialSegments: {
    
    
          name: 'radialSegments',
          value: 230,
          min: 0,
          max: 400,
          step: 1
        },
        tubularSegments: {
    
    
          name: 'tubularSegments',
          value: 8,
          min: 0,
          max: 50,
          step: 1
        },
        p: {
    
    
          name: 'p',
          value: 4,
          min: 0,
          max: 20,
          step: 1
        },
        q: {
    
    
          name: 'q',
          value: 3,
          min: 0,
          max: 20,
          step: 1
        }
      },
      mesh: null,
      camera: null,
      scene: null,
      renderer: null,
      controls: null
    }
  },
  mounted () {
    
    
    this.init()
  },
  methods: {
    
    
    formatTooltip (val) {
    
    
      return val
    },
    // 初始化
    init () {
    
    
      this.createScene() // 创建场景
      this.createMesh() // 创建网格模型
      this.createLight() // 创建光源
      this.createCamera() // 创建相机
      this.createRender() // 创建渲染器
      this.createControls() // 创建控件对象
      this.render() // 渲染
    },
    // 创建场景
    createScene () {
    
    
      this.scene = new THREE.Scene()
    },
    // 创建网格模型
    createMesh () {
    
    
      // 创建环面扭结
      const geom = new THREE.TorusKnotGeometry(
        this.properties.radius.value,
        this.properties.tube.value,
        this.properties.radialSegments.value,
        this.properties.tubularSegments.value,
        this.properties.p.value,
        this.properties.q.value
      )
      // 创建材质
      const meshMaterial = new THREE.MeshBasicMaterial({
    
    
        vertexColors: THREE.VertexColors,
        wireframe: true,
        wireframeLinewidth: 2,
        color: 0xaaaaaa
      })

      // 添加组合材质
      this.mesh = new THREE.Mesh(geom, meshMaterial)

      // 网格对象添加到场景中
      this.scene.add(this.mesh)
    },
    // 网格对象保存为json格式
    saveToJSON () {
    
    
      const json = this.mesh.toJSON()
      localStorage.setItem('json', JSON.stringify(json))
    },
    // 导入json格式的网格对象
    loadJSON () {
    
    
      this.removeMesh()
      const json = localStorage.getItem('json')

      if (json) {
    
    
        const loadedGeometry = JSON.parse(json)
        const loader = new THREE.ObjectLoader()
        const loadedMesh = loader.parse(loadedGeometry)
        this.scene.add(loadedMesh)
      }
    },
    removeMesh () {
    
    
      const toRemove = []
      this.scene.traverse(e => {
    
    
        if (e instanceof THREE.Mesh) toRemove.push(e)
      })
      toRemove.forEach(e => {
    
    
        this.scene.remove(e)
      })
    },
    // 创建光源
    createLight () {
    
    
      // 环境光
      const ambientLight = new THREE.AmbientLight(0xffffff, 0.1) // 创建环境光
      this.scene.add(ambientLight) // 将环境光添加到场景

      const spotLight = new THREE.SpotLight(0xffffff) // 创建聚光灯
      spotLight.position.set(-40, 60, -10)
      spotLight.castShadow = true
      this.scene.add(spotLight)
    },
    // 创建相机
    createCamera () {
    
    
      const element = document.getElementById('container')
      const width = element.clientWidth // 窗口宽度
      const height = element.clientHeight // 窗口高度
      const k = width / height // 窗口宽高比
      // PerspectiveCamera( fov, aspect, near, far )
      this.camera = new THREE.PerspectiveCamera(35, k, 0.1, 1000)
      this.camera.position.set(-80, 60, 40) // 设置相机位置

      this.camera.lookAt(new THREE.Vector3(10, 0, 0)) // 设置相机方向
      this.scene.add(this.camera)
    },
    // 创建渲染器
    createRender () {
    
    
      const element = document.getElementById('container')
      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(0x3f3f3f, 1) // 设置背景颜色
      element.appendChild(this.renderer.domElement)
    },

    // 更新
    redraw () {
    
    
      this.removeMesh()
      this.createMesh()
    },
    render () {
    
    
      this.renderer.render(this.scene, this.camera)
      requestAnimationFrame(this.render)
    },
    // 创建控件对象
    createControls () {
    
    
      this.controls = new OrbitControls(this.camera, this.renderer.domElement)
    }
  }
}
</script>
<style>
#container {
    
    
  position: absolute;
  width: 100%;
  height: 100%;
}
.controls-box {
    
    
  position: absolute;
  right: 5px;
  top: 5px;
  width: 300px;
  padding: 10px;
  background-color: #fff;
  border: 1px solid #c3c3c3;
}
.vertice-span {
    
    
  line-height: 38px;
  padding: 0 2px 0 10px;
}
</style>

Guess you like

Origin blog.csdn.net/qw8704149/article/details/112549650