@@ -80,9 +80,9 @@ function buildPrismsFromNodes(
8080 const xyKey = ( n : CapacityMeshNode ) =>
8181 `${ n . center . x . toFixed ( 8 ) } |${ n . center . y . toFixed ( 8 ) } |${ n . width . toFixed ( 8 ) } |${ n . height . toFixed ( 8 ) } `
8282 const azKey = ( n : CapacityMeshNode ) => {
83- const zs = ( n . availableZ && n . availableZ . length ? [ ... new Set ( n . availableZ ) ] : [ 0 ] ) . sort (
84- ( a , b ) => a - b ,
85- )
83+ const zs = (
84+ n . availableZ && n . availableZ . length ? [ ... new Set ( n . availableZ ) ] : [ 0 ]
85+ ) . sort ( ( a , b ) => a - b )
8686 return `zset:${ zs . join ( "," ) } `
8787 }
8888 const key = ( n : CapacityMeshNode ) => `${ xyKey ( n ) } |${ azKey ( n ) } `
@@ -226,8 +226,13 @@ const ThreeBoardView: React.FC<{
226226 const w = el . clientWidth || 800
227227 const h = el . clientHeight || height
228228
229- const renderer = new THREE . WebGLRenderer ( { antialias : true } )
230- renderer . setPixelRatio ( Math . min ( window . devicePixelRatio , 2 ) )
229+ const renderer = new THREE . WebGLRenderer ( {
230+ antialias : true ,
231+ alpha : true ,
232+ premultipliedAlpha : false ,
233+ } )
234+ // Increase pixel ratio for better alphaHash quality
235+ renderer . setPixelRatio ( window . devicePixelRatio )
231236 renderer . setSize ( w , h )
232237 el . innerHTML = ""
233238 el . appendChild ( renderer . domElement )
@@ -300,7 +305,7 @@ const ThreeBoardView: React.FC<{
300305 const dx = b . maxX - b . minX
301306 const dz = b . maxY - b . minY // map board Y -> three Z
302307 const dy = ( b . z1 - b . z0 ) * layerThickness
303- const cx = ( b . minX + b . maxX ) / 2
308+ const cx = - ( ( b . minX + b . maxX ) / 2 ) // negate X to match expected orientation
304309 const cz = ( b . minY + b . maxY ) / 2
305310 // Negate Y so z=0 is at top, higher z goes down
306311 const cy = - ( ( b . z0 + b . z1 ) / 2 ) * layerThickness
@@ -321,6 +326,7 @@ const ThreeBoardView: React.FC<{
321326 opacity : clampedOpacity ,
322327 transparent : clampedOpacity < 1 ,
323328 alphaHash : clampedOpacity < 1 ,
329+ alphaToCoverage : true ,
324330 } )
325331
326332 const mesh = new THREE . Mesh ( geom , mat )
@@ -472,15 +478,15 @@ const ThreeBoardView: React.FC<{
472478 const dist = size * 2.0
473479 // Camera looks from above-right-front, with negative Y being "up" (z=0 at top)
474480 camera . position . set (
475- fitBox . maxX + dist * 0.6 ,
481+ - ( fitBox . maxX + dist * 0.6 ) , // negate X to account for flipped axis
476482 - dy / 2 + dist , // negative Y is up, so position above the center
477483 fitBox . maxY + dist * 0.6 ,
478484 )
479485 camera . near = Math . max ( 0.1 , size / 100 )
480486 camera . far = dist * 10 + size * 10
481487 camera . updateProjectionMatrix ( )
482488 controls . target . set (
483- ( fitBox . minX + fitBox . maxX ) / 2 ,
489+ - ( ( fitBox . minX + fitBox . maxX ) / 2 ) , // negate X to account for flipped axis
484490 - dy / 2 , // center of the inverted Y range
485491 ( fitBox . minY + fitBox . maxY ) / 2 ,
486492 )
@@ -553,7 +559,7 @@ export const SolverDebugger3d: React.FC<SolverDebugger3dProps> = ({
553559 solver,
554560 simpleRouteJson,
555561 layerThickness = 1 ,
556- height = 460 ,
562+ height = 600 ,
557563 defaultShowRoot = true ,
558564 defaultShowObstacles = false , // don't show obstacles by default
559565 defaultShowOutput = true ,
@@ -568,31 +574,58 @@ export const SolverDebugger3d: React.FC<SolverDebugger3dProps> = ({
568574 const [ showOutput , setShowOutput ] = useState ( defaultShowOutput )
569575 const [ wireframeOutput , setWireframeOutput ] = useState ( defaultWireframeOutput )
570576
571- const [ meshOpacity , setMeshOpacity ] = useState ( 1 ) // fully opaque by default
572- const [ shrinkBoxes , setShrinkBoxes ] = useState ( false )
577+ const [ meshOpacity , setMeshOpacity ] = useState ( 0.6 )
578+ const [ shrinkBoxes , setShrinkBoxes ] = useState ( true )
573579 const [ boxShrinkAmount , setBoxShrinkAmount ] = useState ( 0.1 )
574- const [ showBorders , setShowBorders ] = useState ( false )
580+ const [ showBorders , setShowBorders ] = useState ( true )
575581
576- // Keep mesh nodes in sync with solver
577- const meshNodes = useMemo ( ( ) => {
582+ // Mesh nodes state - updated when solver completes or during stepping
583+ const [ meshNodes , setMeshNodes ] = useState < CapacityMeshNode [ ] > ( [ ] )
584+
585+ // Update mesh nodes from solver output
586+ const updateMeshNodes = useCallback ( ( ) => {
578587 try {
579- if (
580- ( solver as any ) . solved !== true &&
581- typeof solver . solve === "function"
582- ) {
583- solver . solve ( )
584- }
585- } catch { }
586- return solver . getOutput ( ) . meshNodes ?? [ ]
588+ const output = solver . getOutput ( )
589+ const nodes = output . meshNodes ?? [ ]
590+ setMeshNodes ( nodes )
591+ } catch {
592+ setMeshNodes ( [ ] )
593+ }
587594 } , [ solver ] )
588595
596+ // Initialize mesh nodes on mount (in case solver is already solved)
597+ useEffect ( ( ) => {
598+ updateMeshNodes ( )
599+ // eslint-disable-next-line react-hooks/exhaustive-deps
600+ } , [ ] )
601+
602+ // Handle solver completion
603+ const handleSolverCompleted = useCallback ( ( ) => {
604+ updateMeshNodes ( )
605+ } , [ updateMeshNodes ] )
606+
607+ // Poll for updates during stepping (GenericSolverDebugger doesn't have onStep)
608+ useEffect ( ( ) => {
609+ const interval = setInterval ( ( ) => {
610+ // Only update if solver has output available
611+ if ( ( solver as any ) . solved || ( solver as any ) . stats ?. placed > 0 ) {
612+ updateMeshNodes ( )
613+ }
614+ } , 100 ) // Poll every 100ms during active solving
615+
616+ return ( ) => clearInterval ( interval )
617+ } , [ updateMeshNodes , solver ] )
618+
589619 const toggle3d = useCallback ( ( ) => setShow3d ( ( s ) => ! s ) , [ ] )
590620 const rebuild = useCallback ( ( ) => setRebuildKey ( ( k ) => k + 1 ) , [ ] )
591621
592622 return (
593623 < >
594624 < div style = { { display : "grid" , gap : 12 , ...style } } >
595- < GenericSolverDebugger solver = { solver as any } />
625+ < GenericSolverDebugger
626+ solver = { solver as any }
627+ onSolverCompleted = { handleSolverCompleted }
628+ />
596629
597630 < div
598631 style = { {
0 commit comments