#include <gp/coord.h>
#include <numbers>
#include "frame_buffer.h"
#include "hw01-misc.h"
struct HW01_Data {
HW01_Data():inited(false){};
bool inited;
bool tryout0, tryout1;
int zoom;
double t_frame_last, t_sim;
bool paused;
};
HW01_Data hw01_data;
void
line_draw
( pFrame_Buffer& fb, iCoor p0, iCoor p1, uint32_t co)
{
int x0 = p0.x, y0 = p0.y;
int x1 = p1.x, y1 = p1.y;
const iVect delta = p1 - p0;
const int width = fb.width_get();
if ( abs( delta.x ) < abs( delta.y ) )
{
if ( y0 > y1 ) { swap(x0,x1); swap(y0,y1); }
float dxdy = float(delta.x) / delta.y;
float x = x0;
for ( int yi = y0; yi < y1; yi++ )
{
fb[ yi * width + x ] = co;
x += dxdy;
}
}
else
{
if ( x0 > x1 ) { swap(x0,x1); swap(y0,y1); }
float dydx = float(delta.y) / delta.x;
float y = y0;
for ( int xi = x0; xi < x1; xi++ )
{
fb[ int(y) * width + xi ] = co;
y += dydx;
}
}
}
template< typename F > void
func_plot
( pFrame_Buffer& fb,
iCoor plot_lower_left, int plot_width, int plot_height,
float func_x0, float func_x1, F func )
{
const int win_width [[maybe_unused]] = fb.width_get();
const int win_height [[maybe_unused]] = fb.height_get();
assert( plot_width > 0 && plot_height > 0 );
const uint32_t color_red [[maybe_unused]] = 0xff0000;
const uint32_t color_deep_sky_blue(0x00bfff);
const uint32_t color_plot [[maybe_unused]] = 0xffff00; const uint32_t color_box = color_deep_sky_blue;
const uint32_t color_background [[maybe_unused]] = 0x333333;
iCoor p0 = plot_lower_left; iVect vx( plot_width, 0 ), vy( 0, plot_height );
iCoor p1 = p0 + vx + vy;
line_draw( fb, p0, p0 + vy, color_box );
line_draw( fb, p0, p0 + vx, color_box );
line_draw( fb, p0 + vy, p1, color_box );
line_draw( fb, p0 + vx, p1, color_box );
float func_y0 [[maybe_unused]] = func(func_x0);
float func_y1 [[maybe_unused]] = func(func_x1);
for ( int i=p0.x+1; i<p1.x; i++ )
for ( int j=p0.y+1; j<p1.y; j++ )
fb[ i + j * win_width ] = color_background;
float dfx = ( func_x1 - func_x0 ) / plot_width;
float min_y = func(func_x0);
float max_y = min_y;
for ( int i=0; i<plot_width; i++ )
{
float x = func_x0 + dfx * i;
float y = func(x);
if ( y < min_y ) min_y = y;
if ( y > max_y ) max_y = y;
}
float delta_y_tight = max_y - min_y;
float margin = delta_y_tight * 0.05;
float delta_y = delta_y_tight + 2 * margin;
max_y += margin;
min_y -= margin;
float scale = plot_height / delta_y;
for ( int i=0; i<plot_width; i++ )
{
float x = func_x0 + dfx * i;
float y = func(x);
float y_next = func(x+dfx);
int ix = p0.x + i;
int iy0 = p0.y + ( y - min_y ) * scale;
int iy1 = p0.y + ( y_next - min_y ) * scale;
int iylo = min(iy0,iy1);
int iyhi = max(iy0,iy1);
for ( int iy = iylo; iy <= iyhi; iy++ )
fb[ ix + iy * win_width ] = color_plot;
}
}
void kbd_input_handle(pFrame_Buffer& fb, HW01_Data& hw01_data);
void
render_hw01(pFrame_Buffer& fb, HW01_Data& hw01_data)
{
const int win_width = fb.width_get();
const int win_height = fb.height_get();
kbd_input_handle(fb,hw01_data);
const int sq_slen = min(win_width,win_height) * .45;
const int sq_x0 = sq_slen * 0.1, sq_y1 = win_height - 75;
const int sq_x1 = sq_x0 + sq_slen, sq_y0 = sq_y1 - sq_slen;
const uint32_t color_red [[maybe_unused]] = 0xff0000;
const uint32_t color_blue [[maybe_unused]] = 0xff;
const uint32_t color_green [[maybe_unused]] = 0xff00;
int num_waves = 4;
float sine_ht = sq_slen/float(num_waves);
for ( float
yb = sq_y1 - sine_ht/2, freq = 4 * M_PI / ( win_width - 40 - sq_x1 );
yb > sq_y0;
yb -= sine_ht, freq *= 2 )
for ( int x = sq_x1 + 20; x < win_width - 20; x++ )
{
int y = yb + sin( x * freq ) * sine_ht * .45;
fb[ y * win_width + x ] = 0xff00;
}
int n_pts = 12 * 4;
float c_r1 = sq_slen/6; float c_r2 = sq_slen/2; pCoor c_ctr( c_r2 + 20, c_r2 + 20 ); float delta_theta = 2 * numbers::pi / n_pts;
for ( int i=0; i<n_pts; i++ )
{
pVect v( cosf(i*delta_theta), sinf(i*delta_theta), 0 );
pCoor p1 = c_ctr + c_r1 * v;
pCoor p2 = c_ctr + c_r2 * v;
line_draw(fb, p1, p2, 0xffffff );
}
fb.fb_stats_off();
const bool simple_demo = false;
if ( simple_demo )
{
iCoor plot_ll( 20, 20 );
float p_wd = 400, p_ht = 200;
float fx0 = -2 * numbers::pi, fx1 = numbers::pi * 7;
func_plot( fb, plot_ll, p_wd, p_ht, fx0, fx1, sinf );
}
float alphap = 0.5, alphan = 1;
auto xIELU = [&](float x)
{ return x > 0 ? alphap * x * x + 0.5 * x
: alphan * ( exp(x) - 1 ) - alphan * x + 0.5*x; };
float s0 = 0.7;
iCoor p00(c_ctr.x - sq_slen*s0*0.5, c_ctr.y-sq_slen*s0*0.5);
func_plot( fb, p00, sq_slen*s0, sq_slen*s0, -3, 3, xIELU);
float f_carrier = 17;
float f_modmod = 1;
float t_sim = hw01_data.t_sim;
float f_mod = 2 + sinf(t_sim*f_modmod);
auto fm = [&](float t) { return sinf( 4*sinf(t*f_mod) + t*f_carrier ); };
auto am = [&](float t) { return (1.2 + sinf(t*f_mod) ) * sinf(t*f_carrier); };
float plot_width = sq_slen * 0.7;
int plot_gap = sq_slen / 8;
int plot_stride = plot_width + plot_gap;
int plot1_ht = sq_slen * .4;
int plot1_y1 = sq_y1 - ( sq_slen - plot1_ht ) / 2;
int plot1_y0 = plot1_y1 - plot1_ht;
float fx0 = hw01_data.t_sim * 0.1 - 10;
float fxwid = numbers::pi;
int plot2_ht = sq_slen * 0.75;
int plot2_y0 = c_ctr.y - plot2_ht / 2;
for ( int x0 = sq_x1 + plot_gap; x0 + plot_stride < win_width;
x0 += plot_stride )
{
iCoor p10(x0,plot1_y0);
iCoor p20(x0,plot2_y0);
func_plot( fb, p10, plot_width, plot1_ht, fx0, fx0+fxwid, fm );
func_plot( fb, p20, plot_width, plot2_ht, fx0, fx0+fxwid, am );
fxwid *= 2;
}
fb.fb_stats_off();
const int zoom = hw01_data.zoom;
const int x_mid = ( sq_x0 + sq_x1 ) / 2;
const int y_mid = ( sq_y0 + sq_y1 ) / 2;
const int src_hwid = sq_slen / ( zoom * 2 );
const int mouse_x = fb.mouse_x;
const int mouse_y = fb.mouse_y;
for ( int y = -src_hwid; y < src_hwid; y++ )
for ( int x = -src_hwid; x < src_hwid; x++ )
{
uint32_t pixel = fb[ mouse_x + x + ( mouse_y + y ) * win_width ];
int fb_idx = x_mid + x * zoom + ( y_mid + y * zoom ) * win_width;
for ( int yy = 0; yy < zoom; yy++ )
for ( int xx = 0; xx < zoom; xx++ )
fb[ fb_idx + xx + yy * win_width ] = pixel;
}
const iCoor mouse_p(fb.mouse_x,fb.mouse_y);
const int src_wid = src_hwid * 2;
iVect src_dx(src_wid,0), src_dy(0,src_wid);
iCoor src_ll = mouse_p - iVect(src_hwid,src_hwid); iCoor src_ur = mouse_p + iVect(src_hwid,src_hwid);
uint32_t color_src_box = 0x8888ff; uint32_t color_dst_box = 0x8888ff;
line_draw( fb, src_ll, src_ll + src_dx, color_src_box );
line_draw( fb, src_ll, src_ll + src_dy, color_src_box );
line_draw( fb, src_ur, src_ur - src_dx, color_src_box );
line_draw( fb, src_ur, src_ur - src_dy, color_src_box );
iCoor dst_ll( sq_x0, sq_y0 ), dst_ur( sq_x1, sq_y1 );
iVect dst_dx( sq_slen, 0 ), dst_dy( 0, sq_slen );
line_draw( fb, dst_ll, dst_ll + dst_dx, color_dst_box );
line_draw( fb, dst_ll, dst_ll + dst_dy, color_dst_box );
line_draw( fb, dst_ur, dst_ur - dst_dx, color_dst_box );
line_draw( fb, dst_ur, dst_ur - dst_dy, color_dst_box );
}
void
kbd_input_handle(pFrame_Buffer& fb, HW01_Data& hw01_data)
{
if ( !hw01_data.inited )
{
hw01_data.inited = true;
hw01_data.tryout0 = false;
hw01_data.tryout1 = false;
hw01_data.zoom = 4;
hw01_data.t_frame_last = time_wall_fp();
hw01_data.t_sim = 0;
hw01_data.paused = false;
}
switch ( fb.keyboard_key ) {
#if 0
case FB_KEY_RIGHT: case FB_KEY_LEFT:
{
const int inc = fb.keyboard_key == FB_KEY_LEFT ? -kbd_inc : kbd_inc;
break;
}
case FB_KEY_UP: case FB_KEY_DOWN:
{
const int inc = fb.keyboard_key == FB_KEY_DOWN ? -kbd_inc : kbd_inc;
break;
}
#endif
case 'p': case 'P': hw01_data.paused = !hw01_data.paused; break;
case 'y':
hw01_data.tryout0 = !hw01_data.tryout0; break;
case 'Y':
hw01_data.tryout1 = !hw01_data.tryout1; break;
case 'u': case 'U': if ( hw01_data.zoom > 1 ) hw01_data.zoom--; break;
case 'z': case 'Z': hw01_data.zoom++; break;
default:
break;
};
const double t_now = time_wall_fp();
if ( ! hw01_data.paused )
hw01_data.t_sim += t_now - hw01_data.t_frame_last;
hw01_data.t_frame_last = t_now;
fb.fbprintf("Tryout 0,1: %s,%s ('y','Y') %s ('p') "
"Zoom: %d ('u','z') \n",
hw01_data.tryout0 ? "TRUE " : "FALSE",
hw01_data.tryout1 ? "TRUE " : "FALSE",
hw01_data.paused ? "PAUSED " : "RUNNING",
hw01_data.zoom);
}
int
main(int argc, char **argv)
{
pFrame_Buffer demo_frame_buffer(argc,argv);
demo_frame_buffer.show
( [&](pFrame_Buffer& fb){ render_hw01(fb,hw01_data); } );
return 0;
}