#include <gp/coord.h>
#include <gp/colors.h>
#include "frame_buffer.h"
class Our_3D {
public:
Our_3D(pFrame_Buffer& fbp)
:frame_buffer(fbp)
{
vtx_colors = nullptr;
vtx_coors = nullptr;
};
Our_3D& transform_eye_from_object_set(const pMatrix& m)
{
eye_from_object = m;
return *this;
}
Our_3D& transform_clip_from_eye_set(const pMatrix& m)
{
clip_from_eye = m;
return *this;
}
Our_3D& light_location_set(const pCoor c)
{
light_location = c;
return *this;
}
Our_3D& light_color_set(const pColor c)
{
light_color = c;
return *this;
}
Our_3D& vtx_coors_set(vector<pCoor>& c)
{
vtx_coors = &c;
return *this;
}
Our_3D& vtx_colors_set(vector<pColor>& c)
{
vtx_colors = &c;
return *this;
}
Our_3D& draw_rasterization();
pFrame_Buffer& frame_buffer;
pMatrix eye_from_object, clip_from_eye;
pCoor light_location;
pColor light_color;
vector<pCoor> *vtx_coors;
vector<pColor> *vtx_colors;
bool opt_tryout1, opt_tryout2;
};
class World : public World_Base {
public:
World(pFrame_Buffer& fb):World_Base(fb),gc(fb){}
Our_3D gc;
virtual void render(bool first_time)
{
if ( first_time ) init_scene();
render_scene();
}
void init_scene();
void render_scene();
pCoor eye_location, light_location;
pCoor *adj_location;
pVect eye_direction;
bool opt_tryout1,opt_tryout2;
};
void
World::init_scene()
{
eye_location = pCoor(-1.2,.5,10.2);
light_location = pCoor(-2.2,1.5,10.2);
eye_direction = pVect(.1,0,-1);
adj_location = &eye_location;
opt_tryout1 = opt_tryout2 = false;
gc.opt_tryout1 = opt_tryout1;
gc.opt_tryout2 = opt_tryout2;
}
void
World::render_scene()
{
pFrame_Buffer& frame_buffer = gc.frame_buffer;
switch ( frame_buffer.keyboard_key ) {
case FB_KEY_LEFT: adj_location->x -= 0.1; break;
case FB_KEY_RIGHT: adj_location->x += 0.1; break;
case FB_KEY_PAGE_UP: adj_location->y += 0.1; break;
case FB_KEY_PAGE_DOWN: adj_location->y -= 0.1; break;
case FB_KEY_UP: adj_location->z -= 0.1; break;
case FB_KEY_DOWN: adj_location->z += 0.1; break;
case 'e': case 'E': adj_location = &eye_location; break;
case 'l': case 'L': adj_location = &light_location; break;
case 'y': gc.opt_tryout1 = opt_tryout1 = !opt_tryout1; break;
case 'Y': gc.opt_tryout2 = opt_tryout2 = !opt_tryout2; break;
}
frame_buffer.fbprintf
("Tryout1 %s ('y') Tryout2 %s ('Y') \n",
opt_tryout1 ? "ON " : "OFF", opt_tryout2 ? "ON " : "OFF");
gc.light_location_set( light_location ).light_color_set( color_white * 100 );
const uint win_width = frame_buffer.width_get();
const uint win_height = frame_buffer.height_get();
const float aspect = 1.0 * win_width / win_height;
const float width_m = 1.6; const float height_m = width_m / aspect;
pMatrix_Translate center_eye(-eye_location);
pMatrix_Rotation rotate_eye(eye_direction,pVect(0,0,-1));
pMatrix eye_from_object = rotate_eye * center_eye;
gc.transform_eye_from_object_set(eye_from_object);
pMatrix_Frustum clip_from_eye
( -width_m/2, width_m/2, -height_m/2, height_m/2, 1, 5000 );
gc.transform_clip_from_eye_set(clip_from_eye);
vector<pCoor> coors_os;
vector<pColor> colors;
coors_os << pCoor( 0, 0, 0 ) << pCoor( 9, 6, -9 ) << pCoor( 0, 7, -5 );
colors << color_white << color_white << color_white;
coors_os << pCoor(7,4,-2) << pCoor(-3,5,-9) << pCoor(9,2,-2);
colors << color_blue << color_blue << color_blue;
colors << color_lsu_spirit_gold << color_lsu_spirit_gold
<< color_lsu_spirit_gold;
colors << color_lsu_spirit_purple << color_lsu_spirit_purple
<< color_lsu_spirit_purple;
coors_os << pCoor(-7,0,-2) << pCoor(-7,2,-2) << pCoor(-5,0,-2);
coors_os << pCoor(-7,2,-2) << pCoor(-5,2,-2) << pCoor(-5,0,-2);
int n_segs = 20;
pCoor center(1,-1,-3);
pVect sz( 0, 0.5, 0.05 );
pNorm ax( 0, -sz.z, sz.y ), ay = cross(sz,ax);
vector<pCoor> strip_coor(n_segs+1);
float r = 4, d_th = 2 * M_PI / n_segs;
for ( int i=0; i<=n_segs; i++ )
strip_coor[i] = center + r*ax * cosf(i*d_th) + r*ay * sinf(i*d_th);
for ( int i=0; i<n_segs; i++ )
{
coors_os << strip_coor[i] << strip_coor[i+1] << strip_coor[i] + sz;
coors_os << strip_coor[i] + sz << strip_coor[i+1] + sz << strip_coor[i+1];
if ( i == 0 )
colors << color_red << color_green << color_blue
<< color_green << color_green << color_green;
else
colors << pColor(0xff00ff) << pColor(0xffff00) << pColor(0xffff)
<< pColor(0xffff) << pColor(0xffff) << pColor(0xffff);
}
gc.vtx_coors_set(coors_os);
gc.vtx_colors_set(colors);
gc.draw_rasterization();
}
Our_3D&
Our_3D::draw_rasterization()
{
const uint win_width = frame_buffer.width_get();
const uint win_height = frame_buffer.height_get();
pMatrix_Translate recenter(pVect(1,1,0));
pMatrix_Scale scale( win_width/2, win_height/2, 1 );
pMatrix window_from_clip = scale * recenter;
pMatrix ws_from_os = window_from_clip * clip_from_eye * eye_from_object;
float* const zbuffer = frame_buffer.buffer_depth_get();
auto& coors_os = *vtx_coors;
auto& colors = *vtx_colors;
for ( size_t i=0; i+2<coors_os.size(); i += 3 )
{
pCoor o0 = coors_os[i+0], o1 = coors_os[i+1], o2 = coors_os[i+2];
pCoor_Homogenized
w0( ws_from_os * o0 ),
w1( ws_from_os * o1 ), w2( ws_from_os * o2 );
pColor c0 = colors[i+0], c1 = colors[i+1], c2 = colors[i+2];
pNorm tn = cross(o0,o1,o2);
pVect v20(w2,w0), v21(w2,w1);
const float db0 = 1/max(fabs(v20.x),fabs(v20.y));
const float db1 = 1/max(fabs(v21.x),fabs(v21.y));
const float w0ow2z = w0.z / w2.z, w1ow2z = w1.z / w2.z;
for ( float b0=0; b0<=1; b0 += db0 )
for ( float b1=0; b1<=1-b0; b1 += db1 )
{
const float b2 = 1 - b0 - b1;
pCoor wf = b0*w0 + b1*w1 + b2*w2;
if ( uint(wf.x) >= win_width || uint(wf.y) >= win_height ) continue;
const size_t idx = wf.x + int(wf.y) * win_width;
float zinv = wf.z;
if ( zinv < 0 || zinv > 1 ) continue;
if ( zbuffer[ idx ] < zinv ) continue;
zbuffer[ idx ] = zinv;
float bc0 = b0 ? 1/( w0ow2z * (1-b0)/b0 + 1 ) : 0;
float bc1 = b1 ? 1/( w1ow2z * (1-b1)/b1 + 1 ) : 0;
float bc2 = 1 - bc0 - bc1;
pColor color = bc0*c0 + bc1*c1 + bc2*c2;
pCoor of = bc0*o0 + bc1*o1 + bc2*o2;
pNorm f_to_l(of,light_location);
float phase = fabs(dot(tn,f_to_l));
pColor lighted_color = phase / f_to_l.mag_sq * light_color * color;
frame_buffer[ idx ] = lighted_color.int_rgb();
}
}
return *this;
}
int
main(int argc, char **argv)
{
pFrame_Buffer demo_frame_buffer(argc,argv);
WRender render( demo_frame_buffer );
World our_world( demo_frame_buffer );
WRENDER_INSERT(render, our_world);
render.run();
return 0;
}