#include <gp/coord.h>
#include "frame_buffer.h"
#include "hw01-misc.h"
struct HW01_Data {
HW01_Data():inited(false){};
bool inited;
bool tryout0, tryout1;
vector<uint32_t> fb_area_dup;
iVect mag_from_diag;
iVect mag_to_of; iVect mag_to_diag;
};
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;
}
}
}
void
parallel_lines_draw
( pFrame_Buffer& fb, iCoor p0, iCoor pb, iVect v, uint32_t co)
{
line_draw( fb, p0, p0 + v, co );
line_draw( fb, pb, pb + v, co );
}
void
parallelogram_draw
( pFrame_Buffer& fb, iCoor p00, iVect vx, iVect vy, uint32_t color )
{
parallel_lines_draw(fb, p00, p00+vy, vx, color);
parallel_lines_draw(fb, p00, p00+vx, vy, color);
}
void
aa_rectangle_draw
( pFrame_Buffer& fb, iCoor p00, int wd, int ht, uint32_t color )
{
const int win_width [[maybe_unused]] = fb.width_get();
const int win_height [[maybe_unused]] = fb.height_get();
iCoor p11 = p00 + iVect(wd,ht);
assert( wd >= 0 && ht >= 0 );
if ( p00.x >= win_width || p00.y >= win_height ) return;
if ( p11.x <= 0 || p11.y <= 0 ) return;
iCoor p00c( max( 0, p00.x ), max( 0, p00.y ) );
iCoor p11c( min( win_width-1, p11.x ), min( win_height-1, p11.y ) );
iCoor p01c( p00c.x, p11c.y ), p10c( p11c.x, p00c.y );
if ( p00.x == p00c.x ) line_draw( fb, p00c, p01c, color );
if ( p11.x == p11c.x ) line_draw( fb, p10c, p11c, color );
if ( p00.y == p00c.y ) line_draw( fb, p00c, p10c, color );
if ( p11.y == p11c.y ) line_draw( fb, p01c, p11c, color );
}
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_y0 = win_height - 150;
const int sq_x1 = sq_x0 + sq_slen, sq_y1 = sq_y0 - sq_slen;
const uint32_t color_red = 0xff0000;
const uint32_t color_blue = 0xff;
const uint32_t color_green = 0xff00;
int num_waves = 4;
float plot_ht = sq_slen/float(num_waves);
for ( float
yb = sq_y0 - plot_ht/2, freq = 4 * M_PI / ( win_width - 40 - sq_x1 );
yb > sq_y1;
yb -= plot_ht, freq *= 2 )
for ( int x = 20; x < win_width - 20; x++ )
{
int y = yb + sin( x * freq ) * plot_ht * .45;
fb[ y * win_width + x ] = 0xff00;
}
int n_rects = 24;
int n_pts = n_rects * 3;
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 * M_PI / n_pts;
vector<pVect> vecs;
for ( int i=0; i<n_pts; i++ )
vecs.push_back( pVect( cosf(i*delta_theta), sinf(i*delta_theta), 0 ) );
for ( int i=0; i<n_pts; i+=3 )
{
pVect v1 = vecs[i+1] * ( c_r2 - c_r1 );
pVect v2 = c_r1 * ( vecs[i+2] - vecs[i] );
pCoor p1 = c_ctr + c_r1 * vecs[i];
parallelogram_draw(fb, p1, v1, v2, 0xffffff );
}
fb.fb_stats_off();
const iCoor mouse(fb.mouse_x,fb.mouse_y);
const iVect& mag_from_diag = hw01_data.mag_from_diag;
iVect& mag_to_of = hw01_data.mag_to_of;
iVect& mag_to_diag = hw01_data.mag_to_diag;
const int mag_to_wd = mag_to_diag.x;
const int mag_to_ht = mag_to_diag.y;
const iCoor mag_from_ll = mouse - mag_from_diag / 2;
const int mag_from_wd [[maybe_unused ]] = mag_from_diag.x;
const int mag_from_ht [[maybe_unused]] = mag_from_diag.y;
const iCoor mag_to_ll = mag_from_ll + mag_to_of;
const bool show_starter_code = hw01_data.tryout0;
if ( show_starter_code )
{
for ( int x=0; x<mag_from_wd; x++ )
fb[ mag_from_ll.x + x + ( mag_from_ll.y + x ) * win_width ]
= color_blue;
for ( int x=0; x<min(mag_to_wd,mag_to_ht); x++ )
fb[ mag_to_ll.x + x + ( mag_to_ht + mag_to_ll.y - x ) * win_width ]
= color_green;
for ( int x=0; x<mag_from_wd; x++ )
hw01_data.fb_area_dup[ x + x * mag_from_wd ]
= color_red;
}
for ( int x=0; x<mag_from_wd; x++ )
for ( int y=0; y<mag_from_ht; y++ )
{
iCoor from = mag_from_ll + iVect(x,y);
bool in_win = from.x >= 0 && from.x < win_width
&& from.y >= 0 && from.y < win_height;
hw01_data.fb_area_dup[ x + y * mag_from_wd ] =
in_win ? fb[ from.x + from.y * win_width ] : 0;
}
aa_rectangle_draw
( fb, mag_from_ll, mag_from_diag.x, mag_from_diag.y, color_blue );
const float zoom_x = float(mag_to_wd)/mag_from_wd;
const float zoom_y = float(mag_to_ht)/mag_from_ht;
for ( int x=0; x<mag_from_wd; x++ )
for ( int y=0; y<mag_from_ht; y++ )
{
uint32_t pixel = hw01_data.fb_area_dup[x + y * mag_from_wd];
int xt0 = max( 0, mag_to_ll.x + int(x * zoom_x) );
int xt1 = min( win_width, mag_to_ll.x + int((x+1) * zoom_x) );
int yt0 = max( 0, mag_to_ll.y + int(y * zoom_y) );
int yt1 = min( win_height, mag_to_ll.y + int((y+1) * zoom_y) );
for ( int xt = xt0; xt < xt1; xt++ )
for ( int yt = yt0; yt < yt1; yt++ )
fb[ xt + yt * win_width ] = pixel;
}
aa_rectangle_draw
( fb, mag_to_ll, mag_to_diag.x, mag_to_diag.y, color_green );
}
void
kbd_input_handle(pFrame_Buffer& fb, HW01_Data& hw01_data)
{
iVect& mag_to_of = hw01_data.mag_to_of;
iVect& mag_to_diag = hw01_data.mag_to_diag;
if ( !hw01_data.inited )
{
hw01_data.inited = true;
hw01_data.tryout0 = false;
hw01_data.tryout1 = false;
hw01_data.mag_from_diag = { 100, 100 };
const int mag_from_wd = hw01_data.mag_from_diag.x;
const int mag_from_ht = hw01_data.mag_from_diag.y;
hw01_data.fb_area_dup.resize( mag_from_wd * mag_from_ht );
mag_to_diag = iVect( mag_from_wd * 2.5, mag_from_ht * 2.5 );
mag_to_of = iVect( mag_from_wd*.3, mag_from_ht*.7 );
}
const int kbd_inc = 2;
switch ( fb.keyboard_key ) {
case FB_KEY_RIGHT: case FB_KEY_LEFT:
{
const int inc = fb.keyboard_key == FB_KEY_LEFT ? -kbd_inc : kbd_inc;
if ( fb.keyboard_shift ) mag_to_of.x += 2*inc;
else { mag_to_diag.x += 2*inc; mag_to_of.x -= inc; }
break;
}
case FB_KEY_UP: case FB_KEY_DOWN:
{
const int inc = fb.keyboard_key == FB_KEY_DOWN ? -kbd_inc : kbd_inc;
if ( fb.keyboard_shift ) mag_to_of.y += 2*inc;
else { mag_to_diag.y += 2*inc; mag_to_of.y -= inc; }
break;
}
case 'y':
hw01_data.tryout0 = !hw01_data.tryout0; break;
case 'Y':
hw01_data.tryout1 = !hw01_data.tryout1; break;
default:
break;
};
}
int
main(int argc, char **argv)
{
pFrame_Buffer demo_frame_buffer(argc,argv);
HW01_Data hw01_data;
demo_frame_buffer.show
( [&](pFrame_Buffer& fb){ render_hw01(fb,hw01_data); } );
return 0;
}