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

Introduction and use of ExtrudeGeometry

1. Introduction to ExtrudeGeometry

ExtrudeGeometry can use a two-dimensional figure to create a three-dimensional figure. The following parameters can be entered when creating ExtrudeGeometry geometry:

Attributes have to description
depth no This attribute specifies how high the graph can be stretched, the default value is 100
bevelThickness no This attribute specifies the thickness of the bevel, the default value is 6
bevelSize no This attribute specifies the height of the bevel. The default value is bevelThickness-2
bevelSegments no This attribute specifies the number of segments of the bevel angle, the more segments, the smoother the bevel angle, the default value is 3
commandEnabled no This attribute specifies whether to enable the bevel, the default is true
curveSegments no This attribute specifies the number of segments of the stretched curve. The more segments, the smoother the curve. The default value is 12
steps no This attribute specifies how many segments the stretched body is divided into, the default value is 1
extrudePath no This attribute specifies the path along which the graph is stretched, if not specified, it will stretch along the z-axis
UVGenerator no This attribute provides the object of the UV generator function

2.demo description

Insert picture description here

As shown above, this example supports the following functions

  1. Adjust the height of the geometry stretch through the depth attribute
  2. Specify the thickness of the bevel through the bevelThickness property
  3. Specify the height of the bevel through the bevelSize property
  4. Specify the number of segments of the bevel through the bevelSegments property
  5. Set whether to turn on the bevel through the bevelEnabled property
  6. Specify the number of segments of the stretch curve through the curveSegments property
  7. Specify the number of segments of the stretched body through the steps 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>
        <el-row>
          <el-checkbox v-model="properties.bevelEnabled" @change="redraw">bevelEnabled</el-checkbox>
        </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: {
    
    
        depth: {
    
    
          name: 'depth',
          value: 2,
          min: 0,
          max: 40,
          step: 1
        },
        bevelThickness: {
    
    
          name: 'bevelThickness',
          value: 2,
          min: 0,
          max: 10,
          step: 0.1
        },
        bevelSize: {
    
    
          name: 'bevelSize',
          value: 0.8,
          min: 0,
          max: 10,
          step: 0.1
        },
        bevelSegments: {
    
    
          name: 'bevelSegments',
          value: 3,
          min: 0,
          max: 40,
          step: 1
        },
        curveSegments: {
    
    
          name: 'curveSegments',
          value: 12,
          min: 0,
          max: 40,
          step: 1
        },
        steps: {
    
    
          name: 'steps',
          value: 1,
          min: 0,
          max: 5,
          step: 1
        },
        bevelEnabled: true
      },
      step: 0.01,
      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()
    },
    // 绘制图形
    drawShape () {
    
    
      // 创建基础形状
      const shape = new THREE.Shape()

      // 设置起始点
      shape.moveTo(10, 10)

      // 画线到新坐标
      shape.lineTo(10, 40)

      // 贝塞尔曲线
      shape.bezierCurveTo(15, 25, 25, 25, 30, 40)

      // 样条曲线
      shape.splineThru([
        new THREE.Vector2(32, 30),
        new THREE.Vector2(28, 20),
        new THREE.Vector2(30, 10)
      ])

      // 底部二次曲线
      shape.quadraticCurveTo(20, 15, 10, 10)

      // 左眼
      const hole1 = new THREE.Path()
      hole1.absellipse(16, 24, 2, 3, 0, Math.PI * 2, true)
      shape.holes.push(hole1)

      // 右眼
      const hole2 = new THREE.Path()
      hole2.absellipse(23, 24, 2, 3, 0, Math.PI * 2, true)
      shape.holes.push(hole2)

      // 嘴巴
      const hole3 = new THREE.Path()
      hole3.absarc(20, 16, 2, 0, Math.PI, true)
      shape.holes.push(hole3)
      return shape
    },

    // 创建网格模型
    createMesh () {
    
    
      // 拉伸几何体配置项
      const options = {
    
    
        depth: this.properties.depth.value,
        bevelThickness: this.properties.bevelThickness.value,
        bevelSize: this.properties.bevelSize.value,
        bevelSegments: this.properties.bevelSegments.value,
        bevelEnabled: this.properties.bevelEnabled,
        curveSegments: this.properties.curveSegments.value,
        steps: this.properties.steps.value
      }

      // 创建拉伸几何体
      const geom = new THREE.ExtrudeGeometry(this.drawShape(), options)
      geom.applyMatrix4(new THREE.Matrix4().makeTranslation(-30, -10, 0))
      // 创建材质
      const meshMaterial = new THREE.MeshNormalMaterial({
    
    
        flatShading: false,
        transparent: true,
        opacity: 0.5
      })

      // 创建网格对象
      this.mesh = new THREE.Mesh(geom, meshMaterial)
      // 网格对象添加到场景中
      this.scene.add(this.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.mesh.rotation.y = this.step += 0.01
      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/110100622