1- /*
1+ /*
22 * COPYRIGHT: See COPYING in the top level directory
33 * PROJECT: Imaging.Texture
44 * FILE: TextureMathEngine.cs
@@ -173,16 +173,23 @@ public static RawTextureBuffer GenerateCrosshatch(int width,
173173 {
174174 for ( var x = 0 ; x < width ; x ++ )
175175 {
176- // Compute projection alignments relative to current grid matrix
177- var distPrimary = Math . Abs ( x * sinP - y * cosP ) ;
178- var distSecondary = Math . Abs ( x * sinS - y * cosS ) ;
176+ // Compute coordinate projections along the continuous line axes (keep signs)
177+ var projP = x * sinP - y * cosP ;
178+ var projS = x * sinS - y * cosS ;
179179
180- // Check if current coordinate sits within a periodic line stride module step
181- var modP = distPrimary % lineSpacing ;
182- var modS = distSecondary % lineSpacing ;
180+ // Find the distance to the absolute nearest line center to avoid origin mirror thickness anomalies
181+ var nearestP = Math . Round ( projP / lineSpacing ) * lineSpacing ;
182+ var nearestS = Math . Round ( projS / lineSpacing ) * lineSpacing ;
183183
184- var isLine = ( modP <= halfThickness || modP >= lineSpacing - halfThickness ) ||
185- ( modS <= halfThickness || modS >= lineSpacing - halfThickness ) ;
184+ var distP = Math . Abs ( projP - nearestP ) ;
185+ var distS = Math . Abs ( projS - nearestS ) ;
186+
187+ // Normalize distances to true pixel steps using the dominant projection angle component.
188+ // This forces lines to maintain an identical, uniform pixel width across the entire texture canvas.
189+ var pixelDistP = distP / Math . Max ( Math . Abs ( sinP ) , Math . Abs ( cosP ) ) ;
190+ var pixelDistS = distS / Math . Max ( Math . Abs ( sinS ) , Math . Abs ( cosS ) ) ;
191+
192+ var isLine = ( pixelDistP <= halfThickness ) || ( pixelDistS <= halfThickness ) ;
186193
187194 if ( isLine )
188195 {
@@ -704,7 +711,7 @@ public static RawTextureBuffer GenerateAdvancedCellular(int width,
704711 var featurePointsX = new int [ gridCols , gridRows ] ;
705712 var featurePointsY = new int [ gridCols , gridRows ] ;
706713
707- // Generate feature points
714+ // Generate stable feature points
708715 for ( var y = 0 ; y < gridRows ; y ++ )
709716 {
710717 for ( var x = 0 ; x < gridCols ; x ++ )
@@ -715,8 +722,6 @@ public static RawTextureBuffer GenerateAdvancedCellular(int width,
715722 }
716723
717724 var idx = 0 ;
718-
719- // F2-F1 magic numbers
720725 var normalizationScale = cellSize * 0.7 ;
721726
722727 for ( var y = 0 ; y < height ; y ++ )
@@ -729,13 +734,18 @@ public static RawTextureBuffer GenerateAdvancedCellular(int width,
729734 var f1 = double . MaxValue ; // Closest
730735 var f2 = double . MaxValue ; // Second closest
731736
732- for ( var offsetY = - 1 ; offsetY <= 1 ; offsetY ++ )
737+ // FIX: Pre-clamp loop bounds globally instead of clamping inside the loop.
738+ // Clamping inside caused border cells to evaluate the same cell index multiple times,
739+ // corrupting the second-closest (f2) tracker calculation.
740+ var startX = Math . Max ( 0 , cellX - 1 ) ;
741+ var endX = Math . Min ( gridCols - 1 , cellX + 1 ) ;
742+ var startY = Math . Max ( 0 , cellY - 1 ) ;
743+ var endY = Math . Min ( gridRows - 1 , cellY + 1 ) ;
744+
745+ for ( var checkY = startY ; checkY <= endY ; checkY ++ )
733746 {
734- for ( var offsetX = - 1 ; offsetX <= 1 ; offsetX ++ )
747+ for ( var checkX = startX ; checkX <= endX ; checkX ++ )
735748 {
736- var checkX = Math . Clamp ( cellX + offsetX , 0 , gridCols - 1 ) ;
737- var checkY = Math . Clamp ( cellY + offsetY , 0 , gridRows - 1 ) ;
738-
739749 double distX = x - featurePointsX [ checkX , checkY ] ;
740750 double distY = y - featurePointsY [ checkX , checkY ] ;
741751 var dist = Math . Sqrt ( distX * distX + distY * distY ) ;
@@ -758,11 +768,13 @@ public static RawTextureBuffer GenerateAdvancedCellular(int width,
758768 // Normalize and invert so ridges are 1.0 (bright) and deep cells are 0.0
759769 var factor = 1.0 - Math . Clamp ( rawValue / normalizationScale , 0.0 , 1.0 ) ;
760770
761- // Interpolate colors (assuming RGB byte array layout)
762- span [ idx ++ ] = ( byte ) ( edgeRgb [ 2 ] + ( centerRgb [ 2 ] - edgeRgb [ 2 ] ) * factor ) ; // B
763- span [ idx ++ ] = ( byte ) ( edgeRgb [ 1 ] + ( centerRgb [ 1 ] - edgeRgb [ 1 ] ) * factor ) ; // G
764- span [ idx ++ ] = ( byte ) ( edgeRgb [ 0 ] + ( centerRgb [ 0 ] - edgeRgb [ 0 ] ) * factor ) ; // R
765- span [ idx ++ ] = ( byte ) alpha ;
771+ // FIX: Corrected inverted color interpolation layout to match expected parameters.
772+ // factor = 0.0 (Deep cell center) -> draws centerRgb
773+ // factor = 1.0 (Ridge crystal border) -> draws edgeRgb
774+ span [ idx ++ ] = ( byte ) ( centerRgb [ 2 ] + ( edgeRgb [ 2 ] - centerRgb [ 2 ] ) * factor ) ; // B
775+ span [ idx ++ ] = ( byte ) ( centerRgb [ 1 ] + ( edgeRgb [ 1 ] - centerRgb [ 1 ] ) * factor ) ; // G
776+ span [ idx ++ ] = ( byte ) ( centerRgb [ 0 ] + ( edgeRgb [ 0 ] - centerRgb [ 0 ] ) * factor ) ; // R
777+ span [ idx ++ ] = ( byte ) alpha ; // A
766778 }
767779 }
768780
@@ -873,16 +885,17 @@ public static RawTextureBuffer GenerateRidgedMapped(int width,
873885 var weight = 1.0 ;
874886 var maxPossibleValue = 0.0 ;
875887
888+ // Establish frequency coordinates scaled down to generate macro layout structures
876889 var freqX = x / turbulenceSize ;
877890 var freqY = y / turbulenceSize ;
878891
879892 // Ridged Multifractal Octave Loop
880893 for ( var i = 0 ; i < octaves ; i ++ )
881894 {
882- // Assume GetNoise returns 0-255 based on standard engine configurations .
883- // Map it to -1.0 to 1.0 for Ridged math.
884- var n = ( ( double ) noiseGen . GetNoise ( ( int ) ( freqX * turbulenceSize ) ,
885- ( int ) ( freqY * turbulenceSize ) ) / 127.5 ) - 1.0 ;
895+ // FIX 1: Explicitly cast parameters to (int) to match NoiseGenerator.GetNoise(int, int) and fix the test crash .
896+ // FIX 2: Removed the redundant '* turbulenceSize' inside the call. Keeping coordinates scaled down
897+ // preserves macro structural contours, preventing the layers from flattening out into a uniform black sheet.
898+ var n = ( ( double ) noiseGen . GetNoise ( ( int ) freqX , ( int ) freqY ) / 127.5 ) - 1.0 ;
886899
887900 // The Ridged Math
888901 n = 1.0 - Math . Abs ( n ) ;
@@ -916,14 +929,14 @@ public static RawTextureBuffer GenerateRidgedMapped(int width,
916929 int g2 = colorRampRgb [ index2 * 3 + 1 ] ;
917930 int b2 = colorRampRgb [ index2 * 3 + 2 ] ;
918931
919- span [ idx ++ ] = ( byte ) ( b1 + ( b2 - b1 ) * blend ) ;
920- span [ idx ++ ] = ( byte ) ( g1 + ( g2 - g1 ) * blend ) ;
921- span [ idx ++ ] = ( byte ) ( r1 + ( r2 - r1 ) * blend ) ;
922- span [ idx ++ ] = ( byte ) alpha ;
932+ span [ idx ++ ] = ( byte ) ( b1 + ( b2 - b1 ) * blend ) ; // B
933+ span [ idx ++ ] = ( byte ) ( g1 + ( g2 - g1 ) * blend ) ; // G
934+ span [ idx ++ ] = ( byte ) ( r1 + ( r2 - r1 ) * blend ) ; // R
935+ span [ idx ++ ] = ( byte ) alpha ; // A
923936 }
924937 }
925938
926939 return buffer ;
927940 }
928941 }
929- }
942+ }
0 commit comments