Simple implementation of threejs model thumbnail generation in Vue3

Table of contents

I. Introduction

2. Introduction

3. Simple implementation

0. Prepare

1. Create a scene

2. Model import

3. Generate Base64

4. Bind pictures

4. Results display


I. Introduction

        Since the 3D model needs to render each face and edge of the model, the problem of opening the model is often very slow. So how to solve this problem, the simplest and crude method is of course to continuously optimize the model loading, but optimization is often the most difficult. On the other hand, let users accurately open the model they need, can this problem be alleviated to a certain extent? So it is necessary to realize the thumbnail of the 3D model.

2. Introduction

        The main framework for implementing model thumbnails in this article is Vue3, which uses threejs to manage models. It is generally divided into three steps: 1. Prepare the threejs scene container; 2. Build the threejs scene and load the model; 3. Convert the canvas to base64 encoding and load it into the img container.

3. Simple implementation

0. Prepare

        First of all, since you want to import the model, you need to prepare a model that you want to add to the scene. Here I recommend a model download site, SketchChfab , where most of the referenced models in the Threejs source code come from.

        Then, you need to prepare a container for the generated canvas:

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

        Create a ts file to integrate the operations that can be used in the model scene, and name it sceneCreator here:

1. Create a scene

The basic scene creation will not be repeated. If you don’t understand it, you can refer to the simple use of Three.js in Vue3 .

//引入threejs
import * as THREE from 'three' 
//引入加载器
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
​
class SceneCreator {
   public scene: THREE.Scene = new THREE.Scene()
   private camera: THREE.PerspectiveCamera
   private renderer: THREE.Renderer
   private controls: OrbitControls
​
   constructor (fatherElement: HTMLElement) {
     this.scene.background = new THREE.Color(0xaaaaaa)
     // 添加光源
     this.initLight()
​
     // 创建一个透视相机
     const width = window.innerWidth; const height = window.innerHeight
     this.camera = new THREE.PerspectiveCamera(45, width / height, 1, 5000)
     // 设置相机位置
     this.camera.position.set(100, 400, 600)
     // 设置相机方向
     this.camera.lookAt(0, 0, 0)
​
     // 创建辅助坐标轴
     const axesHelper = new THREE.AxesHelper(100)
     this.scene.add(axesHelper)
​
     // 创建一个WebGL渲染器
     this.renderer = new THREE.WebGLRenderer()
     this.renderer.setSize(width, height)
     this.renderer.render(this.scene, this.camera)
​
     fatherElement.appendChild(this.renderer.domElement)
   }
​
   render () {
     this.renderer.render(this.scene, this.camera)
   }
    /**
    *灯光初始化
    */
   initLight () {
     const ambient = new THREE.AmbientLight(0x505050)
     this.scene.add(ambient)
     const pointLight1 = new THREE.PointLight(0xffffff, 0.4)
     const pointLight2 = new THREE.PointLight(0xffffff, 0.4)
     pointLight1.position.set(200, 300, 400)
     this.scene.add(pointLight1)
     pointLight2.position.set(-200, -300, -400)
     this.scene.add(pointLight2)
​
     const hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.6)
     hemiLight.color.setHSL(0.6, 1, 0.6)
     hemiLight.groundColor.setHSL(0.095, 1, 0.75)
     hemiLight.position.set(0, 200, 0)
     this.scene.add(hemiLight)
​
     const hemiLightHelper = new THREE.HemisphereLightHelper(hemiLight, 10)
     this.scene.add(hemiLightHelper)
​
     const dirLight = new THREE.DirectionalLight(0xffffff, 1)
     dirLight.color.setHSL(0.1, 1, 0.95)
     dirLight.position.set(-100, 175, 100)
     dirLight.position.multiplyScalar(30)
     this.scene.add(dirLight)
   }
}
//暴露
export { SceneCreator }

2. Model import

        Here, use the GLTFLoader in threejs to load the downloaded glb. Since making a thumbnail does not require any special operations on the model, you only need to add the loaded model to the scene.

createCar () {
     const loader = new GLTFLoader()
​
     const glbHref = new URL('../assets/glb/car/ferrari_458.glb', import.meta.url).href
​
     loader.load(glbHref, (gltf) => {
       const carModel = gltf.scene.children[0]
​
       this.scene.add(carModel)
     })
   }

3. Generate Base64

<script lang='ts' setup>
import { onMounted, Ref, ref } from 'vue'
import { SceneCreator } from '../utils/sceneCreator'
​
let myScene: SceneCreator
const img:Ref<string> = ref('')
​
const createThumbnails = async () => {
  const el = document.getElementById('thumbnail')
  if (el) {
    // 创建场景
    myScene = new SceneCreator(el)
    // 场景自适应,防止模型变形
    myScene.resize()
    // 载入模型,由于loader是异步的所以我们需要等它加载好后再生成base64,否则生成的图片是没有模型的
    await myScene.createCar()
    myScene.render()
    // 生成base64
    const canvas = el.children[0] as HTMLCanvasElement
    img.value = canvas.toDataURL('img/png')
    // 不需要展示canvas就移除它
    // el.remove()
  }
}
​
onMounted(() => {
  createThumbnails()
})
</script>

4. Bind pictures

        Create an img tag, and bind the base64 generated in step 3 to the scr of the img tag.

<template>
  <div id="thumbnail"></div>
  <img :src="img" alt="">
</template>

4. Results display

Guess you like

Origin blog.csdn.net/qq_52013792/article/details/128129616