home *** CD-ROM | disk | FTP | other *** search
- /*
- Module to Scan Convert Objects on the Hemicube.
- Objects include Polygon, sphere, bubble, cylinder, tube,
- cone, cup and anular ring.
- Objects other than Polygon are scan converted by
- breaking them into rectangular parts in u,v domain.
- The breakup used is user defined if specified by the
- user or default break up.
- Default breakup for different objects are as follows:
- Sphere, Bubble : 4 x 4
- Cylinder, Tube : 4 x 1
- Cone, cup : 4 x 1
- Anular Ring : 4 x 1
- User may change the defaults by changing the
- appropriate #define statements below.
- The rectangluar parts in the u,v domain are assumed to
- be planar quadrilateral. No effort is made to check
- their planarity. The normal to the quadrilateral is
- computed as the actual object object normal at the
- center of the (u,v) rectangular part. This normal is
- used for back-face culling.
- NOTE : If the above mentioned technique is used to
- render the objects other than Polygon then terrible
- cracks may appear.
- ------
- sumant
- 29-July-1991
- */
- #include <stdio.h>
- #include <math.h>
-
- #include "GraphicsGems.h"
- #include "poly.h"
- #include "data_structure.h"
- #include "objects.h"
- extern int hemicube_resolution;
- #define default_sphere_h_reso 4
- #define default_sphere_v_reso 4
- #define default_cylinder_h_reso 4
- #define default_cylinder_v_reso 1
- #define default_cone_h_reso 4
- #define default_cone_v_reso 1
- #define default_ring_h_reso 4
- #define default_ring_v_reso 1
- Poly_vert *poly_dummy;
- /*
- Some Fixed assumptions for scan converting on hemicube Face
- NOTE : If the row and column resolution are same then
- the raster is assumed to be for the side face
- of hemicube.
- */
- double D = 1.;
- double Dmin=0.025;
- double Dmax=100;
- static Poly_box regular_box={-1.,1.,-1.,1.,0.,1.};
-
- int view_transform(C,U,V,N,rows,cols,m)
- Point3 *C;
- Vector3 *U,*V,*N;
- int rows,cols;
- Matrix4 *m;
- /*
- From
- N - ViewPlane Normal
- V - View Up Vector
- U - Axis perpendicular to V and N
- C - the point where the new origin will lie
- D - viewplane distance from origin
- DMin - Distance of the near plane
- Dmax - Distance of the Far place
- Umin,Umax,Vmin,Vmax - the ViewWindow extent
- Computes
- matrix - a 4x4 transformation matrix to transform the
- viewing volume to regular clipping volume.
- Ref. : book by Slater and Salmon
- */
- {
- double Wxmin,Wymin,Wxmax,Wymax;
- double pX,pY,dX,dY,dD;
- Matrix4 m1,m2;
- /*
- V3Negate(U); V3Negate(V);
- */
- /*
- fprintf(stderr,"%g %g %g : %g %g %g : %g %g %g\n",
- U->x,U->y,U->z,V->x,V->y,V->z,N->x,N->y,N->z);
- */
- /* Following two lines very special to Hemicube face */
- Wxmax = Wymax = 1.;
- Wxmin = -1.; Wymin =((rows==cols)?-1.:0.);
- m1.element[0][0]=U->x;
- m1.element[1][0]=U->y;
- m1.element[2][0]=U->z;
-
- m1.element[0][1]=V->x;
- m1.element[1][1]=V->y;
- m1.element[2][1]=V->z;
-
- m1.element[0][2]=N->x;
- m1.element[1][2]=N->y;
- m1.element[2][2]=N->z;
-
- m1.element[0][3] = m1.element[1][3] = m1.element[2][3] = 0.;
- m1.element[3][3] = 1.;
- m1.element[3][0] = -V3Dot(C,U);
- m1.element[3][1] = -V3Dot(C,V);
- m1.element[3][2] = -V3Dot(C,N);
- /*
-
- Transforming the View Volume to Regular ParalleloPiped.
- ------------------------------------------------------
- 2D/dX 0 0 0
- 0 2D/dY 0 0
- -pX/dX -pY/dY DMax/ 1
- (DMax-DMin)
- 0 0 -DMax.DMin/ 0
- (DMax-DMin)
-
- where pX = (Umin+Umax); pY = (Vmin+Vmax)
- dX = (Umin+Umax); dY = (Vmax-Vmin)
-
- */
- /* Covert to Regular Pyramid */
- pX = (Wxmin+Wxmax); pY = (Wymin+Wymax);
- dX = (Wxmax-Wxmin); dY = (Wymax-Wymin);
- dD = (Dmax-Dmin);
- m2.element[0][1] = m2.element[0][2] = m2.element[0][3] =
- m2.element[1][0] = m2.element[1][2] = m2.element[1][3] =
- m2.element[3][0] = m2.element[3][1] = m2.element[3][3] = 0.;
- m2.element[2][3] = 1.0;
-
- m2.element[0][0] = 2.0*D/dX;
- m2.element[1][1] = 2.0*D/dY;
- m2.element[2][0] = -pX/dX; m2.element[2][1] = -pY/dY;
- m2.element[2][2] = Dmax/dD;
- m2.element[3][2] = -Dmax*Dmin/dD;
- V3MatMul(&m1,&m2,m);
- }
-
- static int current_patch;
- static double *current_zbuffer;
- static short int *current_raster;
- static char *current_surface_buffer;
- static void pixelproc(x, y, point)
- int x, y;
- Poly_vert *point;
- {
- int index=y*hemicube_resolution+x;
- if (x < 0 || x >= hemicube_resolution){
- fprintf(stderr,"Beyond the raster limit.\n");
- return;
- }
- if (point->sz < current_zbuffer[index]){
- int uindex=grid_u(current_patch,point->u);
- int vindex=grid_v(current_patch,point->v);
- current_zbuffer[index] = point->sz;
- current_raster[index] =
- object[current_patch].start_grid_index+
- gridindex(current_patch,uindex,vindex)+1;
- current_surface_buffer[index]=
- object[current_patch].surface_reflection_type+1;
- }
- }
- static void homogeneous_xform(p,m)
- Poly_vert *p;
- Matrix4 *m;
- {
- p->sx = (p->x * m->element[0][0]) + (p->y * m->element[1][0]) +
- (p->z * m->element[2][0]) + m->element[3][0];
- p->sy = (p->x * m->element[0][1]) + (p->y * m->element[1][1]) +
- (p->z * m->element[2][1]) + m->element[3][1];
- p->sz = (p->x * m->element[0][2]) + (p->y * m->element[1][2]) +
- (p->z * m->element[2][2]) + m->element[3][2];
- p->sw = (p->x * m->element[0][3]) + (p->y * m->element[1][3]) +
- (p->z * m->element[2][3]) + m->element[3][3];
- }
- static void clip_n_scan(patchnum,p,m,rows,cols,zbuffer,surface_buffer,raster)
- int patchnum;
- Poly *p;
- Matrix4 *m;
- int rows,cols;
- double *zbuffer;
- char *surface_buffer;
- short int *raster;
- {
- int i;
- for (i=0;i<p->n;i++){
- homogeneous_xform(&(p->vert[i]),m);
- }
- p->mask = (POLY_MASK(sx)|POLY_MASK(sy)|POLY_MASK(sz)
- |POLY_MASK(sw)
- |POLY_MASK(u)|POLY_MASK(v));
- if(poly_clip_to_box(p,®ular_box)!=POLY_CLIP_OUT){
- Window w;
- for(i=0;i<p->n;i++){
- p->vert[i].sx/=p->vert[i].sw;
- p->vert[i].sy/=p->vert[i].sw;
- p->vert[i].sz/=p->vert[i].sw;
- /* Do Window to Vp transform */
- p->vert[i].sx=0.5*cols*(p->vert[i].sx+1.);
- p->vert[i].sy=0.5*rows*(p->vert[i].sy+1.);
- }
- current_patch=patchnum;
- current_zbuffer=zbuffer;
- current_surface_buffer=surface_buffer;
- current_raster=raster;
- w.x0 = w.y0 = 0;
- w.x1 = cols-1; w.y1=rows-1;
- poly_scan(p,&w,pixelproc);
- }
- }
- void null_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
- Vector3 *N;
- Matrix4 *m;
- int rows,cols;
- double *zbuffer;
- char *surface_buffer;
- short int *raster;
- {
- error("Scan Conversion of this geometry has not been implemented.");
- }
- static int back_face(v1,v2)
- Vector3 *v1,*v2;
- {
- double d=V3Dot(v1,v2);
- return(d>0. && d<=1.);
- }
- static void quadrilateral_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
- int patchnum;
- Vector3 *N;
- Matrix4 *m;
- int rows,cols;
- double *zbuffer;
- char *surface_buffer;
- short int *raster;
- {
- Poly p;
- Quadrilateral *q=(Quadrilateral *)object[patchnum].object_specific_structure;
- if (back_face(N,&(q->plane_normal))) return;
- p.n = 4;
- p.vert[0].x = q->P00.x; p.vert[0].y = q->P00.y; p.vert[0].z = q->P00.z;
- p.vert[0].u = p.vert[0].v = 0.;
- p.vert[1].x = q->P10.x; p.vert[1].y = q->P10.y; p.vert[1].z = q->P10.z;
- p.vert[1].u = 1.0; p.vert[1].v = 0.;
- p.vert[2].x = q->P11.x; p.vert[2].y = q->P11.y; p.vert[2].z = q->P11.z;
- p.vert[2].u = p.vert[2].v = 1.;
- p.vert[3].x = q->P01.x; p.vert[3].y = q->P01.y; p.vert[3].z = q->P01.z;
- p.vert[3].u = 0.; p.vert[3].v = 1.;
- clip_n_scan(patchnum,&p,m,rows,cols,zbuffer,surface_buffer,raster);
- }
-
- static void quadric_scan_convert(otype,patchnum,nu,nv,def_nu,def_nv,
- d,N,m,rows,cols,zbuffer,surface_buffer,raster)
- int otype;
- int patchnum;
- int nu,nv,def_nu,def_nv;
- void *d;
- Vector3 *N;
- Matrix4 *m;
- int rows,cols;
- double *zbuffer;
- char *surface_buffer;
- short int *raster;
- {
- Point3 posn[4];
- Poly p;
- int i,j,k;
- double du,dv,u,v;
- double U[4], V[4];
-
- if (nv==1 && nu==1){
- nv = def_nv; nu = def_nu;
- }
- du = 1./nu; dv = 1./nv;
- for(i=0,v=0.;i<nv;i++,v+=dv){
- posn[0] = ofunc[otype].object_point(d,0.,v);
- posn[3] = ofunc[otype].object_point(d,0.,v+dv);
- U[0] = U[3] = 0.; V[0] = v; V[3] = v+dv;
- for(j=0,u=0.;j<nu;j++,u+=du){
- Vector3 normal;
- normal = ofunc[otype].get_surface_normal(
- d,u+0.5*du,v+0.5*dv
- );
- if (back_face(N,&normal)) continue;
- posn[1] = ofunc[otype].object_point(d,u+du,v);
- U[1] = u + du; V[1] = v;
- posn[2] = ofunc[otype].object_point(d,u+du,v+dv);
- U[2] = u + du; V[2] = v+dv;
- p.n = 4;
- switch (otype){
- case SPHERE :
- case CYLINDER :
- case CONE :
- case RING :
- for(k=0;k<4;k++){
- p.vert[k].x = posn[k].x;
- p.vert[k].y = posn[k].y;
- p.vert[k].z = posn[k].z;
- p.vert[k].u = U[k];
- p.vert[k].v = V[k];
- }
- break;
- case BUBBLE :
- case TUBE :
- case CUP :
- for(k=3;k>=0;k--){
- p.vert[k].x = posn[k].x;
- p.vert[k].y = posn[k].y;
- p.vert[k].z = posn[k].z;
- p.vert[k].u = U[k];
- p.vert[k].v = V[k];
- }
- break;
- default :
- error("In scan converting qudric this case is illegal.");
- }
- posn[0] = posn[1];
- U[0] = U[1];
- V[0] = V[1];
- posn[3] = posn[2];
- U[3] = U[2];
- V[3] = V[2];
- clip_n_scan(patchnum,&p,m,rows,cols,zbuffer,surface_buffer,raster);
- }
- }
- }
- static void sphere_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
- int patchnum;
- Vector3 *N;
- Matrix4 *m;
- int rows,cols;
- double *zbuffer;
- char *surface_buffer;
- short int *raster;
- {
- quadric_scan_convert(SPHERE,patchnum,
- object[patchnum].grid_h_reso,
- object[patchnum].grid_v_reso,
- default_sphere_h_reso,default_sphere_v_reso,
- object[patchnum].object_specific_structure,
- N,m,rows,cols,zbuffer,surface_buffer,raster);
- }
-
- static void bubble_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
- int patchnum;
- Vector3 *N;
- Matrix4 *m;
- int rows,cols;
- double *zbuffer;
- char *surface_buffer;
- short int *raster;
- {
- quadric_scan_convert(BUBBLE,patchnum,
- object[patchnum].grid_h_reso,
- object[patchnum].grid_v_reso,
- default_sphere_h_reso,default_sphere_v_reso,
- object[patchnum].object_specific_structure,
- N,m,rows,cols,zbuffer,surface_buffer,raster);
- }
-
- static void cylinder_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
- int patchnum;
- Vector3 *N;
- Matrix4 *m;
- int rows,cols;
- double *zbuffer;
- char *surface_buffer;
- short int *raster;
- {
- quadric_scan_convert(CYLINDER,patchnum,
- object[patchnum].grid_h_reso,
- object[patchnum].grid_v_reso,
- default_cylinder_h_reso,default_cylinder_v_reso,
- object[patchnum].object_specific_structure,
- N,m,rows,cols,zbuffer,surface_buffer,raster);
- }
-
- static void tube_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
- int patchnum;
- Vector3 *N;
- Matrix4 *m;
- int rows,cols;
- double *zbuffer;
- char *surface_buffer;
- short int *raster;
- {
- quadric_scan_convert(TUBE,patchnum,
- object[patchnum].grid_h_reso,
- object[patchnum].grid_v_reso,
- default_cylinder_h_reso,default_cylinder_v_reso,
- object[patchnum].object_specific_structure,
- N,m,rows,cols,zbuffer,surface_buffer,raster);
- }
-
- static void cone_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
- int patchnum;
- Vector3 *N;
- Matrix4 *m;
- int rows,cols;
- double *zbuffer;
- char *surface_buffer;
- short int *raster;
- {
- quadric_scan_convert(CONE,patchnum,
- object[patchnum].grid_h_reso,
- object[patchnum].grid_v_reso,
- default_cone_h_reso,default_cone_v_reso,
- object[patchnum].object_specific_structure,
- N,m,rows,cols,zbuffer,surface_buffer,raster);
- }
-
- static void cup_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
- int patchnum;
- Vector3 *N;
- Matrix4 *m;
- int rows,cols;
- double *zbuffer;
- char *surface_buffer;
- short int *raster;
- {
- quadric_scan_convert(CUP,patchnum,
- object[patchnum].grid_h_reso,
- object[patchnum].grid_v_reso,
- default_cone_h_reso,default_cone_v_reso,
- object[patchnum].object_specific_structure,
- N,m,rows,cols,zbuffer,surface_buffer,raster);
- }
-
- static void ring_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
- int patchnum;
- Vector3 *N;
- Matrix4 *m;
- int rows,cols;
- double *zbuffer;
- char *surface_buffer;
- short int *raster;
- {
- quadric_scan_convert(RING,patchnum,
- object[patchnum].grid_h_reso,
- object[patchnum].grid_v_reso,
- default_ring_h_reso,default_ring_v_reso,
- object[patchnum].object_specific_structure,
- N,m,rows,cols,zbuffer,surface_buffer,raster);
- }
- static void polygon_scan_convert(patchnum,N,m,rows,cols,zbuffer,surface_buffer,raster)
- int patchnum;
- Vector3 *N;
- Matrix4 *m;
- int rows,cols;
- double *zbuffer;
- char *surface_buffer;
- short int *raster;
- {
- Poly p;
- int i;
- Polygon *poly=(Polygon *)object[patchnum].object_specific_structure;
-
- if (back_face(N,&(poly->plane_normal))) return;
- p.n = poly->nvertices;
- for(i=0;i<p.n;i++){
- p.vert[i].x=poly->vertex_list[i].x;
- p.vert[i].y=poly->vertex_list[i].y;
- p.vert[i].z=poly->vertex_list[i].z;
- p.vert[i].u = p.vert[i].v = 0.5;
- /* This assignment is arbitrary.
- Any value would do. */
- }
- clip_n_scan(patchnum,&p,m,rows,cols,zbuffer,surface_buffer,raster);
- }
- void (*geometry_specific_scan_convert[MAX_GEOMETRY_TYPE])()=
- {
- quadrilateral_scan_convert,
- sphere_scan_convert,
- bubble_scan_convert,
- cylinder_scan_convert,
- tube_scan_convert,
- cone_scan_convert,
- cup_scan_convert,
- ring_scan_convert,
- polygon_scan_convert,
- null_scan_convert
- };
-