Acabado simple de eliminación de modelo three.js (webgl) / limpieza de escena / liberación de memoria
contenido
En segundo lugar, el principio de realización.
3. Grupo modelo (malla) en la escena
4. Limpia la escena y libera la memoria.
1. Breve introducción
Algunos conocimientos desarrollados por Three js son convenientes para encontrar problemas similares en el período posterior, y pueden ser consultados y utilizados en el tiempo.
Esta sección presenta el modelo three.js (webgl) eliminación / limpieza de escenas / liberación de memoria clasificación simple, para que todos optimicen la dirección del pensamiento, si hay deficiencias, bienvenido a señalar, o si tiene un método mejor, Bienvenido a dejar un mensaje.
Al desarrollar aplicaciones Web3D a través de Threejs, es posible que deba eliminar objetos de modelo en la escena.Si desea eliminar un objeto de modelo 3D de una escena
Scene
o un objeto de grupoGroup
, no solo.remove()
, recuerde eliminarlo cuando sea necesario·dispose()
.Al desarrollar una escena 3D, si necesita agregar, eliminar o modificar dinámicamente modelos y escenas, o cuando las páginas se cambian y se vuelven a renderizar, para evitar la superposición de memoria, debe borrar manualmente la memoria ocupada por la escena para evitar el desbordamiento y desperdicio de recursos.
En segundo lugar, el principio de realización.
1. Para modelos generales, recuerde desechar() la geometría y el material, y eliminar() la malla del modelo.
2. Limpia la escena y libera la memoria, la clave es la siguiente
- Use dispose() para borrar el uso de la memoria del búfer de vértices de toda la geometría de la malla
- Use object.clear() para destruir el objeto modelo y borrar la memoria de la página
- Pausa el método requestAnimationFrame() para evitar una ejecución sin sentido
- Vaciar el lienzo canvas, vaciar el dom y los elementos relacionados
3. Grupo modelo (malla) en la escena
Scene
1. Elimine un subobjeto en el objeto de escena Group
y libere Group
la memoria ocupada por los búferes de vértices de toda la geometría del modelo de malla en el objeto de grupo
deleteObject(group) {
// 递归遍历组对象group释放所有后代网格模型绑定几何体占用内存
group.traverse(function(obj) {
if (obj.type === 'Mesh') {
obj.geometry.dispose();
obj.material.dispose();
}
})
// 删除场景对象scene的子对象group
scene.remove(group);
}
2, otro método, borrar el grupo
clearGroup(group) {
// 释放 几何体 和 材质
const clearCache = (item) => {
item.geometry.dispose();
item.material.dispose();
};
// 递归释放物体下的 几何体 和 材质
const removeObj = (obj) => {
let arr = obj.children.filter((x) => x);
arr.forEach((item) => {
if (item.children.length) {
removeObj(item);
} else {
clearCache(item);
item.clear();
}
});
obj.clear();
arr = null;
};
// 移除 group
removeObj(group);
}
记得:
1)如果是场景中
scene.remove(group); // 删除组
2)如果是 组中
groups.remove(group);// 删除模型
4. Limpia la escena y libera la memoria.
// 清空场景,包括 scene 场景下的动画,子物体,renderer,camera,control,以及自己使用过的变量置空处理 等
clearScene() {
cancelAnimationFrame(this.animationId);
this.scene.traverse((child) => {
if (child.material) {
child.material.dispose();
}
if (child.geometry) {
child.geometry.dispose();
}
child = null;
});
// 场景中的参数释放清理或者置空等
this.sceneDomElement.innerHTML = '';
this.renderer.forceContextLoss();
this.renderer.dispose();
this.scene.clear();
this.flows = [];
this.scene = null;
this.camera = null;
this.controls = null;
this.renderer.domElement = null;
this.renderer = null;
this.sceneDomElement = null;
console.log('clearScene');
}
5. Suplemento de referencia: Problema de liberación de memoria de Three.js (si no se maneja correctamente, es posible que no se libere y ocupe memoria)
Publicación de blog de referencia: Problema de liberación de memoria de Three.js
1. El método convencional no puede eliminar por completo alguna geometría, textura, etc. en la escena, e incluso si la página se va, la memoria no se liberará automáticamente. Abra el administrador de tareas, puede ver que la CPU siempre está ocupada y aumenta cada vez más al cambiar de página.
//注意: 这里释放场景,并未处理必要的scene子物体的 geometry 、material 等
beforeDestroy() {
try {
scene.clear();
renderer.dispose();
renderer.forceContextLoss();
renderer.content = null;
cancelAnimationFrame(animationID) // 去除animationFrame
let gl = renderer.domElement.getContext("webgl");
gl && gl.getExtension("WEBGL_lose_context").loseContext();
}catch (e) {
console.log(e)
}
}
2. Aquí se encapsula un método de seguimiento para administrar la liberación de malla, geometría, textura, object3D, modelos obj cargados externamente, modelos gltf, etc. en la escena de liberación
1) Método de seguimiento de recursos:
import * as THREE from 'three/build/three.module'
export default class ResourceTracker {
constructor() {
this.resources = new Set();
}
track(resource) {
if (!resource) {
return resource;
}
// handle children and when material is an array of materials or
// uniform is array of textures
if (Array.isArray(resource)) {
resource.forEach(resource => this.track(resource));
return resource;
}
if (resource.dispose || resource instanceof THREE.Object3D) {
this.resources.add(resource);
}
if (resource instanceof THREE.Object3D) {
this.track(resource.geometry);
this.track(resource.material);
this.track(resource.children);
} else if (resource instanceof THREE.Material) {
// We have to check if there are any textures on the material
for (const value of Object.values(resource)) {
if (value instanceof THREE.Texture) {
this.track(value);
}
}
// We also have to check if any uniforms reference textures or arrays of textures
if (resource.uniforms) {
for (const value of Object.values(resource.uniforms)) {
if (value) {
const uniformValue = value.value;
if (uniformValue instanceof THREE.Texture ||
Array.isArray(uniformValue)) {
this.track(uniformValue);
}
}
}
}
}
return resource;
}
untrack(resource) {
this.resources.delete(resource);
}
dispose() {
for (const resource of this.resources) {
if (resource instanceof THREE.Object3D) {
if (resource.parent) {
resource.parent.remove(resource);
}
}
if (resource.dispose) {
resource.dispose();
}
}
this.resources.clear();
}
}
2) Introducir pista e inicializar
import ResourceTracker from "../../../common/3D/dispose";
// 在外层定义resMgr和track
let resMgr = new ResourceTracker();
const track = resMgr.track.bind(resMgr);
3) Llame al método de seguimiento para todas las mallas, geometrías, texturas, objetos 3D, modelos obj cargados externamente, modelos gltf y otros objetos que deben agregarse a la escena
let xxx = track(new Three.Vector3());
obj.geometry.computeBoundingBox();
obj.geometry.boundingBox.getCenter(center);
let wrapper = track(new Three.Object3D());
wrapper.position.set(center.x,center.y,center.z);
obj.position.set(-center.x,-center.y,-center.z);
wrapper.add(obj);
scene.add(wrapper);
return warpper;
4) Liberar la memoria del objeto 3D rastreado
beforeDestroy() {
try {
scene.clear();
resMgr && resMgr.dispose()
renderer.dispose();
renderer.forceContextLoss();
renderer.content = null;
cancelAnimationFrame(animationID)
let gl = renderer.domElement.getContext("webgl");
gl && gl.getExtension("WEBGL_lose_context").loseContext();
console.log(renderer.info) //查看memery字段即可
}catch (e) {
console.log(e)
}
}