Browse Source

docs: add Plain THREE and Tres memory tests

Peter 3 months ago
parent
commit
167fe5297e

+ 176 - 0
playground/vue/src/pages/advanced/MemoryTresCanvasesObjects.vue

@@ -0,0 +1,176 @@
+<script setup lang="ts">
+import { TresCanvas } from '@tresjs/core'
+import type { Group, Material } from 'three'
+import { BoxGeometry, Color, Mesh, MeshBasicMaterial, PerspectiveCamera, Scene, Vector3, WebGLRenderer } from 'three'
+import { onUnmounted, ref } from 'vue'
+
+const toggleMax = 400
+const numObjectsMax = 2000
+const startTimeMS = ref(0)
+const width = 900
+const height = 600
+
+const toggleCount = ref(0)
+const showTres = ref(false)
+const showVueThree = ref(false)
+
+const msg = ref('Click Start Test to begin.')
+const r = ref(null)
+let intervalId: ReturnType<typeof setInterval>
+
+const testVueThree = (() => {
+  let renderer: WebGLRenderer | null = null
+  let scene: Scene | null = null
+  let camera: PerspectiveCamera | null = null
+  let frameCount = 0
+
+  function testVueThree() {
+    if (toggleCount.value < toggleMax) {
+      if (r.value) {
+        if (renderer) {
+          if (frameCount < 2) {
+            frameCount++
+            renderer.render(scene!, camera!)
+          }
+          else {
+            camera?.removeFromParent()
+            scene!.children.forEach((m) => { ((m as Mesh).material as Material).dispose(); (m as Mesh).geometry.dispose() })
+            renderer.dispose()
+
+            frameCount = 0
+            camera = null
+            scene = null
+            renderer = null
+
+            showVueThree.value = false
+            toggleCount.value++
+          }
+        }
+        else {
+          renderer = new WebGLRenderer({ canvas: r.value })
+          renderer.setSize(width, height)
+          renderer.setClearColor(new Color('#EEE'))
+          scene = new Scene()
+          camera = new PerspectiveCamera()
+          camera.position.x = 10
+          camera.position.y = 10
+          camera.lookAt(new Vector3(0, 0, 0))
+          for (let i = 0; i < numObjectsMax; i++) {
+            scene.add(new Mesh(new BoxGeometry(), new MeshBasicMaterial()))
+          }
+          scene.add(camera)
+          renderer.render(scene, camera)
+        }
+      }
+      else if (!showVueThree.value) {
+        showVueThree.value = true
+      }
+    }
+    else {
+      const elapsedSec = (Date.now() - startTimeMS.value) / 1000
+      msg.value = `Plain Vue/THREE test completed in ${elapsedSec} seconds.`
+      clearInterval(intervalId)
+    }
+  }
+
+  return testVueThree
+})()
+
+const testTres = (() => {
+  let frameCount = 0
+
+  return () => {
+    if (toggleCount.value < toggleMax) {
+      if (r.value && frameCount < 2) {
+        // NOTE: Wait until Tres has actually rendered before
+        // removing the canvas.
+        ((r.value as Group).children[0] as Mesh).onAfterRender = () => { frameCount++ }
+      }
+      else {
+        if (frameCount < 1) {
+          showTres.value = true
+        }
+        else {
+          toggleCount.value++
+          showTres.value = false
+          frameCount = 0
+        }
+      }
+    }
+    else {
+      const elapsedSec = (Date.now() - startTimeMS.value) / 1000
+      msg.value = `Tres test completed in ${elapsedSec} seconds.`
+      clearInterval(intervalId)
+    }
+  }
+})()
+
+const isStarted = ref(false)
+
+const startTestTres = () => {
+  isStarted.value = true
+  startTimeMS.value = Date.now()
+  // NOTE: Using `setInterval`; it typically will keep
+  // running in situations were `requestAnimationFrame` will pause.
+  intervalId = setInterval(testTres, 1000 / 60)
+  msg.value = 'Test is running...'
+}
+
+const startTestVueThree = () => {
+  isStarted.value = true
+  startTimeMS.value = Date.now()
+  // NOTE: Using `setInterval`; it typically will keep
+  // running in situations were `requestAnimationFrame` will pause.
+  intervalId = setInterval(testVueThree, 1000 / 60)
+  msg.value = 'Test is running...'
+}
+
+onUnmounted(() => {
+  clearInterval(intervalId)
+})
+</script>
+
+<template>
+  <OverlayInfo>
+    <h1>Memory test: Canvases with objects – Tres vs Plain Vue/THREE</h1>
+    <p><span style="color: red">IMPORTANT</span> Epileptic warning: the tests run on this page cause the screen to flash rapidly.</p>
+    <h2>Setup</h2>
+    <p>This test will create and remove {{ toggleMax }} canvas instances with {{ numObjectsMax }} objects/materials/geometries each.</p>
+    <h2>Note</h2>
+    <ul>
+      <li>These tests are intended to help spot memory leaks.</li>
+      <li>Faster/slower test duration does not indicate a problem.</li>
+    </ul>
+    <h2>Status</h2>
+    <p>{{ msg }}</p>
+    <p>Number of canvases created: {{ toggleCount }} / {{ toggleMax }}</p>
+    <button
+      v-if="!isStarted"
+      style="padding: 8px 16px; margin-top: 10px;"
+      @click="startTestTres"
+    >
+      Start Tres test
+    </button>
+
+    <button
+      v-if="!isStarted"
+      style="padding: 8px 16px; margin-top: 10px;"
+      @click="startTestVueThree"
+    >
+      Start plain Vue/THREE test
+    </button>
+  </OverlayInfo>
+  <div v-if="showTres" :style="{ width: `${width}px`, height: `${height}px` }">
+    <TresCanvas clear-color="#EEE">
+      <TresGroup ref="r">
+        <TresMesh v-for="_, i of Array.from({ length: numObjectsMax })" :key="i">
+          <TresMeshBasicMaterial />
+          <TresBoxGeometry />
+        </TresMesh>
+      </TresGroup>
+    </TresCanvas>
+  </div>
+  <div v-if="showVueThree">
+    <canvas ref="r" clear-color="black"></canvas>
+  </div>
+</template>

+ 0 - 75
playground/vue/src/pages/advanced/MemoryTresObjects.vue

@@ -1,75 +0,0 @@
-<script setup lang="ts">
-import { TresCanvas } from '@tresjs/core'
-import { onUnmounted, ref } from 'vue'
-
-const toggleMax = 400
-const numObjectsMax = 2000
-const startTimeMS = ref(0)
-
-const toggleCount = ref(0)
-const show = ref(false)
-const msg = ref('Click Start Test to begin.')
-const r = ref(null)
-const isStarted = ref(false)
-
-let rafId: number
-
-const startTest = () => {
-  isStarted.value = true
-  startTimeMS.value = Date.now()
-  msg.value = 'Test is running...'
-  show.value = true // Start by showing the canvas
-
-  const tick = () => {
-    if (toggleCount.value < toggleMax) {
-      if (r.value && show.value) {
-        show.value = false
-        toggleCount.value++
-      }
-      else if (!show.value) {
-        show.value = true
-      }
-      rafId = requestAnimationFrame(tick)
-    }
-    else {
-      const elapsedSec = (Date.now() - startTimeMS.value) / 1000
-      msg.value = `Test completed in ${elapsedSec} seconds.`
-    }
-  }
-
-  rafId = requestAnimationFrame(tick)
-}
-
-onUnmounted(() => {
-  if (rafId) {
-    cancelAnimationFrame(rafId)
-  }
-})
-</script>
-
-<template>
-  <OverlayInfo>
-    <h1>Memory test: Tres Objects</h1>
-    <h2>Setup</h2>
-    <p>This test will create and remove {{ toggleMax }} TresCanvas instances with {{ numObjectsMax }} objects each.</p>
-    <h2>Status</h2>
-    <p>{{ msg }}</p>
-    <p>Number of TresCanvases created: {{ toggleCount }} / {{ toggleMax }}</p>
-    <button
-      v-if="!isStarted"
-      style="padding: 8px 16px; margin-top: 10px;"
-      @click="startTest"
-    >
-      Start Test
-    </button>
-  </OverlayInfo>
-  <div v-if="show" style="width: 90%; height: 90%; border: 1px solid #F00">
-    <TresCanvas clear-color="black">
-      <TresGroup ref="r" />
-      <TresMesh v-for="_, i of Array.from({ length: numObjectsMax })" :key="i">
-        <TresMeshBasicMaterial />
-        <TresBoxGeometry />
-      </TresMesh>
-    </TresCanvas>
-  </div>
-</template>

+ 2 - 2
playground/vue/src/router/routes/advanced.ts

@@ -51,7 +51,7 @@ export const advancedRoutes = [
   },
   {
     path: '/advanced/memory-tres-objects',
-    name: 'Memory Test: Tres Objects',
-    component: () => import('../../pages/advanced/MemoryTresObjects.vue'),
+    name: 'Memory Test: Tres Canvases/Objects',
+    component: () => import('../../pages/advanced/MemoryTresCanvasesObjects.vue'),
   },
 ]