Tabla de contenido
4. Visualización de resultados
I. Introducción
Dado que el modelo 3D necesita renderizar cada cara y borde del modelo, el problema de abrir el modelo suele ser muy lento. Entonces, cómo resolver este problema, el método más simple y crudo es, por supuesto, optimizar continuamente la carga del modelo, pero la optimización suele ser la más difícil. Por otro lado, permitir que los usuarios abran con precisión el modelo que necesitan, ¿se puede aliviar este problema hasta cierto punto? Entonces es necesario realizar la miniatura del modelo 3D.
2. Introducción
El marco principal para implementar miniaturas de modelos en este artículo es Vue3, que usa threejs para administrar modelos. Generalmente se divide en tres pasos: 1. Preparar el contenedor de la escena threejs, 2. Construir la escena threejs y cargar el modelo, 3. Convertir el lienzo a la codificación base64 y cargarlo en el contenedor img.
3. Implementación sencilla
0. Preparar
En primer lugar, dado que desea importar el modelo, debe preparar un modelo que desee agregar a la escena. Aquí recomiendo un sitio de descarga de modelos, SketchChfab , de donde provienen la mayoría de los modelos a los que se hace referencia en el código fuente de Threejs.
Luego, debe preparar un contenedor para el lienzo generado:
<template>
<div id="thumbnail"></div>
</template>
Cree un archivo ts para integrar las operaciones que se pueden usar en la escena del modelo y asígnele el nombre sceneCreator aquí:
1. Crea una escena
La creación básica de la escena no se repetirá. Si no la entiende, puede consultar el uso simple de Three.js en 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. Importación de modelos
Aquí, use el GLTFLoader en threejs para cargar el glb descargado. Dado que hacer una miniatura no requiere ninguna operación especial en el modelo, solo necesita agregar el modelo cargado a la escena.
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. Generar 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. Enlazar imágenes
Cree una etiqueta img y vincule el base64 generado en el paso 3 al scr de la etiqueta img.
<template>
<div id="thumbnail"></div>
<img :src="img" alt="">
</template>