i4_image_class *im; float *z_buffer; i4_transform_class t; int iw,ih; i4_3d_vector light; int mouse_x, mouse_y; float theta; float get_z(int x, int y) { return z_buffer[x+y*iw]; } void set_z(int x, int y, float z) { z_buffer[ x + y*iw ]=z; } void clear_z() { for (int i=0; iwidth()-1, im->height()-1); i4_3d_vector circles[3]={i4_3d_vector(0,0,0), i4_3d_vector(0.5,1,0), i4_3d_vector(-2,-2,4)}; im->clear(0x4f0000, context); clear_z(); float sx=width()/2, sy=height()/2; float cx=sx,cy=sy; for (int j=0; j<3; j++) { for (int i=0; i<50000; i++) { float x=frand(), y=frand(); float z=frand(); i4_3d_vector p(x,y,z); p.normalize(); float c1=-p.dot(light); i4_3d_vector reflect=i4_3d_vector(light.x + 2*p.x*c1, light.y + 2*p.y*c1, light.z + 2*p.z*c1); float light_v=-light.dot(p)*0.7; i4_3d_vector pixel_pos(circles[j].x+p.x,circles[j].y+p.y, circles[j].z+p.z); i4_3d_vector t_p; t.transform(pixel_pos, t_p); i4_3d_vector view_dir=t_p; view_dir.normalize(); float view_dot_r=-view_dir.dot(reflect); if (view_dot_r>=0) { light_v += pow(view_dot_r, 0.4)*0.2; } if (light_v<0) light_v=0; if (light_v>1) light_v=1; float ooz=1.0/t_p.z; float px=t_p.x * ooz * sx; float py=t_p.y * ooz * sy; int ix=(int)(px+cx), iy=(int)(py+cy); if (ix>=0 && iy>=0 && ixput_pixel(ix, iy, (int)(light_v*255.0)); set_z(ix,iy, t_p.z); } } } } } void calc_transform() { t.identity(); t.mult_translate(0,0,8); t.mult_rotate_x(theta); t.mult_rotate_y(theta); } char *name() { return "trace_view"; } trace_view(int w, int h) : i4_window_class(w,h) { theta=0; i4_pixel_format fmt; fmt.default_format(); fmt.alpha_mask=0; fmt.calc_shift(); iw=w; ih=h; z_buffer=(float *)i4_malloc(w*h*sizeof(float), ""); im=i4_create_image(w,h, i4_pal_man.register_pal(&fmt)); calc_transform(); light=i4_3d_vector(0,0,1); render(); } i4_bool project_point(i4_3d_vector v, i4_3d_vector &t_v) { t.transform(v, t_v); if (t_v.z>0) { float ooz=1.0/t_v.z; t_v.x=t_v.x * ooz * width()/2.0 + width()/2.0; t_v.y=t_v.y * ooz * height()/2.0 + height()/2.0; return i4_T; } return i4_F; } void draw_3d_line(i4_3d_vector p1, i4_3d_vector p2, w32 color, i4_draw_context_class &context) { i4_3d_vector t_p1, t_p2; if (project_point(p1, t_p1) && project_point(p2, t_p2)) local_image->line((int)t_p1.x, (int)t_p1.y, (int)t_p2.x, (int)t_p2.y, color, context); } void receive_event(i4_event *ev) { if (ev->type()==i4_event::MOUSE_BUTTON_DOWN) { CAST_PTR(bev, i4_mouse_button_event_class, ev); float fw=width(), fh=height(); light=i4_3d_vector((bev->x-fw/2)/(fw/2), (bev->y-fh/2)/(fh/2), 1); light.normalize(); render(); request_redraw(); mouse_x=bev->x; mouse_y=bev->y; } else if (ev->type()==i4_event::KEY_PRESS) { theta+=0.2; calc_transform(); render(); request_redraw(); } i4_window_class::receive_event(ev); } void draw(i4_draw_context_class &context) { im->put_image(local_image, 0,0, context); i4_float mx=(mouse_x - width()/2); i4_float my=(mouse_y - height()/2); i4_3d_vector c_pos, c_dir; t.inverse_transform(i4_3d_vector(0,0,0),c_pos); t.inverse_transform(i4_3d_vector(mx,my, width()),c_dir); c_dir -= c_pos; draw_3d_line(i4_3d_vector(-1,0,0), i4_3d_vector(1,0,0), 0x00ff00, context); draw_3d_line(i4_3d_vector(0,-1,0), i4_3d_vector(0,1,0), 0x00ff00, context); draw_3d_line(i4_3d_vector(0,0,-1), i4_3d_vector(0,0,1), 0x00ff00, context); draw_3d_line(i4_3d_vector(c_pos.x + mx, c_pos.y + my, c_pos.z), i4_3d_vector(0,0,0), 0xffffff, context); }