Sphere explorer: stop leaking GPU memory on every rebuild; render only when needed

Every slider move rebuilt all lines without disposing the old geometries and materials,
and the render loop ran at full rate even when idle or hidden.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01161aC97vUnBnyZRBGyJeHy
This commit is contained in:
teahubxyzandClaude Opus 5.5 committed 2026-10-23 20:26:50 +00:00
1 parent a111980b74
commit fc624a53c0
1 file changed
+7 -4
+7 -4
View File
@@ -98,7 +98,7 @@ function toPlane([x,y]){return new THREE.Vector3(x*lift,-1.001,y*lift)}
const W=()=>innerWidth,H=()=>innerHeight;
const renderer=new THREE.WebGLRenderer({antialias:true,alpha:false});
renderer.setPixelRatio(Math.min(devicePixelRatio,2));renderer.setClearColor(new THREE.Color(css('--bg')));
renderer.setPixelRatio(Math.min(devicePixelRatio,1.5));renderer.setClearColor(new THREE.Color(css('--bg')));
document.getElementById('stage').appendChild(renderer.domElement);
const scene=new THREE.Scene();
const cam=new THREE.PerspectiveCamera(40,1,0.01,100);cam.position.set(2.6,-2.4,3.2);
@@ -117,8 +117,11 @@ const invP=([x,y])=>{const r=x*x+y*y;return r<1e-12?[1e6,0]:[x/r,y/r]};
const trisDense=T.map(([lx,by,ay,rx,ty])=>{const A=P(lx,by),B=P(150,ay),Cc=P(rx,by);return{up:!!ty,pts:[...seg(A,B,600),...seg(B,Cc,600).slice(1),...seg(Cc,A,600).slice(1)]}});
const bindu2=new THREE.Mesh(new THREE.SphereGeometry(.022,16,12),new THREE.MeshBasicMaterial({color:C.bindu}));scene.add(bindu2);
function build(){
group.clear();planeG.clear();
const drop=g=>{g.traverse(o=>{if(o.geometry)o.geometry.dispose();if(o.material)o.material.dispose()});g.clear()};
let pending=false;
function build(){if(pending)return;pending=true;requestAnimationFrame(()=>{pending=false;rebuild()})}
function rebuild(){
drop(group);drop(planeG);
const mk=(pts,col,op,g,f)=>g.add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(pts.map(f)),new THREE.LineBasicMaterial({color:col,transparent:op<1,opacity:op})));
tris.forEach(t=>mk(t.pts,t.up?C.up:C.down,1,group,toSphere));
decor.forEach(d=>mk(d,C.fg,.45,group,toSphere));
@@ -142,7 +145,7 @@ function resize(){renderer.setSize(W(),H());cam.aspect=W()/H();cam.updateProject
addEventListener('resize',resize);resize();build();
const reduce=matchMedia('(prefers-reduced-motion: reduce)').matches;
if(reduce){ctl.autoRotate=false;document.getElementById('t-spin').setAttribute('aria-pressed','false')}
(function loop(){requestAnimationFrame(loop);ctl.update();renderer.render(scene,cam)})();
(function loop(){requestAnimationFrame(loop);if(document.hidden)return;ctl.update();renderer.render(scene,cam)})();
const $=id=>document.getElementById(id);
function setMode(m){mode=m;$('m-stereo').setAttribute('aria-pressed',m==='stereo');$('m-gnomo').setAttribute('aria-pressed',m==='gnomo');build()}