home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / rad386 / radiosit / src / scan_con.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-21  |  14.0 KB  |  483 lines

  1. /*
  2.     Module to Scan Convert Objects on the Hemicube.
  3.     Objects include Polygon, sphere, bubble, cylinder, tube,
  4.     cone, cup and anular ring.
  5.     Objects other than Polygon are scan converted by
  6.     breaking them into rectangular parts in u,v domain.
  7.     The breakup used is user defined if specified by the
  8.     user or default break up.
  9.     Default breakup for different objects are as follows:
  10.     Sphere, Bubble : 4 x 4
  11.     Cylinder, Tube : 4 x 1
  12.     Cone, cup      : 4 x 1
  13.     Anular Ring    : 4 x 1
  14.     User may change the defaults by changing the
  15.     appropriate #define statements below.
  16.     The rectangluar parts in the u,v domain are assumed to
  17.     be planar quadrilateral. No effort is made to check 
  18.     their planarity. The normal to the quadrilateral is
  19.     computed as the actual object object normal at the 
  20.     center of the (u,v) rectangular part. This normal is
  21.     used for back-face culling.
  22.     NOTE : If the above mentioned technique is used to 
  23.     render the objects other than Polygon then terrible
  24.     cracks may appear. 
  25. ------
  26. sumant
  27. 29-July-1991
  28. */
  29. #include <stdio.h>
  30. #include <math.h>
  31.  
  32. #include "GraphicsGems.h"
  33. #include "poly.h"
  34. #include "data_structure.h"
  35. #include "objects.h"
  36. extern int hemicube_resolution;
  37. #define default_sphere_h_reso 4
  38. #define default_sphere_v_reso 4
  39. #define default_cylinder_h_reso 4
  40. #define default_cylinder_v_reso 1
  41. #define default_cone_h_reso 4
  42. #define default_cone_v_reso 1
  43. #define default_ring_h_reso 4
  44. #define default_ring_v_reso 1
  45. Poly_vert *poly_dummy;
  46. /*
  47.     Some Fixed assumptions for scan converting on hemicube Face
  48.     NOTE : If the row and column resolution are same then
  49.         the raster is assumed to be for the side face
  50.         of hemicube.
  51. */
  52. double D = 1.;
  53. double Dmin=0.025;
  54. double Dmax=100;
  55. static Poly_box regular_box={-1.,1.,-1.,1.,0.,1.};
  56.  
  57. int view_transform(C,U,V,N,rows,cols,m)
  58. Point3 *C;
  59. Vector3 *U,*V,*N;
  60. int rows,cols;
  61. Matrix4 *m;
  62. /*
  63.         From 
  64.           N - ViewPlane Normal
  65.               V - View Up Vector
  66.           U - Axis perpendicular to V and N
  67.               C - the point where the new origin will lie
  68.               D - viewplane distance from origin 
  69.               DMin - Distance of the near plane
  70.               Dmax - Distance of the Far place
  71.               Umin,Umax,Vmin,Vmax - the ViewWindow extent
  72.         Computes
  73.               matrix - a 4x4 transformation matrix to transform the
  74.                         viewing volume to regular clipping volume.
  75.         Ref. : book by Slater and Salmon
  76. */
  77. {
  78.     double Wxmin,Wymin,Wxmax,Wymax;
  79.     double pX,pY,dX,dY,dD;
  80.     Matrix4 m1,m2;
  81. /*
  82.     V3Negate(U); V3Negate(V);
  83. */
  84. /*
  85. fprintf(stderr,"%g %g %g : %g %g %g : %g %g %g\n",
  86. U->x,U->y,U->z,V->x,V->y,V->z,N->x,N->y,N->z);
  87. */
  88.     /* Following two lines very special to Hemicube face */
  89.     Wxmax = Wymax = 1.;
  90.     Wxmin = -1.; Wymin =((rows==cols)?-1.:0.);
  91.         m1.element[0][0]=U->x;
  92.         m1.element[1][0]=U->y;
  93.         m1.element[2][0]=U->z;
  94.  
  95.         m1.element[0][1]=V->x;
  96.         m1.element[1][1]=V->y;
  97.         m1.element[2][1]=V->z;
  98.  
  99.         m1.element[0][2]=N->x;
  100.         m1.element[1][2]=N->y;
  101.         m1.element[2][2]=N->z;
  102.  
  103.     m1.element[0][3] = m1.element[1][3] = m1.element[2][3] = 0.;
  104.     m1.element[3][3] = 1.;
  105.         m1.element[3][0] = -V3Dot(C,U);
  106.         m1.element[3][1] = -V3Dot(C,V);
  107.         m1.element[3][2] = -V3Dot(C,N);
  108.         /*
  109.  
  110.                 Transforming the View Volume to Regular ParalleloPiped.
  111.                 ------------------------------------------------------
  112.                 2D/dX   0       0            0
  113.                 0       2D/dY   0            0
  114.                 -pX/dX  -pY/dY  DMax/        1
  115.                                 (DMax-DMin)
  116.                 0       0       -DMax.DMin/  0
  117.                                 (DMax-DMin)
  118.  
  119.                 where pX = (Umin+Umax); pY = (Vmin+Vmax)
  120.                       dX = (Umin+Umax); dY = (Vmax-Vmin)
  121.  
  122.         */
  123.         /* Covert to Regular Pyramid */
  124.         pX = (Wxmin+Wxmax); pY = (Wymin+Wymax);
  125.         dX = (Wxmax-Wxmin); dY = (Wymax-Wymin);
  126.         dD = (Dmax-Dmin);
  127.     m2.element[0][1] = m2.element[0][2] = m2.element[0][3] = 
  128.     m2.element[1][0] = m2.element[1][2] = m2.element[1][3] =
  129.     m2.element[3][0] = m2.element[3][1] = m2.element[3][3] = 0.;
  130.         m2.element[2][3] = 1.0;
  131.  
  132.         m2.element[0][0] = 2.0*D/dX;
  133.         m2.element[1][1] = 2.0*D/dY;
  134.         m2.element[2][0] = -pX/dX; m2.element[2][1] = -pY/dY;
  135.         m2.element[2][2] = Dmax/dD;
  136.         m2.element[3][2] = -Dmax*Dmin/dD;
  137.     V3MatMul(&m1,&m2,m);
  138. }
  139.  
  140. static int current_patch;
  141. static double *current_zbuffer;
  142. static short int *current_raster;
  143. static char *current_surface_buffer;
  144. static void pixelproc(x, y, point)
  145. int x, y;
  146. Poly_vert *point;
  147. {
  148.         int index=y*hemicube_resolution+x;
  149.     if (x < 0 || x >= hemicube_resolution){
  150.         fprintf(stderr,"Beyond the raster limit.\n");
  151.         return;
  152.     }
  153.         if (point->sz < current_zbuffer[index]){
  154.         int uindex=grid_u(current_patch,point->u);
  155.         int vindex=grid_v(current_patch,point->v);
  156.                 current_zbuffer[index] = point->sz;
  157.         current_raster[index] = 
  158.             object[current_patch].start_grid_index+
  159.             gridindex(current_patch,uindex,vindex)+1;
  160.         current_surface_buffer[index]=
  161.             object[current_patch].surface_reflection_type+1;
  162.         }
  163. }
  164. static void homogeneous_xform(p,m)
  165. Poly_vert *p;
  166. Matrix4 *m;
  167. {
  168.         p->sx = (p->x * m->element[0][0]) + (p->y * m->element[1][0]) +
  169.                  (p->z * m->element[2][0]) + m->element[3][0];
  170.         p->sy = (p->x * m->element[0][1]) + (p->y * m->element[1][1]) +
  171.                  (p->z * m->element[2][1]) + m->element[3][1];
  172.         p->sz = (p->x * m->element[0][2]) + (p->y * m->element[1][2]) +
  173.                  (p->z * m->element[2][2]) + m->element[3][2];
  174.         p->sw = (p->x * m->element[0][3]) + (p->y * m->element[1][3]) +
  175.                  (p->z * m->element[2][3]) + m->element[3][3];
  176. }
  177. static void clip_n_scan(patchnum,p,m,rows,cols,zbuffer,surface_buffer,raster)
  178. int patchnum;
  179. Poly *p;
  180. Matrix4 *m;
  181. int rows,cols;
  182. double *zbuffer;
  183. char *surface_buffer;
  184. short int *raster;
  185. {
  186.     int i;
  187.     for (i=0;i<p->n;i++){
  188.         homogeneous_xform(&(p->vert[i]),m);
  189.     }
  190.         p->mask = (POLY_MASK(sx)|POLY_MASK(sy)|POLY_MASK(sz)
  191.           |POLY_MASK(sw)
  192.           |POLY_MASK(u)|POLY_MASK(v));
  193.     if(poly_clip_to_box(p,®ular_box)!=POLY_CLIP_OUT){
  194.         Window w;
  195.                 for(i=0;i<p->n;i++){
  196.                         p->vert[i].sx/=p->vert[i].sw;
  197.                         p->vert[i].sy/=p->vert[i].sw;
  198.                         p->vert[i].sz/=p->vert[i].sw;
  199.                         /* Do Window to Vp transform */
  200.                         p->vert[i].sx=0.5*cols*(p->vert[i].sx+1.);
  201.                         p->vert[i].sy=0.5*rows*(p->vert[i].sy+1.);
  202.                 }
  203.         current_patch=patchnum;
  204.         current_zbuffer=zbuffer;
  205.         current_surface_buffer=surface_buffer;
  206.         current_raster=raster;
  207.         w.x0 = w.y0 = 0;
  208.         w.x1 = cols-1; w.y1=rows-1;
  209.                 poly_scan(p,&w,pixelproc);
  210.     }
  211. }
  212. void null_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
  213. Vector3 *N;
  214. Matrix4 *m;
  215. int rows,cols;
  216. double *zbuffer;
  217. char *surface_buffer;
  218. short int *raster;
  219. {
  220. error("Scan Conversion of this geometry has not been implemented.");
  221. }
  222. static int back_face(v1,v2)
  223. Vector3 *v1,*v2;
  224. {
  225.     double d=V3Dot(v1,v2);
  226.     return(d>0. && d<=1.);
  227. }
  228. static void quadrilateral_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
  229. int patchnum;
  230. Vector3 *N;
  231. Matrix4 *m;
  232. int rows,cols;
  233. double *zbuffer;
  234. char *surface_buffer;
  235. short int *raster;
  236. {
  237.     Poly p;
  238.     Quadrilateral *q=(Quadrilateral *)object[patchnum].object_specific_structure;
  239.     if (back_face(N,&(q->plane_normal))) return;
  240.     p.n = 4;
  241.     p.vert[0].x = q->P00.x; p.vert[0].y = q->P00.y; p.vert[0].z = q->P00.z;
  242.     p.vert[0].u = p.vert[0].v = 0.;
  243.     p.vert[1].x = q->P10.x; p.vert[1].y = q->P10.y; p.vert[1].z = q->P10.z;
  244.     p.vert[1].u = 1.0; p.vert[1].v = 0.;
  245.     p.vert[2].x = q->P11.x; p.vert[2].y = q->P11.y; p.vert[2].z = q->P11.z;
  246.     p.vert[2].u = p.vert[2].v = 1.;
  247.     p.vert[3].x = q->P01.x; p.vert[3].y = q->P01.y; p.vert[3].z = q->P01.z;
  248.     p.vert[3].u = 0.; p.vert[3].v = 1.;
  249.     clip_n_scan(patchnum,&p,m,rows,cols,zbuffer,surface_buffer,raster);
  250. }
  251.  
  252. static void quadric_scan_convert(otype,patchnum,nu,nv,def_nu,def_nv,
  253.             d,N,m,rows,cols,zbuffer,surface_buffer,raster)
  254. int otype;
  255. int patchnum;
  256. int nu,nv,def_nu,def_nv;
  257. void *d;
  258. Vector3 *N;
  259. Matrix4 *m;
  260. int rows,cols;
  261. double *zbuffer;
  262. char *surface_buffer;
  263. short int *raster;
  264. {
  265.     Point3 posn[4];
  266.         Poly p;
  267.     int i,j,k;
  268.     double du,dv,u,v;
  269.     double U[4], V[4];
  270.  
  271.     if (nv==1 && nu==1){
  272.         nv = def_nv; nu = def_nu;
  273.     }
  274.     du = 1./nu; dv = 1./nv;
  275.     for(i=0,v=0.;i<nv;i++,v+=dv){
  276.         posn[0] = ofunc[otype].object_point(d,0.,v);
  277.         posn[3] = ofunc[otype].object_point(d,0.,v+dv);
  278.         U[0] = U[3] = 0.; V[0] = v; V[3] = v+dv;
  279.         for(j=0,u=0.;j<nu;j++,u+=du){
  280.             Vector3 normal;
  281.             normal = ofunc[otype].get_surface_normal(
  282.                     d,u+0.5*du,v+0.5*dv
  283.                 );
  284.                 if (back_face(N,&normal)) continue;
  285.             posn[1] = ofunc[otype].object_point(d,u+du,v);
  286.             U[1] = u + du; V[1] = v;
  287.             posn[2] = ofunc[otype].object_point(d,u+du,v+dv);
  288.             U[2] = u + du; V[2] = v+dv;
  289.             p.n = 4;
  290.             switch (otype){
  291.             case SPHERE    :
  292.             case CYLINDER    :
  293.             case CONE    :
  294.             case RING    :
  295.                 for(k=0;k<4;k++){
  296.                     p.vert[k].x = posn[k].x;
  297.                     p.vert[k].y = posn[k].y;
  298.                     p.vert[k].z = posn[k].z;
  299.                     p.vert[k].u = U[k];
  300.                     p.vert[k].v = V[k];
  301.                 }
  302.                 break;
  303.             case BUBBLE    :
  304.             case TUBE    :
  305.             case CUP    :
  306.                 for(k=3;k>=0;k--){
  307.                     p.vert[k].x = posn[k].x;
  308.                     p.vert[k].y = posn[k].y;
  309.                     p.vert[k].z = posn[k].z;
  310.                     p.vert[k].u = U[k];
  311.                     p.vert[k].v = V[k];
  312.                 }
  313.                 break;
  314.             default        :
  315.                 error("In scan converting qudric this case is illegal.");
  316.             }
  317.             posn[0] = posn[1];
  318.                 U[0] = U[1]; 
  319.                     V[0] = V[1];
  320.             posn[3] = posn[2]; 
  321.                 U[3] = U[2]; 
  322.                     V[3] = V[2];
  323.             clip_n_scan(patchnum,&p,m,rows,cols,zbuffer,surface_buffer,raster);
  324.         }
  325.     }
  326. }
  327. static void sphere_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
  328. int patchnum;
  329. Vector3 *N;
  330. Matrix4 *m;
  331. int rows,cols;
  332. double *zbuffer;
  333. char *surface_buffer;
  334. short int *raster;
  335. {
  336.     quadric_scan_convert(SPHERE,patchnum,
  337.         object[patchnum].grid_h_reso,
  338.         object[patchnum].grid_v_reso,
  339.         default_sphere_h_reso,default_sphere_v_reso,
  340.             object[patchnum].object_specific_structure,
  341.             N,m,rows,cols,zbuffer,surface_buffer,raster);
  342. }
  343.  
  344. static void bubble_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
  345. int patchnum;
  346. Vector3 *N;
  347. Matrix4 *m;
  348. int rows,cols;
  349. double *zbuffer;
  350. char *surface_buffer;
  351. short int *raster;
  352. {
  353.     quadric_scan_convert(BUBBLE,patchnum,
  354.         object[patchnum].grid_h_reso,
  355.         object[patchnum].grid_v_reso,
  356.         default_sphere_h_reso,default_sphere_v_reso,
  357.             object[patchnum].object_specific_structure,
  358.             N,m,rows,cols,zbuffer,surface_buffer,raster);
  359. }
  360.  
  361. static void cylinder_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
  362. int patchnum;
  363. Vector3 *N;
  364. Matrix4 *m;
  365. int rows,cols;
  366. double *zbuffer;
  367. char *surface_buffer;
  368. short int *raster;
  369. {
  370.     quadric_scan_convert(CYLINDER,patchnum,
  371.         object[patchnum].grid_h_reso,
  372.         object[patchnum].grid_v_reso,
  373.         default_cylinder_h_reso,default_cylinder_v_reso,
  374.             object[patchnum].object_specific_structure,
  375.             N,m,rows,cols,zbuffer,surface_buffer,raster);
  376. }
  377.  
  378. static void tube_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
  379. int patchnum;
  380. Vector3 *N;
  381. Matrix4 *m;
  382. int rows,cols;
  383. double *zbuffer;
  384. char *surface_buffer;
  385. short int *raster;
  386. {
  387.     quadric_scan_convert(TUBE,patchnum,
  388.         object[patchnum].grid_h_reso,
  389.         object[patchnum].grid_v_reso,
  390.         default_cylinder_h_reso,default_cylinder_v_reso,
  391.             object[patchnum].object_specific_structure,
  392.             N,m,rows,cols,zbuffer,surface_buffer,raster);
  393. }
  394.  
  395. static void cone_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
  396. int patchnum;
  397. Vector3 *N;
  398. Matrix4 *m;
  399. int rows,cols;
  400. double *zbuffer;
  401. char *surface_buffer;
  402. short int *raster;
  403. {
  404.     quadric_scan_convert(CONE,patchnum,
  405.         object[patchnum].grid_h_reso,
  406.         object[patchnum].grid_v_reso,
  407.         default_cone_h_reso,default_cone_v_reso,
  408.             object[patchnum].object_specific_structure,
  409.             N,m,rows,cols,zbuffer,surface_buffer,raster);
  410. }
  411.  
  412. static void cup_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
  413. int patchnum;
  414. Vector3 *N;
  415. Matrix4 *m;
  416. int rows,cols;
  417. double *zbuffer;
  418. char *surface_buffer;
  419. short int *raster;
  420. {
  421.     quadric_scan_convert(CUP,patchnum,
  422.         object[patchnum].grid_h_reso,
  423.         object[patchnum].grid_v_reso,
  424.         default_cone_h_reso,default_cone_v_reso,
  425.             object[patchnum].object_specific_structure,
  426.             N,m,rows,cols,zbuffer,surface_buffer,raster);
  427. }
  428.  
  429. static void ring_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
  430. int patchnum;
  431. Vector3 *N;
  432. Matrix4 *m;
  433. int rows,cols;
  434. double *zbuffer;
  435. char *surface_buffer;
  436. short int *raster;
  437. {
  438.     quadric_scan_convert(RING,patchnum,
  439.         object[patchnum].grid_h_reso,
  440.         object[patchnum].grid_v_reso,
  441.         default_ring_h_reso,default_ring_v_reso,
  442.             object[patchnum].object_specific_structure,
  443.             N,m,rows,cols,zbuffer,surface_buffer,raster);
  444. }
  445. static void polygon_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
  446. int patchnum;
  447. Vector3 *N;
  448. Matrix4 *m;
  449. int rows,cols;
  450. double *zbuffer;
  451. char *surface_buffer;
  452. short int *raster;
  453. {
  454.         Poly p;
  455.     int i;
  456.         Polygon *poly=(Polygon *)object[patchnum].object_specific_structure;
  457.  
  458.         if (back_face(N,&(poly->plane_normal))) return;
  459.         p.n = poly->nvertices;
  460.     for(i=0;i<p.n;i++){
  461.         p.vert[i].x=poly->vertex_list[i].x;
  462.         p.vert[i].y=poly->vertex_list[i].y;
  463.         p.vert[i].z=poly->vertex_list[i].z;
  464.         p.vert[i].u = p.vert[i].v = 0.5; 
  465.             /* This assignment is arbitrary.
  466.                Any value would do. */
  467.     }
  468.     clip_n_scan(patchnum,&p,m,rows,cols,zbuffer,surface_buffer,raster);
  469. }
  470. void (*geometry_specific_scan_convert[MAX_GEOMETRY_TYPE])()=
  471. {
  472.     quadrilateral_scan_convert,
  473.     sphere_scan_convert,
  474.     bubble_scan_convert,
  475.     cylinder_scan_convert,
  476.     tube_scan_convert,
  477.     cone_scan_convert,
  478.     cup_scan_convert,
  479.     ring_scan_convert,
  480.     polygon_scan_convert,
  481.     null_scan_convert
  482. };
  483.