www.pudn.com > LightTrack.rar > EngBase.cpp
/** 3DGPL *************************************************\ * () * * Functions for the base of polygonal 3D engine. * * * * Ifdefs: * * _CI_ Colour/Intensity model; * * _RGB_ RGB model; * * _Z_BUFFER_ Depth array; * * _PAINTER_ Back to front order. * * * * Defines: * * M_init_rendering Set type of rendering; * * M_shade_vertex Shading a single vertex; * * M_sort_elements Polygons in _PAINTER_; * * * * M_shade_polygon Shading using normals; * * M_render_polygon Rendering in perspective; * * * * M_set_gate Set gate's clipping bounds. * * * * Internals: * * MI_construct_tuples Gets X Y Z R G B Tx Ty; * * MI_tmapping_vectors Computes U V for tmapping. * * * * (c) 1995-98 Sergei Savchenko, (savs@cs.mcgill.ca) * \**********************************************************/ //EngBase.cpp #include "Graphics.h" /* 2-D rendering */ #include "Trans.h" /* 3-D transformations */ #include "Clipper.h" /* 2-D/3-D clipping */ #include "Engine.h" /* 3-D engine */ #include/* NULL */ #include /* INT_MIN and INT_MAX */ int M_force_linear_tmapping=0; /* when the polygons are small */ int M_rendering_type; /* types that can be rendered */ unsigned char M_camera_gam; /* needed for surfaces */ int M_camera_x,M_camera_y,M_camera_z; int M_camera_log_focus; /* camera parameters */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * INTERNAL: Constructing polygon list. * * --------- * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void CI_construct_tuples(int *from,register int *to, int *vertices,int *colours, int *textures, int dimension,int length,int *min,int *max ) { register int i,index; HW_set_int(min,3,INT_MAX); /* X Y Z */ HW_set_int(max,3,INT_MIN); /* initializing searching */ for(i=0;i max[0]) max[0]=*to; /* determining polygon's extend */ if(*to max[1]) max[1]=*to; if(*to max[2]) max[2]=*to; if(*to =M_LNG_SHADED) { if(colours==NULL) { *to++=(*(from++))< =M_LNG_SHADED) { if(colours==NULL) { *to++=(*(from++))< m_type) { case M_AMBIENT: /* uniform illumination */ { #if defined(_CI_) intensity[0]+=light->m_intensity; #endif #if defined(_RGB_) intensity[0]+=light->m_red; intensity[1]+=light->m_green; intensity[2]+=light->m_blue; #endif } break; case M_POINT: /* depends on the unit vector */ { T_unit_vector(vertex,light->m_parameter,light_vector); prd=T_scalar_product(light_vector,normal); if(prd<0) break; #if defined(_CI_) intensity[0]+=(prd*light->m_intensity)>>T_LOG_NORMAL_SIZE; #endif #if defined(_RGB_) intensity[0]+=(prd*light->m_red)>>T_LOG_NORMAL_SIZE; intensity[1]+=(prd*light->m_green)>>T_LOG_NORMAL_SIZE; intensity[2]+=(prd*light->m_blue)>>T_LOG_NORMAL_SIZE; #endif } break; case M_DIRECT: /* depends on the normal */ { prd=-T_scalar_product(light->m_parameter,normal); if(prd<0) break; #if defined(_CI_) intensity[0]+=(prd*light->m_intensity)>>T_LOG_NORMAL_SIZE; #endif #if defined(_RGB_) intensity[0]+=(prd*light->m_red)>>T_LOG_NORMAL_SIZE; intensity[1]+=(prd*light->m_green)>>T_LOG_NORMAL_SIZE; intensity[2]+=(prd*light->m_blue)>>T_LOG_NORMAL_SIZE; #endif } break; } } } /**********************************************************\ * Sorting at the same time an array of vertices and an * * array of indices. * \**********************************************************/ #if defined(_PAINTER_) void M_sort_elements(int *vertices,int dimension,int *indices,int number) { int i,j,tmp; for(i=number-1;i>0;i--) /* buble sorting indexes */ { for(j=0;jm_intensity=0; #endif #if defined(_RGB_) poly->m_red=0; poly->m_green=0; poly->m_blue=0; /* init flat intensity */ #endif vertex=poly->m_vertices; normal_idxs=poly->m_normals; for(i=0;i<=poly->m_no_edges;i++,vertex+=M_LNG_POLYGON_VERTEX,normal_idxs++) { M_shade_vertex(vertex+1,vertices+vertex[0]*T_LNG_VECTOR, normals+(*normal_idxs*T_LNG_VECTOR), no_lights,lights ); #if defined(_CI_) poly->m_intensity+=vertex[1]; #endif #if defined(_RGB_) poly->m_red+=vertex[1]; poly->m_green+=vertex[2]; poly->m_blue+=vertex[3]; /* polygon's illumination */ #endif } #if defined(_CI_) poly->m_intensity/=(poly->m_no_edges+1); #endif #if defined(_RGB_) poly->m_red/=(poly->m_no_edges+1); poly->m_green/=(poly->m_no_edges+1); /* computing intensities for */ poly->m_blue/=(poly->m_no_edges+1); /* dirty rendering options */ #endif } /**********************************************************\ * Rendering a generic polygon in perspective. * * Firstly vertex tuples are being created, they are * * of length M_LNG_WHATEVER, they are being pyramide * * clipped and Z clipped, hence tuples are being sent * * into perspective acquiring length of G_LNG_WHATEVER, * * (Z might get discarded for _PAINTER_, that's why), * * culling is being done, and then method dependent * * (AMBIENT, SHADED) rendering are being done. * * Specifically for perspective a function to get * * mapping vectors would be invoked. * \**********************************************************/ void M_render_polygon(struct M_polygon *poly, int *vertices,int *colours, int *textures ) { int original1[M_MAX_POLYGON_VERTICES*C_MAX_DIMENSIONS]; int original2[M_MAX_POLYGON_VERTICES*C_MAX_DIMENSIONS]; int perspective[M_MAX_POLYGON_VERTICES*C_MAX_DIMENSIONS]; int vector1[T_LNG_VECTOR],vector2[T_LNG_VECTOR]; int *clipped,number,cnd; int i,min[3],max[3]; /* extends X Y Z */ switch(M_rendering_type) { case M_WIRE: /* X Y Z, a wireframe */ { number=poly->m_no_edges; CI_construct_tuples((int*)poly->m_vertices,original1, vertices,colours,textures, M_LNG_FLAT,number+1,min,max ); if((cnd=C_volume_clipping(min,max))!=0) /* using extends */ { if(cnd==-1) { number=C_polygon_z_clipping(original1,clipped=original2, M_LNG_FLAT,number ); } else clipped=original1; /* source is of M_LNG_FLAT */ T_perspective(clipped,perspective,M_LNG_FLAT,number+1,M_camera_log_focus); /* result is of G_LNG_FLAT */ if(T_normal_z_negative(perspective,perspective+G_LNG_FLAT, perspective+G_LNG_FLAT*2 ) ) { for(i=0;i m_colour,poly->m_intensity ); #endif #if defined(_RGB_) G_line(perspective+i*G_LNG_FLAT,perspective+(i+1)*G_LNG_FLAT, poly->m_colour,poly->m_red,poly->m_green,poly->m_blue ); #endif } } } } break; case M_FLAT: /* X Y Z, flat shaded polygon */ { number=poly->m_no_edges; CI_construct_tuples((int*)poly->m_vertices,original1, vertices,colours,textures, M_LNG_FLAT,number+1,min,max ); if((cnd=C_volume_clipping(min,max))!=0) /* using extends */ { if(cnd==-1) { number=C_polygon_z_clipping(original1,clipped=original2, M_LNG_FLAT,number ); } else clipped=original1; /* source is of M_LNG_FLAT */ T_perspective(clipped,perspective,M_LNG_FLAT,number+1,M_camera_log_focus); /* result is of G_LNG_FLAT */ if(T_normal_z_negative(perspective,perspective+G_LNG_FLAT, perspective+G_LNG_FLAT*2 ) ) { #if defined(_CI_) G_flat_polygon(perspective,number,poly->m_colour,poly->m_intensity); #endif #if defined(_RGB_) G_flat_polygon(perspective,number,poly->m_colour,poly->m_red, poly->m_green,poly->m_blue ); #endif } } } break; case M_TEXTURED: /* X Y Z [I] or [R G B] Tx Ty */ { /* texture mapped polygon */ if(poly->m_texture!=NULL) { number=poly->m_no_edges; CI_construct_tuples((int*)poly->m_vertices,original1, vertices,colours,textures, M_LNG_TEXTURED,number+1,min,max ); if((cnd=C_volume_clipping(min,max))!=0) /* using extends */ { if(cnd==-1) number=C_polygon_z_clipping(original1,clipped=original2, M_LNG_TEXTURED,number ); else clipped=original1; /* source is of M_LNG_TEXTURED */ T_perspective(clipped,perspective,M_LNG_TEXTURED,number+1,M_camera_log_focus); /* result is of G_LNG_TEXTURED */ if(T_normal_z_negative(perspective,perspective+G_LNG_TEXTURED, perspective+G_LNG_TEXTURED*2 ) ) { if((M_force_linear_tmapping)|| (clipped[2] m_type&M_QUAD, original1, original1+M_LNG_TEXTURED, original1+M_LNG_TEXTURED*2, poly->m_log_texture_space_size, vector1,vector2 ); G_prp_textured_polygon(perspective,number,clipped, vector1,vector2, poly->m_texture->m_texture_bytes, poly->m_texture->m_log_texture_size, poly->m_log_texture_space_size ); } else /* linear mapping */ { G_lin_textured_polygon(perspective,number, poly->m_texture->m_texture_bytes, poly->m_texture->m_log_texture_size ); } } } break; /* if no texture do shaded */ } } case M_SHADED: /* X Y Z [I] or [R G B] */ { /* Gourand shaded polygons */ number=poly->m_no_edges; CI_construct_tuples((int*)poly->m_vertices,original1, vertices,colours,textures, M_LNG_SHADED,number+1,min,max ); if((cnd=C_volume_clipping(min,max))!=0) /* using extends */ { if(cnd==-1) { number=C_polygon_z_clipping(original1,clipped=original2, M_LNG_SHADED,number ); } else clipped=original1; /* source is of M_LNG_SHADED */ T_perspective(clipped,perspective,M_LNG_SHADED,number+1,M_camera_log_focus); /* result is of G_LNG_SHADED */ if(T_normal_z_negative(perspective,perspective+G_LNG_SHADED, perspective+G_LNG_SHADED*2 ) ) { G_shaded_polygon(perspective,number,poly->m_colour); } } } break; } } /**********************************************************\ * Setting clipping limits for the extend of a * * perspective projection of a gate to the screen. * * * * Firstly vertex tuples are created, they are pyramide * * clipped and Z clipped, hence tuples are sent into * * perspective, further the extends are found and the * * clipping bounds set. * * * * RETURNS: 1 on success; * * -------- 0 when clipping limits can't be set. * \**********************************************************/ int M_set_gate(struct M_gate *gate,int *vertices) { int original1[M_MAX_POLYGON_VERTICES*C_MAX_DIMENSIONS]; int original2[M_MAX_POLYGON_VERTICES*C_MAX_DIMENSIONS]; int perspective[M_MAX_POLYGON_VERTICES*C_MAX_DIMENSIONS]; int *tmp,*clipped,number,cnd; int min[3],max[3]; /* extends X Y Z */ int nminx,nminy,nmaxx,nmaxy; /* new clipping bounds */ int i,*to; number=gate->m_no_edges; HW_set_int(min,3,INT_MAX); /* X Y Z */ HW_set_int(max,3,INT_MIN); /* initializing searching */ for(to=original1,i=0;i<=number;i++) { HW_copy_int(vertices+(gate->m_vertices[i]*T_LNG_VECTOR),to,3); if(*to>max[0]) max[0]=*to; /* determining polygon's extend */ if(*to max[1]) max[1]=*to; if(*to max[2]) max[2]=*to; if(*to nmaxx) nmaxx=*tmp; /* determining gate extend */ if(*tmp nmaxy) nmaxy=*tmp; /* Y */ if(*tmp