Acabado simple de eliminación de modelo three.js (webgl) / limpieza de escena / liberación de memoria

Acabado simple de eliminación de modelo three.js (webgl) / limpieza de escena / liberación de memoria

contenido

Acabado simple de eliminación de modelo three.js (webgl) / limpieza de escena / liberación de memoria

1. Breve introducción

En segundo lugar, el principio de realización.

3. Grupo modelo (malla) en la escena

4. Limpia la escena y libera la memoria.

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)


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 Sceneo un objeto de grupo Group, 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

Scene1. Elimine un subobjeto en el objeto de escena Groupy libere Groupla 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)
	}
}

Supongo que te gusta

Origin blog.csdn.net/u014361280/article/details/124309410
Recomendado
Clasificación