ResourceTracker.js 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import * as THREE from 'three';
  2. export default class ResourceTracker {
  3. constructor() {
  4. this.resources = new Set();
  5. }
  6. track(resource) {
  7. if (!resource) {
  8. return resource;
  9. }
  10. // handle children and when material is an array of materials or
  11. // uniform is array of textures
  12. if (Array.isArray(resource)) {
  13. resource.forEach(resource => this.track(resource));
  14. return resource;
  15. }
  16. if (resource.dispose || resource instanceof THREE.Object3D) {
  17. this.resources.add(resource);
  18. }
  19. if (resource instanceof THREE.Object3D) {
  20. this.track(resource.geometry);
  21. this.track(resource.material);
  22. this.track(resource.children);
  23. } else if (resource instanceof THREE.Material) {
  24. // We have to check if there are any textures on the material
  25. for (const value of Object.values(resource)) {
  26. if (value instanceof THREE.Texture) {
  27. this.track(value);
  28. }
  29. }
  30. // We also have to check if any uniforms reference textures or arrays of textures
  31. if (resource.uniforms) {
  32. for (const value of Object.values(resource.uniforms)) {
  33. if (value) {
  34. const uniformValue = value.value;
  35. if (uniformValue instanceof THREE.Texture ||
  36. Array.isArray(uniformValue)) {
  37. this.track(uniformValue);
  38. }
  39. }
  40. }
  41. }
  42. }
  43. return resource;
  44. }
  45. untrack(resource) {
  46. this.resources.delete(resource);
  47. }
  48. dispose() {
  49. for (const resource of this.resources) {
  50. if (resource instanceof THREE.Object3D) {
  51. if (resource.parent) {
  52. resource.parent.remove(resource);
  53. }
  54. }
  55. if (resource.dispose) {
  56. resource.dispose();
  57. }
  58. }
  59. this.resources.clear();
  60. }
  61. }