@@ -45,22 +45,27 @@ inline double fastPow(double a, double b) {
45
45
return u .d ;
46
46
}
47
47
48
+
48
49
// ===========================================================================================
49
50
// A Mandelbrot image.
50
51
//
51
52
52
-
53
- MandelbrotImage :: MandelbrotImage ( double * params , bool fpga_param ) {
53
+ MandelbrotImage :: MandelbrotImage ( json & j ) {
54
+ params_json = j ;
54
55
55
56
// // Print sizeof(stuff)
56
57
//cout << "int: " << sizeof(int) << ", long: " << sizeof(long) << ", long long: " << sizeof(long long) << ", float: " << sizeof(float) << ", double: " << sizeof(double) << ", long double: " << sizeof(long double) << endl;
57
58
58
- fpga = fpga_param ; // Currently we restrict image settings based on whether the FPGA was _requested_ (whether available/used or not).
59
- test_flags = ( int )( params [ 23 ] );
59
+ fpga = param < string > ( "renderer" , "fpga" ) == "fpga" ; // Currently we restrict image settings based on whether the FPGA was _requested_ (whether available/used or not).
60
+ param ( " test_flags" , test_flags , 0 );
60
61
for (int i = 0 ; i < 16 ; i ++ ) {
61
- test_vars [i ] = (int )(params [24 + i ]);
62
+ try {
63
+ j ["test_vars" ][i ].get_to (test_vars [i ]);
64
+ } catch (nlohmann ::detail ::exception ) {
65
+ test_vars [i ] = 0.0L ;
66
+ }
62
67
}
63
-
68
+
64
69
verbosity = (int )getTestVar (15 , -10.0 , 10.0 );
65
70
if (verbosity < 0 ) {verbosity = 0 ;}
66
71
@@ -81,7 +86,6 @@ MandelbrotImage::MandelbrotImage(double *params, bool fpga_param) {
81
86
}
82
87
83
88
enableTimer (0 );
84
-
85
89
86
90
depth_array = right_depth_array = NULL ;
87
91
fractional_depth_array = right_fractional_depth_array = NULL ;
@@ -91,9 +95,12 @@ MandelbrotImage::MandelbrotImage(double *params, bool fpga_param) {
91
95
req_width = req_height = 0 ;
92
96
calc_width = calc_height = 0 ;
93
97
x = y = req_pix_size = calc_pix_size = (coord_t )0.0L ;
94
- is_3d = (params [9 ] > 0.0L );
95
- int modes = (int )(params [16 ]); // Bits, lsb first: 0: python(irrelevant here), 1: C++, 2: reserved, 3: optimize1, 4-5: reserved, 6: full-image, ...
96
- int colors = (int )(params [17 ]);
98
+ param ("three_d" , is_3d , false);
99
+ int modes ;
100
+ param ("modes" , modes , 0 ); // Bits, lsb first: 0: python(irrelevant here), 1: C++, 2: reserved, 3: optimize1, 4-5: reserved, 6: full-image, ...
101
+ int colors ;
102
+ param ("colors" , colors , 0 );
103
+
97
104
98
105
// Active color scheme
99
106
active_color_scheme_index = colors & 65535 ;
@@ -105,18 +112,17 @@ MandelbrotImage::MandelbrotImage(double *params, bool fpga_param) {
105
112
color_shift = ((colors >> 16 ) & 255 ) * color_scheme_size [active_color_scheme_index ] / 100 ; // amount to shift color scheme given as 0-99 (percent) and adjusted for color scheme size.
106
113
full_image = (bool )((modes >> 6 ) & 1 );
107
114
//+int color_scheme = (int)(params[17]);
108
- spot_depth = ( int )( params [ 18 ] );
115
+ param ( " spot_depth" , spot_depth , -1 );
109
116
show_spot = spot_depth >= 0 ;
110
- brighten = ( int )( params [ 13 ] );
111
- eye_adjust = params [ 14 ] ;
117
+ param ( " brighten" , brighten , 0 );
118
+ param < coord_t > ( " eye_adjust" , eye_adjust , 0.0L ) ;
112
119
int eye_sep_adjust = (int )(getTestVar (14 , -500.0f , 500.0f ));
113
- req_eye_separation = params [ 15 ] + eye_sep_adjust ;
114
- adjustment = params [ 7 ] / 100.0L ;
115
- adjustment2 = params [ 8 ] / 100.0L ;
120
+ req_eye_separation = param ( "eye_sep" , 0.0L ) + eye_sep_adjust ;
121
+ adjustment = param < coord_t > ( "var1" , 0.0L ) / 100.0L ;
122
+ adjustment2 = param < coord_t > ( "var2" , 0.0L ) / 100.0L ;
116
123
adjust = (adjustment != 0.0L || adjustment2 != 0.0L ) && !fpga ;
117
124
118
-
119
- int texture = fpga ? 0 : (int )(params [19 ]);
125
+ int texture = fpga ? 0 : param < int > ("texture" , 0 );
120
126
string_lights = (bool )((texture >> 0 ) & 1 );
121
127
fanciful_pattern = (bool )((texture >> 1 ) & 1 );
122
128
shadow_interior = (bool )((texture >> 2 ) & 1 );
@@ -126,16 +132,15 @@ MandelbrotImage::MandelbrotImage(double *params, bool fpga_param) {
126
132
light_brightness = getTestVar (13 , 1.0f , 5.2f );
127
133
128
134
power_divergence = getTestFlag (6 );
129
- int edge_style = (fpga || power_divergence ) ? 0 : ( int )( params [ 20 ] );
135
+ int edge_style = (fpga || power_divergence ) ? 0 : param < int > ( "edge" , 0 );
130
136
square_divergence = edge_style == 1 ;
131
137
y_squared_divergence = edge_style == 2 ;
132
138
normal_divergence = !(power_divergence || square_divergence || y_squared_divergence || ornaments );
133
- int theme = fpga ? 0 : ( int )( params [ 21 ] );
139
+ int theme = fpga ? 0 : param < int > ( "theme" , 0 );
134
140
no_theme = theme == 0 ;
135
141
xmas_theme = theme == 1 ;
136
-
137
- cycle = (int )(params [22 ]);
138
-
142
+
143
+ param ("cycle" , cycle , 0 );
139
144
test_texture = getTestFlag (0 );
140
145
lighting = string_lights || fanciful_pattern || shadow_interior || round_edges ;
141
146
textured = (test_texture || lighting ) && !fpga ;
@@ -157,7 +162,7 @@ MandelbrotImage::MandelbrotImage(double *params, bool fpga_param) {
157
162
use_derivatives = getTestFlag (15 );
158
163
159
164
// For darkening distant 3D depths.
160
- darken = ( params [ 12 ] > 0.0L );
165
+ param ( " darken" , darken , false );
161
166
texture_max = !darken && getTestFlag (27 ); // Apply texture to max depth. Note that use_next has no effect on max-depth texture, as next_* have not been updated for max_depth.
162
167
// Do not darken if debugging max depth, as it could change dynamically.
163
168
half_faded_depth = 30 ;
@@ -193,18 +198,17 @@ MandelbrotImage::MandelbrotImage(double *params, bool fpga_param) {
193
198
194
199
assert (! IS_BIG_ENDIAN );
195
200
196
- x = (coord_t )params [0 ];
197
- y = (coord_t )params [1 ];
198
- req_pix_size = (coord_t )params [2 ]; // (assuming same size x and y, even though both are sent)
199
- //pix_y = (coord_t)params[3];
200
- req_width = (int )params [4 ];
201
- req_height = (int )params [5 ];
201
+ x = param < coord_t > ("x" , 0.0L );
202
+ y = param < coord_t > ("y" , 0.0L );
203
+ param < coord_t > ("pix_x" , req_pix_size , 0.0L ); // (assuming same size x and y, even though both are sent)
204
+ param ("width" , req_width , 0 );
205
+ param ("height" , req_height , 0 );
202
206
calc_width = req_width ; // assuming not 3d and not limited by FPGA restrictions
203
207
calc_height = req_height ; // "
204
- spec_max_depth = ( int ) params [ 6 ] ;
208
+ param ( "max_depth" , spec_max_depth , 250 ) ;
205
209
max_depth = -1000 ; // garbage value
206
- if (getTestFlag (2 )) {spec_max_depth = ( int )( sqrt (params [ 6 ]) ) - 4 ;}
207
- req_eye_offset = ( int )( params [ 10 ] ) - (eye_sep_adjust >> 1 );
210
+ if (getTestFlag (2 )) {spec_max_depth = sqrt (spec_max_depth ) - 4 ;}
211
+ req_eye_offset = param < int > ( "offset_w" , 0 ) - (eye_sep_adjust >> 1 );
208
212
is_stereo = is_3d && req_eye_separation > 0 ;
209
213
req_center_w = req_width >> 1 ; // (adjusted by req_eye_offset for stereo 3D)
210
214
req_center_h = req_height >> 1 ;
@@ -288,8 +292,7 @@ MandelbrotImage::MandelbrotImage(double *params, bool fpga_param) {
288
292
if (verbosity > 0 )
289
293
cout << "Settings: smooth: " << smooth << ", smooth_texture: " << smooth_texture << ", divergence_fn: " << power_divergence << y_squared_divergence << square_divergence << normal_divergence
290
294
<< ", string_lights: " << string_lights << "expansion_factor_3d: " << expansion_factor_3d << "req: (" << req_width << ", " << req_height << "), calc: (" << calc_width << ", " << calc_height << ")" << endl ;
291
- };
292
-
295
+ }
293
296
294
297
295
298
MandelbrotImage ::~MandelbrotImage () {
@@ -873,12 +876,43 @@ inline int MandelbrotImage::pixelDepth(int w, int h, bool trying) {
873
876
if (round_edges ) {
874
877
float beyond = divergent_radius + (outward - ornament_shrink ) / 1.5f * divergent_radius ; // Divisor increases rounding.
875
878
next_effective_radius_sq = beyond * beyond ;
876
- }
879
+ }
877
880
}
878
881
}
879
882
}
880
883
}
881
- next_diverges = next_effective_radius_sq > divergent_radius_sq || force_diverge ;
884
+
885
+ // Experimental approximations for determining convergence and stopping the search on convergence as well as divergence:
886
+ // These are interesting and worth enabling.
887
+ bool conv = false;
888
+ /*
889
+ // Look at fixed windows of radius history and compare.
890
+ x_hist[depth % 16] = xx * xx + yy * yy;
891
+ // Is there a convergent trend.
892
+ if (depth > 16) {
893
+ coord_t diff = 0.0L;
894
+ for (int i = 0; i < 8; i++) {
895
+ diff += x_hist[(depth - i - 8) % 16] - x_hist[(depth - i ) % 16];
896
+ }
897
+ conv = diff > sqrt(x0 * x0 + y0 * y0);
898
+ }
899
+ */
900
+ /*
901
+ // Keep two weighted radius histories with different decay. If that slower decay has a larger value, there's convergence.
902
+ if (depth == 0) {
903
+ exp = 0.0L;
904
+ exp2 = 0.0L;
905
+ } else {
906
+ exp = 0.95L * exp + 0.05L * (xx * xx + yy * yy);
907
+ exp2 = 0.98L * exp2 + 0.02L * (xx * xx + yy * yy);
908
+ }
909
+ conv = exp < 0.99L * exp2;
910
+ */
911
+ next_diverges = next_effective_radius_sq > divergent_radius_sq ||
912
+ //next_effective_radius_sq < 0.01 || // Creates dots inside (mostly) convergent region.
913
+ //(dxx_dx0 * dxx_dx0 + dyy_dx0 * dyy_dx0 < 0.01 && depth > 0) || // Creates dots inside (mostly) convergent region. (need_derivatives must be true)
914
+ conv ||
915
+ force_diverge ;
882
916
883
917
884
918
// DONE?
@@ -1051,8 +1085,6 @@ inline int MandelbrotImage::pixelDepth(int w, int h, bool trying) {
1051
1085
bool radial = getTestFlag (1 ) || smooth_texture ;
1052
1086
float a_granularity = ((float )(1 << (int )getTestVar (5 , 0.0 , 12.0 ))) / 64.0f ; //fastPow(2.0L, (double)(int)getTestVar(5, -6.0, 6.0));
1053
1087
float b_granularity = ((float )(1 << (int )getTestVar (6 , 0.0 , 12.0 ))) / 64.0f ; //fastPow(2.0L, (double)(int)getTestVar(6, -6.0, 6.0));
1054
- //-bool fine_grained = getTestFlag(8);
1055
- //-bool coarse_grained = getTestFlag(9);
1056
1088
bool two_tone = getTestFlag (10 );
1057
1089
bool use_next = getTestFlag (11 );
1058
1090
float a_adj = getTestVar (3 , 0.0f , 2.0f );
@@ -1444,7 +1476,7 @@ MandelbrotImage *MandelbrotImage::generateMandelbrot() {
1444
1476
// initial approximation.
1445
1477
if (adjust ) {
1446
1478
// Matched to eye depth.
1447
- adjust_depth = start_darkening_depth ; // Begin adjustment where we begin darkening (both should be around first visible level) //- getZoomDepth() - eye_depth_fit - eye_adjust;
1479
+ adjust_depth = start_darkening_depth ; // Begin adjustment where we begin darkening (both should be around first visible level)
1448
1480
}
1449
1481
if (verbosity > 3 )
1450
1482
cout << "adjust: " << adjust << ", adjust_depth: " << adjust_depth << ", auto_depth" << auto_depth << ", adjustment: " << adjustment << ", smooth: " << smooth << flush ;
@@ -1711,9 +1743,6 @@ MandelbrotImage::color_t * MandelbrotImage::allocGradientEdgePairColorScheme(int
1711
1743
1712
1744
// Mimic these two edges to form the other four.
1713
1745
completeRGBShiftedColorScheme (color_scheme , colors_per_part );
1714
- //-for (int j = 0; j < size; j++) {
1715
- //- color_scheme[j].component[2] = (j % 4) * 64 + 32;
1716
- //-}
1717
1746
1718
1747
return color_scheme ;
1719
1748
}
@@ -1857,17 +1886,22 @@ void HostMandelbrotApp::get_image(int sock) {
1857
1886
#endif
1858
1887
dynamic_array array_struct ;
1859
1888
1860
- array_struct = handle_write_data (sock );
1861
- bool fpga_req = true;
1862
- if (array_struct .data [6 ] < 0 ) {
1863
- // Depth argument is negative. This is our indication that we must render in C++. TODO: Ick!
1864
- array_struct .data [6 ] = - array_struct .data [6 ];
1865
- fpga_req = false;
1866
- }
1867
- // Or, newer, only slightly less icky flag
1868
- if ((array_struct .data_size >= 16 ) && (((int )(array_struct .data [16 ])) & (1 << 1 ))) {
1869
- fpga_req = false;
1870
- }
1889
+ json json_obj = read_json (sock );
1890
+ //cout << "C++ read JSON: " << json_obj << endl;
1891
+
1892
+ // TODO: Eliminate array_struct.
1893
+
1894
+ array_struct .data_size = 7 ; // TODO
1895
+ array_struct .data = (double * ) malloc (CHUNK_SIZE * 100 /* TODO */ );
1896
+ array_struct .data [0 ] = json_obj ["x" ];
1897
+ array_struct .data [1 ] = json_obj ["y" ];
1898
+ array_struct .data [2 ] = json_obj ["pix_x" ];
1899
+ array_struct .data [3 ] = json_obj ["pix_y" ];
1900
+ array_struct .data [4 ] = json_obj ["width" ];
1901
+ array_struct .data [5 ] = json_obj ["height" ];
1902
+ array_struct .data [6 ] = json_obj ["max_depth" ];
1903
+
1904
+
1871
1905
#ifdef OPENCL
1872
1906
if (fpga_req ) {
1873
1907
// Don't go bigger than allocated sizes.
@@ -1879,7 +1913,7 @@ void HostMandelbrotApp::get_image(int sock) {
1879
1913
}
1880
1914
}
1881
1915
#endif
1882
- MandelbrotImage * mb_img_p = newMandelbrotImage (array_struct . data , fpga_req );
1916
+ MandelbrotImage * mb_img_p = newMandelbrotImage (json_obj );
1883
1917
1884
1918
// Free memory for array_struct.
1885
1919
free (array_struct .data );
@@ -1934,6 +1968,8 @@ void HostMandelbrotApp::get_image(int sock) {
1934
1968
unsigned char * png ;
1935
1969
png = mb_img_p -> generatePNG (& png_size );
1936
1970
1971
+ //cout << "C++ Image Generated" << endl;
1972
+
1937
1973
// Call the utility function to send data over the socket
1938
1974
handle_read_data (sock , png , (int )png_size );
1939
1975
delete mb_img_p ;
0 commit comments