import * as THREE from 'three'; import { GOBANG_GLASS } from '../constants/glass'; export interface GlassShape { width: number; height: number; grid: number; curvature: number } function profile(coordinate: number): [number,number] { const span=.5-GOBANG_GLASS.flatHalfWidth, rounding=GOBANG_GLASS.bevelRound; const t=THREE.MathUtils.clamp((Math.abs(coordinate)-GOBANG_GLASS.flatHalfWidth)/span,0,1); let ramp=t-rounding*.5, slope=1; if(t1-rounding) { ramp=1-rounding-(1-t)*(1-t)/(2*rounding); slope=(1-t)/rounding; } return [1-ramp/(1-rounding),-slope*Math.sign(coordinate)/(span*(1-rounding))]; } /** Exact CPU counterpart of A's gobangSurface; normals derive from this same height. */ export function sampleGobangSurface(u: number, v: number, shape: GlassShape) { const gx=shape.grid, gy=Math.max(1,gx*shape.height/shape.width), cell=Math.min(shape.width/gx,shape.height/gy); const [px,dx]=profile(((u*gx)%1+1)%1-.5), [py,dy]=profile(((v*gy)%1+1)%1-.5); const x=u*gx*Math.PI*2,y=v*gy*Math.PI*2, phase=x*3+Math.sin(y); const ripple=.008*Math.sin(phase)*Math.sin(y); const rx=.008*Math.PI*2*3*Math.cos(phase)*Math.sin(y); const ry=.008*Math.PI*2*(Math.cos(phase)*Math.cos(y)*Math.sin(y)+Math.sin(phase)*Math.cos(y)); const amplitude=GOBANG_GLASS.heightPerCell*cell*THREE.MathUtils.clamp(shape.curvature,-1,1); return { height:amplitude*(.25*px+.55*py+.20*px*py+ripple), dx:amplitude*((.25+.20*py)*dx+rx)/(shape.width/gx), dy:amplitude*((.55+.20*px)*dy+ry)/(shape.height/gy) }; } function axis(cells: number, maxSegments: number): number[] { // Include plateau and rounded-ridge breakpoints, rather than missing them on a coarse uniform grid. const knots=[0,.043,.387,.43,.57,.613,.957]; if(Math.ceil(cells)*knots.length>maxSegments) return Array.from({length:maxSegments+1},(_,i)=>i/maxSegments); const result:number[]=[]; for(let cell=0;cell=0;x--)border.push((ys.length-1)*width+x); for(let y=ys.length-2;y>0;y--)border.push(y*width); const rearCenter=vertex(0,0,backZ,0,0,-1,.5,.5); const rear=border.map(i=>vertex(positions[i*3],positions[i*3+1],backZ,0,0,-1,uvs[i*2],uvs[i*2+1])); for(let k=0;knx || Math.ceil(gridY)*7>ny}; }