home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <math.h>
- #include <malloc.h>
- #include "GraphicsGems.h"
- #include "data_structure.h"
- #include "objects.h"
-
- #include "raddecl.h"
-
- /************** Begin object specific intersections **************/
- static double intersect_polygon(p,ray_start,ray_direction,pu,pv)
- Polygon *p;
- Point3 *ray_start;
- Vector3 *ray_direction;
- double *pu,*pv;
- {
- double ray_polygon();
- *pu = *pv = 0.5;
- return(
- ray_polygon(ray_start,ray_direction,
- &(p->plane_normal), p->plane_constant,
- p->dominant_axis_flag,
- p->nvertices,
- p->vertex_list)
- );
- }
-
- static double intersect_quadrilateral(q,ray_start,ray_direction,pu,pv)
- Quadrilateral *q;
- Point3 *ray_start;
- Vector3 *ray_direction;
- double *pu,*pv;
- {
- double ray_quadrilateral();
- return(
- ray_quadrilateral(ray_start,ray_direction,
- &(q->plane_normal), q->plane_constant,
- q->Du0,q->Du1,q->Du2,q->Dux,q->Duy,
- q->Dv0,q->Dv1,q->Dv2,q->Dvx,q->Dvy,
- &(q->Qux),&(q->Quy),&(q->Qvx),&(q->Qvy),
- &(q->Na),&(q->Nb),&(q->Nc),
- pu,pv)
- );
- }
-
- static double intersect_sphere(s,ray_start,ray_direction,pu,pv)
- Sphere *s;
- Point3 *ray_start;
- Vector3 *ray_direction;
- double *pu,*pv;
- {
- double ray_sphere();
- return(
- ray_sphere(ray_start,ray_direction,
- s->radius, &(s->center), 0, pu,pv)
- );
- }
-
- static double intersect_bubble(b,ray_start,ray_direction,pu,pv)
- Sphere *b;
- Point3 *ray_start;
- Vector3 *ray_direction;
- double *pu,*pv;
- {
- double ray_sphere();
- return(
- ray_sphere(ray_start,ray_direction,
- b->radius, &(b->center), 1, pu,pv)
- );
- }
-
- static void ray_transform(s_in,d_in,m,s_out,d_out)
- Point3 *s_in,*s_out;
- Vector3 *d_in,*d_out;
- Matrix4 *m;
- {
- *d_out = transform_vector(d_in,m);
- *s_out = *s_in;
- V3MulPointByMatrix(s_out,m);
- }
-
- static double intersect_cylinder(c,ray_start,ray_direction,pu,pv)
- Cylinder *c;
- Point3 *ray_start;
- Vector3 *ray_direction;
- double *pu,*pv;
- {
- double ray_cylinder();
- Point3 s;
- Vector3 d;
- ray_transform(ray_start,ray_direction,&(c->world_to_object),&s,&d);
- return(
- ray_cylinder(&s,&d,c->radius,c->height,0,pu,pv)
- );
- }
-
- static double intersect_tube(tube,ray_start,ray_direction,pu,pv)
- Cylinder *tube;
- Point3 *ray_start;
- Vector3 *ray_direction;
- double *pu,*pv;
- {
- double ray_cylinder();
- Point3 s;
- Vector3 d;
- ray_transform(ray_start,ray_direction,&(tube->world_to_object),&s,&d);
- return(
- ray_cylinder(&s,&d,tube->radius,tube->height,1,pu,pv)
- );
- }
-
- static double intersect_cone(c,ray_start,ray_direction,pu,pv)
- Cone *c;
- Point3 *ray_start;
- Vector3 *ray_direction;
- double *pu,*pv;
- {
- double ray_cone();
- Point3 s;
- Vector3 d;
- ray_transform(ray_start,ray_direction,&(c->world_to_object),&s,&d);
- return(
- ray_cone(&s,&d,c->distance,0,pu,pv)
- );
- }
-
- static double intersect_cup(c,ray_start,ray_direction,pu,pv)
- Cone *c;
- Point3 *ray_start;
- Vector3 *ray_direction;
- double *pu,*pv;
- {
- double ray_cone();
- Point3 s;
- Vector3 d;
- ray_transform(ray_start,ray_direction,&(c->world_to_object),&s,&d);
- return(
- ray_cone(&s,&d,c->distance,1,pu,pv)
- );
- }
-
- static double intersect_ring(r,ray_start,ray_direction,pu,pv)
- Ring *r;
- Point3 *ray_start;
- Vector3 *ray_direction;
- double *pu,*pv;
- {
- double ray_ring();
- Point3 s;
- Vector3 d;
- ray_transform(ray_start,ray_direction,&(r->world_to_object),&s,&d);
- return(
- ray_ring(&s,&d,r->inner_radius,r->outer_radius,pu,pv)
- );
- }
-
- static double intersect_other_geometry(dummy,ray_start,ray_direction,pu,pv)
- void *dummy;
- Point3 *ray_start;
- Vector3 *ray_direction;
- double *pu,*pv;
- {
- error("This Geometry is unimplemented.");
- }
-
-
- /************* End object specific intersections **************/
- /************* Begin Object Specific Preprocess **************/
- /*
- get_view_trans_matrix(U,V,N,m)
- Vector3 *U,*V,*N;
- Matrix4 *m;
- {
- m->element[0][0]=U->x;
- m->element[1][0]=U->y;
- m->element[2][0]=U->z;
- m->element[0][1]=V->x;
- m->element[1][1]=V->y;
- m->element[2][1]=V->z;
- m->element[0][2]=N->x;
- m->element[1][2]=N->y;
- m->element[2][2]=N->z;
-
- m->element[0][3]= m->element[1][3]= m->element[2][3]=
- m->element[3][0]= m->element[3][1]= m->element[3][2]=0.;
- m->element[3][3]=1.;
- }
- */
- #define update_scene_bound(bb,b) {\
- b->min.x = MIN(bb->min.x,b->min.x); b->max.x = MAX(bb->max.x,b->max.x);\
- b->min.y = MIN(bb->min.y,b->min.y); b->max.y = MAX(bb->max.y,b->max.y);\
- b->min.z = MIN(bb->min.z,b->min.z); b->max.z = MAX(bb->max.z,b->max.z);\
- }
-
- static void null_preprocess(grid,un,vn,spec_struc,bb,b)
- Surface_Grid_structure *grid;
- int un,vn;
- void *spec_struc;
- Box3 *bb,*b;
- {
- error("No Preprocess Implemented Yet for this Object.");
- }
- /*
- static double area (p1,p2,p3,p4)
- Point3 *p1,*p2,*p3,*p4;
- {
- Vector3 v1,v2,N;
- double a;
- V3Sub(p2,p1,&v1); V3Sub(p4,p1,&v2); V3Cross(&v1,&v2,&N);
- a = V3Length(&N);
- V3Sub(p4,p3,&v1);V3Sub(p2,p3,&v2); V3Cross(&v1,&v2,&N);
- a += V3Length(&N);
- return(a/2.0);
- }
- */
- static int get_dominant_axis(N)
- Vector3 *N;
- {
- double maxval;
- Point3 anorm;
- /* Computes Dominant axis.
- 0 - for X-axis, 1 - for Y-axis, 2 - for Z axis */
- anorm.x = fabs(N->x);
- anorm.y = fabs(N->y);
- anorm.z = fabs(N->z);
- maxval = MAX(anorm.x, MAX(anorm.y,anorm.z));
- return((maxval == anorm.x)?0:((maxval == anorm.y)?1:2));
- }
- static double trapez_area(n,vlist,N,dominant_axis)
- /* Polygon area computation by trapezium area summation method */
- int n;
- Point3 vlist[];
- Vector3 *N;
- int dominant_axis;
- {
- int i;
- double area = 0.;
- Point2 cur,last;
-
- project_point(last,vlist[n-1],dominant_axis);
- for(i=0;i<n;i++,last=cur){
- project_point(cur,vlist[i],dominant_axis);
- area += (cur.x-last.x)*(cur.y+last.y);
- }
- area /= ((dominant_axis==0)?N->x:((dominant_axis==1)?N->y:N->z));
- return(0.5*fabs(area));
- }
-
- static void quadrilateral_preprocess(grid,un,vn,q,bb,b)
- Surface_Grid_structure *grid;
- int un,vn;
- Quadrilateral *q;
- Box3 *bb,*b;
- {
- int i,j,n;
- Point3 Pa, Pb,Pc,Pd;
- double u,v,du=1.0/un,dv=1.0/vn;
- double area();
- /* Compute Bounding Box */
- bb->max.x=MAX(MAX(q->P00.x,q->P10.x),MAX(q->P11.x,q->P01.x));
- bb->max.y=MAX(MAX(q->P00.y,q->P10.y),MAX(q->P11.y,q->P01.y));
- bb->max.z=MAX(MAX(q->P00.z,q->P10.z),MAX(q->P11.z,q->P01.z));
-
- bb->min.x=MIN(MIN(q->P00.x,q->P10.x),MIN(q->P11.x,q->P01.x));
- bb->min.y=MIN(MIN(q->P00.y,q->P10.y),MIN(q->P11.y,q->P01.y));
- bb->min.z=MIN(MIN(q->P00.z,q->P10.z),MIN(q->P11.z,q->P01.z));
- update_scene_bound(bb,b);
- /* Compute Other parameters. */
- Pa.x=q->P00.x-q->P10.x+q->P11.x-q->P01.x;
- Pa.y=q->P00.y-q->P10.y+q->P11.y-q->P01.y;
- Pa.z=q->P00.z-q->P10.z+q->P11.z-q->P01.z;
- Pb.x=q->P10.x-q->P00.x;
- Pb.y=q->P10.y-q->P00.y;
- Pb.z=q->P10.z-q->P00.z;
- Pc.x=q->P01.x-q->P00.x;
- Pc.y=q->P01.y-q->P00.y;
- Pc.z=q->P01.z-q->P00.z;
- Pd = q->P00;
- V3Cross(&Pb,&Pc,&(q->plane_normal));
- V3Normalize(&(q->plane_normal));
- /* Compute grid area. */
- for(n=0,v=0.0,i=0;i<vn;i++,v+=dv){
- Point3 f[4];
- f[0] = get_bilinear(q,(double)0.,v);
- f[3] = get_bilinear(q,(double)0.,v+dv);
- for(u=0.0,j=0;j<un;j++,u+=du,n++){
- f[1] = get_bilinear(q,u+du,v);
- f[2] = get_bilinear(q,u+du,v+dv);
- grid[n].area=trapez_area(4,f,&(q->plane_normal),
- get_dominant_axis(&(q->plane_normal)));
- f[0] = f[1]; f[3] = f[2];
- }
- }
- /* Compute the Coordinate Transformation Matrix */
- /*
- {
- Vector3 U,V,W;
- Matrix4 m;
- V=Pc;
- V3Normalize(&V);
- V3Cross(&V,&(q->plane_normal),&U);
- get_view_trans_matrix(&U,&V,&(q->plane_normal),&m);
- U.x=V.y=W.z=1.0;
- U.y=U.z=V.x=V.z=W.x=W.y=0.0;
- U = transform_vector(&U,&m);
- V = transform_vector(&V,&m);
- W = transform_vector(&W,&m);
- get_view_trans_matrix(&U,&V,&W,&(q->local_trans));
- }
- */
- align_Z_to_axis(&(q->plane_normal),&(q->local_trans));
-
- q->plane_constant = -V3Dot(&(q->plane_normal),&(q->P00));
-
- V3Cross(&Pa,&(q->plane_normal),&(q->Na));
- V3Cross(&Pb,&(q->plane_normal),&(q->Nb));
- V3Cross(&Pc,&(q->plane_normal),&(q->Nc));
-
- q->Du0 = V3Dot(&(q->Nc),&Pd);
- q->Du1 = V3Dot(&(q->Na),&Pd)+V3Dot(&(q->Nc),&Pb);
- q->Du2 = V3Dot(&(q->Na),&Pb);
- if (fabs(q->Du2) > EPSILON){
- double frac = 1.0/q->Du2;
- q->Quy.x = -q->Nc.x*frac;
- q->Quy.y = -q->Nc.y*frac;
- q->Quy.z = -q->Nc.z*frac;
- q->Duy=q->Du0*frac;
- frac /= 2.0;
- q->Qux.x=q->Na.x*frac;
- q->Qux.y=q->Na.y*frac;
- q->Qux.z=q->Na.z*frac;
- q->Dux = -q->Du1*frac;
- }
- q->Dv0 = V3Dot(&(q->Nb),&Pd);
- q->Dv1 = V3Dot(&(q->Na),&Pd)+V3Dot(&(q->Nb),&Pc);
- q->Dv2 = V3Dot(&(q->Na),&Pc);
- if (fabs(q->Dv2) > EPSILON){
- double frac = 1.0/q->Dv2;
- q->Qvy.x = -q->Nb.x*frac;
- q->Qvy.y = -q->Nb.y*frac;
- q->Qvy.z = -q->Nb.z*frac;
- q->Dvy=q->Dv0*frac;
- frac /= 2.0;
- q->Qvx.x=q->Na.x*frac;
- q->Qvx.y=q->Na.y*frac;
- q->Qvx.z=q->Na.z*frac;
- q->Dvx = -q->Dv1*frac;
- }
- }
-
- static void sphere_preprocess(grid,un,vn,s,bb,b)
- Surface_Grid_structure *grid;
- int un,vn;
- Sphere *s;
- Box3 *bb,*b;
- {
- int i,j,n;
- double area,mult,prevcos=1.0,nextcos;
- double v,du=1.0/un,dv=1.0/vn;
- /* Compute Bounding Box */
- bb->min.x = s->center.x - s->radius;
- bb->min.y = s->center.y - s->radius;
- bb->min.z = s->center.z - s->radius;
-
- bb->max.x = s->center.x + s->radius;
- bb->max.y = s->center.y + s->radius;
- bb->max.z = s->center.z + s->radius;
- update_scene_bound(bb,b);
- /* Compute Area of the Grid Elements. */
- mult = 2.*PI*s->radius*s->radius*du;
- for(n=0,v=0.0,i=0;i<vn;i++,v+=dv){
- nextcos = cos(PI*(v+dv));
- area=mult*fabs(prevcos-nextcos);
- prevcos=nextcos;
- for(j=0;j<un;j++,n++)
- grid[n].area=area;
- }
- }
-
- void translate(dx,dy,dz,m)
- double dx,dy,dz;
- Matrix4 *m;
- {
- m->element[0][0] =
- m->element[1][1] =
- m->element[2][2] =
- m->element[3][3] = 1.;
- m->element[0][1] = m->element[0][2] = m->element[0][3] =
- m->element[1][0] = m->element[1][2] = m->element[1][3] =
- m->element[2][0] = m->element[2][1] = m->element[2][3] = 0.;
- m->element[3][0] = dx;
- m->element[3][1] = dy;
- m->element[3][2] = dz;
- }
-
- void scale(sx,sy,sz,m)
- double sx,sy,sz;
- Matrix4 *m;
- {
- m->element[0][0] = sx;
- m->element[1][1] = sy;
- m->element[2][2] = sz;
-
- m->element[3][3] = 1.;
- m->element[0][1] = m->element[0][2] = m->element[0][3] =
- m->element[1][0] = m->element[1][2] = m->element[1][3] =
- m->element[2][0] = m->element[2][1] = m->element[2][3] =
- m->element[3][0] = m->element[3][1] = m->element[3][2] = 0.;
- }
-
- void bound_transform(b,m)
- Box3 *b;
- Matrix4 *m;
- {
- Point3 p;
- Box3 bb;
- bb = *b;
- b->min.x = b->min.y = b->min.z = LARGE;
- b->max.x = b->max.y = b->max.z = -LARGE;
- p = bb.min; V3MulPointByMatrix(&p,m);
- b->min.x = MIN(b->min.x,p.x); b->min.y = MIN(b->min.y,p.y); b->min.z = MIN(b->min.z,p.z);
- b->max.x = MAX(b->max.x,p.x); b->max.y = MAX(b->max.y,p.y); b->max.z = MAX(b->max.z,p.z);
- p = bb.min; p.x = bb.max.x; V3MulPointByMatrix(&p,m);
- b->min.x = MIN(b->min.x,p.x); b->min.y = MIN(b->min.y,p.y); b->min.z = MIN(b->min.z,p.z);
- b->max.x = MAX(b->max.x,p.x); b->max.y = MAX(b->max.y,p.y); b->max.z = MAX(b->max.z,p.z);
- p = bb.min; p.y = bb.max.y; V3MulPointByMatrix(&p,m);
- b->min.x = MIN(b->min.x,p.x); b->min.y = MIN(b->min.y,p.y); b->min.z = MIN(b->min.z,p.z);
- b->max.x = MAX(b->max.x,p.x); b->max.y = MAX(b->max.y,p.y); b->max.z = MAX(b->max.z,p.z);
- p = bb.min; p.x = bb.max.x; p.y = bb.max.y; V3MulPointByMatrix(&p,m);
- b->min.x = MIN(b->min.x,p.x); b->min.y = MIN(b->min.y,p.y); b->min.z = MIN(b->min.z,p.z);
- b->max.x = MAX(b->max.x,p.x); b->max.y = MAX(b->max.y,p.y); b->max.z = MAX(b->max.z,p.z);
-
- p = bb.max; V3MulPointByMatrix(&p,m);
- b->min.x = MIN(b->min.x,p.x); b->min.y = MIN(b->min.y,p.y); b->min.z = MIN(b->min.z,p.z);
- b->max.x = MAX(b->max.x,p.x); b->max.y = MAX(b->max.y,p.y); b->max.z = MAX(b->max.z,p.z);
- p = bb.max; p.x = bb.min.x; V3MulPointByMatrix(&p,m);
- b->min.x = MIN(b->min.x,p.x); b->min.y = MIN(b->min.y,p.y); b->min.z = MIN(b->min.z,p.z);
- b->max.x = MAX(b->max.x,p.x); b->max.y = MAX(b->max.y,p.y); b->max.z = MAX(b->max.z,p.z);
- p = bb.max; p.y = bb.min.y; V3MulPointByMatrix(&p,m);
- b->min.x = MIN(b->min.x,p.x); b->min.y = MIN(b->min.y,p.y); b->min.z = MIN(b->min.z,p.z);
- b->max.x = MAX(b->max.x,p.x); b->max.y = MAX(b->max.y,p.y); b->max.z = MAX(b->max.z,p.z);
- p = bb.max; p.x = bb.min.x; p.y = bb.min.y; V3MulPointByMatrix(&p,m);
- b->min.x = MIN(b->min.x,p.x); b->min.y = MIN(b->min.y,p.y); b->min.z = MIN(b->min.z,p.z);
- b->max.x = MAX(b->max.x,p.x); b->max.y = MAX(b->max.y,p.y); b->max.z = MAX(b->max.z,p.z);
- }
-
- static void cylinder_preprocess(grid,un,vn,c,bb,b)
- Surface_Grid_structure *grid;
- int un,vn;
- Cylinder *c;
- Box3 *bb,*b;
- {
- Vector3 dir;
- Matrix4 m,m1;
- double du=1.0/un,dv=1.0/vn,area;
- int i,j,n;
-
- /* Compute derived data */
- c->height = V3DistanceBetween2Points(&(c->base_point1),&(c->base_point2));
- /* Compute Transformations */
- V3Sub(&(c->base_point2),&(c->base_point1),&dir); V3Normalize(&dir);
- translate(-c->base_point1.x,-c->base_point1.y,-c->base_point1.z,&m);
- align_axis_to_Z(&dir,&m1);
- V3MatMul(&m,&m1,&(c->world_to_object));
- align_Z_to_axis(&dir,&m);
- translate(c->base_point1.x,c->base_point1.y,c->base_point1.z,&m1);
- V3MatMul(&m,&m1,&(c->object_to_world));
-
- /* Compute Bounding Box */
- bb->min.x = bb->min.y = -c->radius; bb->min.z = 0.;
- bb->max.x = bb->max.y = c->radius; bb->max.z = c->height;
- bound_transform(bb,&(c->object_to_world));
- update_scene_bound(bb,b);
- /* Compute Area of the Grid Elements */
- area = 2.*PI*du*c->radius*c->height*dv;
- for(n=0,i=0;i<vn;i++)
- for(j=0;j<un;j++,n++)
- grid[n].area=area;
- }
-
- static void cone_preprocess(grid,un,vn,c,bb,b)
- Surface_Grid_structure *grid;
- int un,vn;
- Cone *c;
- Box3 *bb,*b;
- {
- Point3 origin;
- Matrix4 m,m1,m2,m3;
- double H1,H2,tan_theta;
- double v,du=1.0/un,dv=1.0/vn,mult;
- int i,j,n;
-
- /* Make sure 0 <= apex_radius <= base_radius. */
- if (c->apex_radius > c->base_radius){
- /* interchange */
- Point3 p;
- double r;
- p=c->base_point; c->base_point = c->apex_point; c->apex_point = p;
- r=c->base_radius;c->base_radius=c->apex_radius; c->apex_radius= r;
- }
-
- /* Compute derived data */
- H1 = V3DistanceBetween2Points(&(c->base_point),&(c->apex_point));
- tan_theta = (c->base_radius-c->apex_radius)/H1;
- H2 = c->apex_radius/tan_theta;
- c->distance = H2/(H1+H2);
- V3Sub(&(c->base_point),&(c->apex_point),&(c->axis)); V3Normalize(&(c->axis));
-
- /* Compute Transformations */
- origin.x = c->apex_point.x - H2*c->axis.x;
- origin.y = c->apex_point.y - H2*c->axis.y;
- origin.z = c->apex_point.z - H2*c->axis.z;
- translate(-origin.x,-origin.y,-origin.z,&m);
- align_axis_to_Z(&(c->axis),&m1);
- scale(1./c->base_radius,1./c->base_radius,1./(H1+H2),&m2);
- V3MatMul(&m,&m1,&m3);V3MatMul(&m3,&m2,&(c->world_to_object));
-
- scale(c->base_radius,c->base_radius,(H1+H2),&m);
- align_Z_to_axis(&(c->axis),&m1);
- translate(origin.x,origin.y,origin.z,&m2);
- V3MatMul(&m,&m1,&m3);V3MatMul(&m3,&m2,&(c->object_to_world));
-
- /* Compute Bounding Box */
- bb->min.x = bb->min.y = -1.; bb->min.z = c->distance;
- bb->max.x = bb->max.y = bb->max.z = 1.;
- bound_transform(bb,&(c->object_to_world));
- update_scene_bound(bb,b);
-
- /* Compute Area of the Grid Elements */
- mult = PI*du*sqrt((c->base_radius-c->apex_radius)*(c->base_radius-c->apex_radius)+H1*H1);
- for(n=0,v=0.0,i=0;i<vn;i++,v+=dv){
- double area=mult*((c->base_radius-c->apex_radius)*((v+dv)*(v+dv)-v*v)+2.0*c->apex_radius*dv);
- for(j=0;j<un;j++,n++)
- grid[n].area=area;
- }
- }
-
- static void ring_preprocess(grid,un,vn,r,bb,b)
- Surface_Grid_structure *grid;
- int un,vn;
- Ring *r;
- Box3 *bb,*b;
- {
- Matrix4 m,m1;
- double extent;
- double v,du=1.0/un,dv=1.0/vn,mult;
- int i,j,n;
-
- if (r->inner_radius > r->outer_radius){
- double rad = r->outer_radius;
- r->outer_radius = r->inner_radius;
- r->inner_radius = rad;
- }
- V3Normalize(&(r->normal));
-
- /* Compute Transformations */
- translate(-r->center.x,-r->center.y,-r->center.z,&m);
- align_axis_to_Z(&(r->normal),&m1);
- V3MatMul(&m,&m1,&(r->world_to_object));
-
- align_Z_to_axis(&(r->normal),&m);
- translate(r->center.x,r->center.y,r->center.z,&m1);
- V3MatMul(&m,&m1,&(r->object_to_world));
-
- /* Compute Bounding Box */
- extent = r->outer_radius * sqrt(1. - r->normal.x*r->normal.x);
- bb->min.x = r->center.x - extent;
- bb->max.x = r->center.x + extent;
-
- extent = r->outer_radius * sqrt(1. - r->normal.y*r->normal.y);
- bb->min.y = r->center.y - extent;
- bb->max.y = r->center.y + extent;
-
- extent = r->outer_radius * sqrt(1. - r->normal.z*r->normal.z);
- bb->min.z = r->center.z - extent;
- bb->max.z = r->center.z + extent;
- update_scene_bound(bb,b);
- /* Compute Area of the Grid Elements */
- mult = PI*du*(r->outer_radius*r->outer_radius - r->inner_radius*r->inner_radius);
- for(n=0,v=0.0,i=0;i<vn;i++,v+=dv){
- double area=mult*((v+dv)*(v+dv)-v*v);
- for(j=0;j<un;j++,n++)
- grid[n].area=area;
- }
- }
-
- static void polygon_preprocess(grid,un,vn,p,bb,b)
- Surface_Grid_structure *grid;
- int un,vn;
- Polygon *p;
- Box3 *bb,*b;
- {
- int i,j;
- Point3 *point=p->vertex_list;
- /* Compute derived data */
- /* Normal by Newels Method */
- p->plane_normal.x = p->plane_normal.y = p->plane_normal.z = 0.;
- for(i=0,j=1;i<p->nvertices;i++,j++){
- if (j==p->nvertices)j=0;
- p->plane_normal.x += (point[i].y - point[j].y)*(point[i].z+point[j].z);
- p->plane_normal.y += (point[i].z - point[j].z)*(point[i].x+point[j].x);
- p->plane_normal.z += (point[i].x - point[j].x)*(point[i].y+point[j].y);
- }
- V3Normalize(&(p->plane_normal));
- p->plane_constant = -V3Dot(&(p->plane_normal),point);
- p->dominant_axis_flag = get_dominant_axis(&(p->plane_normal));
- align_Z_to_axis(&(p->plane_normal),&(p->local_trans));
- /* Compute Bounding Box */
- bb->min = bb->max = *point;
- for(i=1;i<p->nvertices;i++){
- bb->min.x = MIN(bb->min.x,point[i].x);
- bb->max.x = MAX(bb->max.x,point[i].x);
- bb->min.y = MIN(bb->min.y,point[i].y);
- bb->max.y = MAX(bb->max.y,point[i].y);
- bb->min.z = MIN(bb->min.z,point[i].z);
- bb->max.z = MAX(bb->max.z,point[i].z);
- }
- update_scene_bound(bb,b);
- /* Compute Area of the Grid Elements */
- if (un > 1 || vn > 1)
- error("Does not know any way to grid arbitrary polygon.");
- grid[0].area=
- trapez_area(p->nvertices,p->vertex_list,&(p->plane_normal),p->dominant_axis_flag);
- }
- #undef update_scene_bound
- /************** End Object Specific Preprocess **************/
- /************** Begin Object Specific Input **************/
- /*
- for quadrilateral
- P00
- P10
- P11
- P01 (Vertices Counter Clockwise)
- for sphere and bubble
- centre
- radius
- for cylinder and tube
- base point1
- base point2
- radius
- for cone and cup
- apex point
- apex radius
- base point
- base radius
- for ring
- center
- normal
- inner radius
- outer radius
- for polygon
- number of vertices
- vertices
- .
- .
- for others
- nill
- */
- static void *quadrilateral_input()
- {
- Quadrilateral *q=(Quadrilateral *)malloc(sizeof(Quadrilateral));
-
- if (q==NULL)error("Cannot allocate Quadrilateral.");
- scanf("%lf%lf%lf",&(q->P00.x),&(q->P00.y),&(q->P00.z));
- scanf("%lf%lf%lf",&(q->P10.x),&(q->P10.y),&(q->P10.z));
- scanf("%lf%lf%lf",&(q->P11.x),&(q->P11.y),&(q->P11.z));
- scanf("%lf%lf%lf",&(q->P01.x),&(q->P01.y),&(q->P01.z));
-
- return((void *)q);
- }
-
- static void *polygon_input()
- {
- int i;
- Point3 *point;
- Polygon *p=(Polygon *)malloc(sizeof(Polygon));
-
- if (p==NULL)error("Cannot allocate Polygon.");
- scanf("%d",&(p->nvertices));
- point = p->vertex_list = (Point3 *)malloc(sizeof(Point3) * p->nvertices);
- if (point == NULL) error("cannot allocate Polygon Vertices.");
- for (i=0; i < p->nvertices; i++,point++)
- scanf("%lf%lf%lf",&(point->x),&(point->y),&(point->z));
- return((void *)p);
- }
-
- static void *sphere_input()
- {
- Sphere *s=(Sphere *)malloc(sizeof(Sphere));
-
- if (s==NULL)error("Cannot allocate Sphere.");
- scanf("%lf%lf%lf",&(s->center.x),&(s->center.y),&(s->center.z));
- scanf("%lf",&(s->radius));
-
- return((void *)s);
- }
-
- static void *cylinder_input()
- {
- Cylinder *c=(Cylinder *)malloc(sizeof(Cylinder));
-
- if (c==NULL)error("Cannot allocate Cylinder/Tube.");
- scanf("%lf%lf%lf",&(c->base_point1.x),&(c->base_point1.y),&(c->base_point1.z));
- scanf("%lf%lf%lf",&(c->base_point2.x),&(c->base_point2.y),&(c->base_point2.z));
- scanf("%lf",&(c->radius));
-
- return((void *)c);
- }
-
-
- static void *cone_input()
- {
- Cone *c=(Cone *)malloc(sizeof(Cone));
-
- if (c==NULL)error("Cannot allocate Cone/Cup.");
- scanf("%lf%lf%lf%lf",&(c->apex_point.x),&(c->apex_point.y),&(c->apex_point.z),
- &(c->apex_radius));
- scanf("%lf%lf%lf%lf",&(c->base_point.x),&(c->base_point.y),&(c->base_point.z),
- &(c->base_radius));
-
- return((void *)c);
- }
-
- static void *ring_input()
- {
- Ring *r=(Ring *)malloc(sizeof(Ring));
-
- if (r==NULL)error("Cannot allocate Ring.");
- scanf("%lf%lf%lf",&(r->center.x),&(r->center.y),&(r->center.z));
- scanf("%lf%lf%lf",&(r->normal.x),&(r->normal.y),&(r->normal.z));
- scanf("%lf%lf",&(r->inner_radius),&(r->outer_radius));
-
- return((void *)r);
- }
-
- static void *no_input()
- {
- error("This type Not implemented.");
- }
-
- /************** End Object Specific Input **************/
- /************** Begin Object Specific Normal **************/
-
- static Vector3 quadrilateral_normal(q,u,v)
- Quadrilateral *q;
- double u,v;
- {
- return(q->plane_normal);
- }
-
- static Vector3 polygon_normal(p,u,v)
- Polygon *p;
- double u,v;
- {
- return(p->plane_normal);
- }
-
- static Vector3 sphere_normal(s,u,v)
- Sphere *s;
- double u,v;
- {
- Vector3 N;
- double phi = u * 2. * PI;
- double theta = v * PI;
- double sin_theta = sin(theta);
-
- N.x = sin_theta*cos(phi);
- N.y = sin_theta*sin(phi);
- N.z = cos(theta);
-
- return(N);
- }
-
- static Vector3 bubble_normal(s,u,v)
- Sphere *s;
- double u,v;
- {
- Vector3 N;
-
- N=sphere_normal(s,u,v);
- V3Negate(&N);
-
- return(N);
- }
-
- static Vector3 cylinder_normal(c,u,v)
- Cylinder *c;
- double u,v;
- {
- Vector3 N;
- double phi = u * 2. * PI;
-
- N.x = cos(phi);
- N.y = sin(phi);
- N.z = 0.;
- N = transform_vector(&N,&(c->object_to_world));
-
- return(N);
- }
-
- static Vector3 tube_normal(c,u,v)
- Cylinder *c;
- double u,v;
- {
- Vector3 N;
-
- N=cylinder_normal(c,u,v);
- V3Negate(&N);
-
- return(N);
- }
-
- static Vector3 cone_normal(c,u,v)
- Cone *c;
- double u,v;
- {
- Vector3 N,v1,v2;
- double phi = u * 2. * PI;
-
- v1.x = cos(phi); v1.y = sin(phi); v1.z = 1.;
- v1 = transform_vector(&v1,&(c->object_to_world));
- V3Cross(&v1,&(c->axis),&v2);
- V3Cross(&v1,&v2,&N);
- V3Normalize(&N);
-
- return(N);
- }
-
- static Vector3 cup_normal(c,u,v)
- Cone *c;
- double u,v;
- {
- Vector3 N;
-
- N=cone_normal(c,u,v);
- V3Negate(&N);
-
- return(N);
- }
-
- static Vector3 ring_normal(r,u,v)
- Ring *r;
- double u,v;
- {
- return(r->normal);
- }
-
- static Vector3 no_normal(s,u,v)
- void *s;
- double u,v;
- {
- error("No Normal Yet.");
- }
-
- /************** End Object Specific Normal **************/
- /************** Begin Object Specific Local Matrix ************/
-
- static Matrix4 quadrilateral_matrix(N,q)
- Vector3 *N;
- Quadrilateral *q;
- {
- return(q->local_trans);
- }
-
-
- static Matrix4 polygon_matrix(N,p)
- Vector3 *N;
- Polygon *p;
- {
- return(p->local_trans);
- }
-
- static Matrix4 align_matrix(N,s)
- Vector3 *N;
- void *s;
- {
- Matrix4 m;
-
- align_Z_to_axis(N,&m);
-
- return(m);
- }
-
- static Matrix4 ring_matrix(N,r)
- /*
- CAUTION: This matrix also has a nonzero translation vector.
- */
- Vector3 *N;
- Ring *r;
- {
- return(r->object_to_world);
- }
-
- static Matrix4 no_matrix(N,s)
- Vector3 *N;
- void *s;
- {
- error("No Matrix Yet.");
- }
-
- /************** End Object Specific Local Matrix ************/
- /************** Begin Object Specific Area Sampling ***********/
-
- static Point3 sphere_point(s,u,v)
- Sphere *s;
- double u,v;
- {
- Point3 p;
- double R =s->radius;
- Point3 C;
- C =s->center;
- p.x = R*sin(PI*v)*cos(2.*PI*u);
- p.y = R*sin(PI*v)*sin(2.*PI*u);
- p.z = R*cos(PI*v);
- V3Add(&p,&C,&p);
- return(p);
- }
-
- static Point3 cylinder_point(c,u,v)
- Cylinder *c;
- double u,v;
- {
- Point3 p;
- double R = c->radius;
- double H = c->height;
- double phi = 2.*PI*u;
- p.x = R*cos(phi);
- p.y = R*sin(phi);
- p.z = v*H;
- V3MulPointByMatrix(&p,&(c->object_to_world));
- return(p);
- }
- static Point3 cone_point(c,u,v)
- Cone *c;
- double u,v;
- {
- Point3 posn;
- double phi=u * 2. * PI;
- Point3 p;
- p.z = (1.-c->distance)*v+c->distance;
- p.x = p.z * cos(phi); p.y = p.z * sin(phi);
- V3MulPointByMatrix(&p,&(c->object_to_world));
- return(p);
- }
- static Point3 ring_point(r,u,v)
- Ring *r;
- double u,v;
- {
- Point3 p;
- double radius=r->inner_radius+
- v*(r->outer_radius-r->inner_radius);
- double phi=2. * u * PI;
- p.x = radius * cos(phi); p.y = radius * sin(phi); p.z = 0.;
- V3MulPointByMatrix(&p,&(r->object_to_world));
- return(p);
- }
- static Point3 triangle_point(p,u,v)
- Point3 *p;
- double u,v;
- {
- Point3 posn;
- posn.x = p[0].x + (1.-v)*u*(p[1].x-p[0].x)+ v*(p[2].x-p[0].x);
- posn.y = p[0].y + (1.-v)*u*(p[1].y-p[0].y)+ v*(p[2].y-p[0].y);
- posn.z = p[0].z + (1.-v)*u*(p[1].z-p[0].z)+ v*(p[2].z-p[0].z);
- return(posn);
- }
- static Point3 polygon_point(p,u,v)
- Polygon *p;
- double u,v;
- {
- return(p->vertex_list[0]); /* Arbitrary */
- }
- static Point3 no_object_point(p,u,v)
- void *p;
- double u,v;
- {
- error("Cannot compute point for this object.");
- }
- /************** End Object Specific Area Sampling ***********/
-
- /************** Begin Grid Centre Point ***********/
- #define get_U ((uindex+0.5) * 1./object[n].grid_h_reso)
- #define get_V ((vindex+0.5) * 1./object[n].grid_v_reso)
- static Point3 quadrilateral_grid_centre_point(n,vindex,uindex)
- int n;
- int vindex,uindex;
- {
- double u = get_U;
- double v = get_V;
- return(get_bilinear(object[n].object_specific_structure,u,v));
- }
- static Point3 sphere_grid_centre_point(n,vindex,uindex)
- int n;
- int vindex,uindex;
- {
- double u = get_U;
- double v = get_V;
- return(sphere_point(object[n].object_specific_structure,u,v));
- }
- static Point3 cylinder_grid_centre_point(n,vindex,uindex)
- int n;
- int vindex,uindex;
- {
- double u = get_U;
- double v = get_V;
- return(cylinder_point(object[n].object_specific_structure,u,v));
- }
- static Point3 cone_grid_centre_point(n,vindex,uindex)
- int n;
- int vindex,uindex;
- {
- double u = get_U;
- double v = get_V;
- return(cone_point(object[n].object_specific_structure,u,v));
- }
- static Point3 ring_grid_centre_point(n,vindex,uindex)
- int n;
- int vindex,uindex;
- {
- double u = get_U;
- double v = get_V;
- return(ring_point(object[n].object_specific_structure,u,v));
- }
- static Point3 polygon_grid_centre_point(n,vindex,uindex)
- int n;
- int vindex,uindex;
- {
- Polygon *p=(Polygon *)object[n].object_specific_structure;
- if (p->nvertices==3){/* Triangle */
- double u = get_U;
- double v = get_V;
- return(triangle_point(p->vertex_list,u,v));
- }
- else /* We donot have a parameterisation method for
- arbitrary polygon. So I can send any point
- on the surface. */
- return(p->vertex_list[0]);
- }
- static Point3 no_grid_centre_point(n,vindex,uindex)
- int n;
- int vindex,uindex;
- {
- error("Grid center Point Not Implemented.");
- }
- #undef get_U
- #undef get_V
- /************** End Grid Centre Point ***********/
-
- ObjectFunctions ofunc[MAX_GEOMETRY_TYPE]={
- /*
- NOTE : Each of the Normal routines must return Normalized Vectors.
- */
- {
- quadrilateral_input,
- quadrilateral_normal,
- intersect_quadrilateral,
- quadrilateral_preprocess,
- quadrilateral_matrix,
- quadrilateral_grid_centre_point,
- get_bilinear
- },
- {
- sphere_input,
- sphere_normal,
- intersect_sphere,
- sphere_preprocess,
- align_matrix,
- sphere_grid_centre_point,
- sphere_point
- },
- {
- sphere_input,
- bubble_normal,
- intersect_bubble,
- sphere_preprocess,
- align_matrix,
- sphere_grid_centre_point,
- sphere_point
- },
- {
- cylinder_input,
- cylinder_normal,
- intersect_cylinder,
- cylinder_preprocess,
- align_matrix,
- cylinder_grid_centre_point,
- cylinder_point
- },
- {
- cylinder_input,
- tube_normal,
- intersect_tube,
- cylinder_preprocess,
- align_matrix,
- cylinder_grid_centre_point,
- cylinder_point,
- },
- {
- cone_input,
- cone_normal,
- intersect_cone,
- cone_preprocess,
- align_matrix,
- cone_grid_centre_point,
- cone_point
- },
- {
- cone_input,
- cup_normal,
- intersect_cup,
- cone_preprocess,
- align_matrix,
- cone_grid_centre_point,
- cone_point
- },
- {
- ring_input,
- ring_normal,
- intersect_ring,
- ring_preprocess,
- ring_matrix,
- ring_grid_centre_point,
- ring_point
- },
- {
- polygon_input,
- polygon_normal,
- intersect_polygon,
- polygon_preprocess,
- polygon_matrix,
- polygon_grid_centre_point,
- polygon_point
- },
- {
- no_input,
- no_normal,
- intersect_other_geometry,
- null_preprocess,
- no_matrix,
- no_grid_centre_point,
- no_object_point
- }
- };
- #undef get_V
- #undef get_U
- #undef update_scene_bound
-