Use vue to learn advanced geometry of three.js-LatheGeometry

Introduction and use of LatheGeometry geometry

1. Introduction to LatheGeometry

LatheGeometry can create a solid geometry by rotating a smooth spline curve around the Y axis. The following parameters can be entered when creating LatheGeometry geometry:

Attributes have to description
points Yes This attribute is to specify the point of the spline curve, and then you can rotate according to this spline curve to get a new graph
segments no This attribute specifies the number of segments used to create graphics. The more segments, the smoother the drawn graphics. The default value is 12
phiStart no This attribute specifies where to start creating the graph, and the value range is 0 to 2*π. The default value is 0
phiLength no This attribute specifies how complete the graph is created, the default value is 2*π

The way to create a three-dimensional sphere is as follows:

// 创建样条曲线的点集
const points = []
const height = 5
const count = 30
for (let i = 0; i < count; i++) {
    
    
  points.push(
    new THREE.Vector3(
      (Math.sin(i * 0.2) + Math.cos(i * 0.3)) * height + 12,
      i - count + count / 2,
      0
    )
  )
}
// 绘制样条曲线产生的图形
const geom = new THREE.LatheGeometry(points,12,0,Math.PI*2)

2.demo description

Insert picture description here

As shown above, this example supports the following functions

  1. Adjust the segmentation of the geometry through the segments property to change the smoothness of the graphic surface
  2. Specify where to start painting through the phiStart attribute
  3. Specify the radian to be rotated when painting through the phiLength attribute

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>
      </section>
    </div>
  </div>
</template>

<script>
import * as THREE from 'three'
import {
    
     OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import {
    
     SceneUtils } from 'three/examples/jsm/utils/SceneUtils.js'
export default {
    
    
  data () {
    
    
    return {
    
    
      properties: {
    
    
        segments: {
    
    
          name: 'segments',
          value: 20,
          min: 0,
          max: 40,
          step: 1
        },
        phiStart: {
    
    
          name: 'phiStart',
          value: 0,
          min: 0,
          max: Math.PI * 2,
          step: 0.1
        },
        phiLength: {
    
    
          name: 'phiLength',
          value: 0.8 * Math.PI * 2,
          min: 0,
          max: Math.PI * 2,
          step: 0.1
        }
      },
      pointGroup: null,
      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()
      const axesHelper = new THREE.AxesHelper(20)
      this.scene.add(axesHelper)
    },
    // 创建网格模型
    createMesh () {
    
    
      // 创建样条曲线的点集
      const points = []
      const height = 5
      const count = 30
      for (let i = 0; i < count; i++) {
    
    
        points.push(
          new THREE.Vector3(
            (Math.sin(i * 0.2) + Math.cos(i * 0.3)) * height + 12,
            i - count + count / 2,
            0
          )
        )
      }

      // 将样条曲线展示出来
      this.pointGroup = new THREE.Object3D()
      const material = new THREE.MeshBasicMaterial({
    
    
        color: 0xff0000,
        transparent: false
      })
      points.forEach(point => {
    
    
        const spGeom = new THREE.SphereGeometry(0.2)
        const spMesh = new THREE.Mesh(spGeom, material)
        spMesh.position.copy(point)
        this.pointGroup.add(spMesh)
      })
      this.scene.add(this.pointGroup)

      // 绘制样条曲线产生的图形
      const geom = new THREE.LatheGeometry(
        points,
        this.properties.segments.value,
        this.properties.phiStart.value,
        this.properties.phiLength.value
      )

      this.mesh = this.createLatheMesh(geom)
      // 网格对象添加到场景中
      this.scene.add(this.mesh)
    },

    createLatheMesh (geom) {
    
    
      // 创建材质
      const meshMaterial = new THREE.MeshNormalMaterial({
    
    
        side: THREE.DoubleSide
      })
      const wireFrameMat = new THREE.MeshBasicMaterial({
    
     wireframe: true })

      // 添加组合材质
      const mesh = SceneUtils.createMultiMaterialObject(geom, [
        meshMaterial,
        wireFrameMat
      ])
      return mesh
    },

    // 创建光源
    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.scene.remove(this.mesh)
      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/110097573