← Natura·Docs/Modules/Source

creatures/sdf-bench.html

42 lines · in natura-src-1.0.0.zip as natura/creatures/sdf-bench.html · creature bench: the SDF-unified elephant against the primitive build

<!doctype html>
<html><head><meta charset="utf-8"><title>elephant unify comparison</title>
<style>body{margin:0;background:#141c28}canvas{display:block}</style></head>
<body>
<canvas id="c" width="1180" height="640"></canvas>
<script src="render3d.js"></script>
<script src="sdfmesh.js"></script>
<script src="rig.js"></script>
<script>
const cv=document.getElementById('c'),ctx=cv.getContext('2d');
const V=(x,y,z)=>({x,y,z});
function bez(P0,P1,P2,P3,u){const m=1-u;return V(m*m*m*P0.x+3*m*m*u*P1.x+3*m*u*u*P2.x+u*u*u*P3.x,m*m*m*P0.y+3*m*m*u*P1.y+3*m*u*u*P2.y+u*u*u*P3.y,m*m*m*P0.z+3*m*m*u*P1.z+3*m*u*u*P2.z+u*u*u*P3.z);}
function addDetails(out,pose){ const P=Creatures3D.prims,asian=pose.species==='asian';
  const hx=1.34,hy=1.74-(pose.headDown||0)*0.34,flare=pose.earFlare||0;
  const IVORY=[232,226,208],AMBER=[92,63,38],PUP=[22,17,13],SKIN=[138,133,126],INNER=[150,132,128];
  // ears: thin fanning sheets, hinged INTO the head side so they connect to the SDF head (not floating)
  for(const s of [-1,1]) P.earFan(out, hx-0.24, hy+0.22, s*(0.22+flare*0.1), s, (asian?0.60:1.06)+flare*0.06, SKIN, INNER, pose.detail==null?0.8:pose.detail);
  // tusks
  for(const s of [-1,1]){ const bx=hx+0.26,by=hy-0.24,bz=s*0.20,rr=asian?0.05:0.085,ext=asian?0.4:1.0;
    const T0=V(bx,by,bz),T1=V(bx+0.45*ext,by-0.30*ext,bz+s*0.05),T2=V(bx+0.75*ext,by-0.45*ext,bz+s*0.02),T3=V(bx+0.92*ext,by-0.30*ext,bz);
    const path=[],rad=[],NB=8; for(let i=0;i<=NB;i++){const u=i/NB;path.push(bez(T0,T1,T2,T3,u));rad.push(rr*(1-0.8*u)+0.012);} P.tube(out,path,rad,8,IVORY,true); }
  // eyes
  for(const s of [-1,1]){ const ex=hx+0.30,ey=hy-0.01,ez=s*0.34;
    P.ellipsoid(out,V(ex,ey,ez),V(0.055,0.058,0.052),10,8,AMBER);
    P.ellipsoid(out,V(ex+0.038,ey,ez+s*0.006),V(0.032,0.034,0.030),8,6,PUP); }
}
function draw(pose,az){ pose=pose||{species:'asian',detail:0.9}; az=az==null?-0.6:az;
  ctx.fillStyle='#141c28'; ctx.fillRect(0,0,cv.width,cv.height);
  // LEFT: current intersecting primitives
  const fa=Creatures3D.buildElephant(pose);
  Creatures3D.render(ctx,fa,{az,el:-0.12,scale:190,ox:300,oy:350,yc:1.05,shadow:false});
  // RIGHT: SDF unified surface-nets mesh + tusks/eyes on top
  const fb=CreaturesSDF.buildElephantSDF(pose,{N:(pose.__N||46)});
  addDetails(fb,pose);
  Creatures3D.render(ctx,fb,{az,el:-0.12,scale:190,ox:830,oy:350,yc:1.05,shadow:false});
  ctx.fillStyle='#8fa0b2'; ctx.font='14px system-ui'; ctx.textAlign='center';
  ctx.fillText('A: intersecting primitives',300,610); ctx.fillText('B: SDF smooth-union (surface nets)',830,610);
}
draw();
window.__b={ draw };
</script>
</body></html>