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;imax[0]) max[0]=*to;                /* determining polygon's extend */ 
  if(*tomax[1]) max[1]=*to; 
  if(*tomax[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;im_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(*tomax[1]) max[1]=*to; 
  if(*tomax[2]) max[2]=*to; 
  if(*tonmaxx) nmaxx=*tmp;               /* determining gate extend */ 
   if(*tmpnmaxy) nmaxy=*tmp;               /* Y */ 
   if(*tmp