44import com .kipti .bnb .content .girder_strut .geometry .GirderGeometry ;
55import com .kipti .bnb .content .girder_strut .geometry .GirderVertex ;
66import com .kipti .bnb .content .girder_strut .mesh .GirderMeshQuad ;
7+ import net .createmod .catnip .theme .Color ;
78import net .minecraft .client .Minecraft ;
89import net .minecraft .client .renderer .block .model .BakedQuad ;
910import net .minecraft .client .renderer .texture .TextureAtlasSprite ;
2021import java .util .LinkedHashMap ;
2122import java .util .List ;
2223import java .util .Map ;
24+ import java .util .concurrent .atomic .AtomicInteger ;
2325
2426public final class GirderCapAccumulator {
2527
2628 private static final float POSITION_TOLERANCE = 1.0e-4f ;
29+ private static final boolean DEBUG_OUTLINES = true ;
30+ private static final AtomicInteger DEBUG_SEQUENCE = new AtomicInteger ();
31+ private static final String DEBUG_KEY_ROOT = "girderCap" ;
32+ private static final Color SEGMENT_COLOR = new Color (245 , 168 , 66 );
33+ private static final Color LOOP_COLOR = new Color (201 , 86 , 228 );
34+ private static final Color PROJECTED_COLOR = new Color (86 , 203 , 228 );
35+ private static final Color FINAL_COLOR = new Color (114 , 228 , 86 );
36+ private static final Color PLANE_NORMAL_COLOR = new Color (255 , 255 , 255 );
2737
2838 private final ResourceLocation stoneLocation ;
2939 private final List <CapSegment > segments = new ArrayList <>();
@@ -45,15 +55,26 @@ public void addSegments(TextureAtlasSprite sourceSprite, int tintIndex, boolean
4555 }
4656
4757 public void emitCaps (Vector3f planePoint , Vector3f planeNormal , List <BakedQuad > consumer ) {
58+ int debugId = 0 ;
59+ if (DEBUG_OUTLINES ) {
60+ debugId = DEBUG_SEQUENCE .incrementAndGet ();
61+ debugPlane (debugId , planePoint , planeNormal );
62+ debugSegments (debugId );
63+ }
64+
4865 List <CapLoop > loops = buildLoops (planePoint , planeNormal );
66+ if (DEBUG_OUTLINES ) {
67+ debugLoopInputs (debugId , loops );
68+ }
4969 if (loops .isEmpty ()) {
5070 return ;
5171 }
5272
5373 TextureAtlasSprite stoneSprite = Minecraft .getInstance ().getTextureAtlas (InventoryMenu .BLOCK_ATLAS ).apply (stoneLocation );
5474
55- for (CapLoop loop : loops ) {
56- emitLoop (loop .vertices (), planeNormal , planePoint , stoneSprite , loop .key ().tintIndex (), loop .key ().shade (), consumer );
75+ for (int i = 0 ; i < loops .size (); i ++) {
76+ CapLoop loop = loops .get (i );
77+ emitLoop (loop .vertices (), planeNormal , planePoint , stoneSprite , loop .key ().tintIndex (), loop .key ().shade (), consumer , debugId , i );
5778 }
5879
5980 segments .clear ();
@@ -170,7 +191,9 @@ private void emitLoop(
170191 TextureAtlasSprite stoneSprite ,
171192 int tintIndex ,
172193 boolean shade ,
173- List <BakedQuad > consumer
194+ List <BakedQuad > consumer ,
195+ int debugId ,
196+ int loopIndex
174197 ) {
175198 Vector3f normalizedPlane = new Vector3f (planeNormal );
176199 if (normalizedPlane .lengthSquared () > GirderGeometry .EPSILON ) {
@@ -193,12 +216,23 @@ private void emitLoop(
193216 ));
194217 }
195218
219+ if (DEBUG_OUTLINES ) {
220+ debugProjectedLoop (debugId , loopIndex , loop , PROJECTED_COLOR , 1f / 64f , "projected" );
221+ }
222+
196223 List <GirderVertex > cleaned = GirderGeometry .dedupeLoopVertices (loop );
197224 if (cleaned .size () < 3 ) {
198225 CreateBitsnBobs .LOGGER .debug ("[GirderCap] loop dropped after dedupe - insufficient vertices {}" , cleaned .size ());
226+ if (DEBUG_OUTLINES ) {
227+ debugProjectedLoop (debugId , loopIndex , cleaned , FINAL_COLOR , 1f / 96f , "final" );
228+ }
199229 return ;
200230 }
201231
232+ if (DEBUG_OUTLINES ) {
233+ debugProjectedLoop (debugId , loopIndex , cleaned , FINAL_COLOR , 1f / 96f , "final" );
234+ }
235+
202236 Vector3f polygonNormal = GirderGeometry .computePolygonNormal (cleaned );
203237 if (polygonNormal .lengthSquared () > GirderGeometry .EPSILON && polygonNormal .dot (faceNormal ) < 0f ) {
204238 java .util .Collections .reverse (cleaned );
@@ -311,6 +345,91 @@ private static float angleDelta(float from, float to) {
311345 return delta ;
312346 }
313347
348+ private void debugPlane (int debugId , Vector3f planePoint , Vector3f planeNormal ) {
349+ if (!DEBUG_OUTLINES ) {
350+ return ;
351+ }
352+ Vector3f normal = new Vector3f (planeNormal );
353+ if (normal .lengthSquared () <= GirderGeometry .EPSILON ) {
354+ return ;
355+ }
356+ normal .normalize ();
357+ Vector3f start = new Vector3f (planePoint );
358+ Vector3f end = new Vector3f (planePoint ).add (new Vector3f (normal ).mul (0.5f ));
359+ showLine (debugKey (debugId , "plane" , 0 , 0 ), start , end , PLANE_NORMAL_COLOR , 1f / 32f );
360+ }
361+
362+ private void debugSegments (int debugId ) {
363+ if (!DEBUG_OUTLINES || segments .isEmpty ()) {
364+ return ;
365+ }
366+ int index = 0 ;
367+ for (CapSegment segment : segments ) {
368+ Vector3f start = segment .start ().position ();
369+ Vector3f end = segment .end ().position ();
370+ if (GirderGeometry .positionsEqual (start , end )) {
371+ continue ;
372+ }
373+ showLine (debugKey (debugId , "segments" , index , 0 ), start , end , SEGMENT_COLOR , 1f / 24f );
374+ index ++;
375+ }
376+ }
377+
378+ private void debugLoopInputs (int debugId , List <CapLoop > loops ) {
379+ if (!DEBUG_OUTLINES || loops .isEmpty ()) {
380+ return ;
381+ }
382+ for (int i = 0 ; i < loops .size (); i ++) {
383+ CapLoop loop = loops .get (i );
384+ List <Vector3f > positions = new ArrayList <>(loop .vertices ().size ());
385+ for (CapVertex vertex : loop .vertices ()) {
386+ positions .add (new Vector3f (vertex .position ()));
387+ }
388+ showPolyline (debugId , "loops" , i , positions , LOOP_COLOR , 1f / 48f , true );
389+ }
390+ }
391+
392+ private void debugProjectedLoop (int debugId , int loopIndex , List <GirderVertex > vertices , Color color , float width , String stage ) {
393+ if (!DEBUG_OUTLINES || vertices .isEmpty ()) {
394+ return ;
395+ }
396+ List <Vector3f > positions = new ArrayList <>(vertices .size ());
397+ for (GirderVertex vertex : vertices ) {
398+ positions .add (new Vector3f (vertex .position ()));
399+ }
400+ showPolyline (debugId , stage , loopIndex , positions , color , width , true );
401+ }
402+
403+ private static void showPolyline (int debugId , String stage , int groupIndex , List <Vector3f > positions , Color color , float width , boolean closed ) {
404+ if (positions .size () < 2 ) {
405+ return ;
406+ }
407+ int segmentIndex = 0 ;
408+ for (int i = 0 ; i < positions .size () - 1 ; i ++) {
409+ Vector3f start = positions .get (i );
410+ Vector3f end = positions .get (i + 1 );
411+ if (GirderGeometry .positionsEqual (start , end )) {
412+ continue ;
413+ }
414+ showLine (debugKey (debugId , stage , groupIndex , segmentIndex ++), start , end , color , width );
415+ }
416+ if (closed ) {
417+ Vector3f start = positions .get (positions .size () - 1 );
418+ Vector3f end = positions .get (0 );
419+ if (!GirderGeometry .positionsEqual (start , end )) {
420+ showLine (debugKey (debugId , stage , groupIndex , segmentIndex ), start , end , color , width );
421+ }
422+ }
423+ }
424+
425+ private static void showLine (String key , Vector3f from , Vector3f to , Color color , float width ) {
426+ GirderCapDebugOutlines .queueLine (key , from , to , color , width );
427+ }
428+
429+ private static String debugKey (int debugId , String stage , int groupIndex , int segmentIndex ) {
430+ return DEBUG_KEY_ROOT + '/' + debugId + '/' + stage + '/' + groupIndex + '/' + segmentIndex ;
431+ }
432+
314433 private record CapSegment (CapVertex start , CapVertex end , int tintIndex , boolean shade ) {
315434 }
316435
0 commit comments