[comp.graphics] Ray-tracing code for 3-d quadratic objects

prem@geomag.fsu.edu (Prem Subrahmanyam) (03/06/90)

   Here is the code I wrote in C for doing 3-dimensional quadratics.
   the derivations are rather complex, so I tried to comment the code
   as best I could, but that's all I could do.  I hope people find
   this interesting.
   ---Prem Subrahmanyam (prem@geomag.gly.fsu.edu)


#define TINY (float)1e-3

int hitconic(offset,eye,v,p,t,a,b,c,d,e,f,g,start,stop)

/* offset is the triple representing where the conic is to be moved */
/* from 0,0,0. */
/* eye and v represent the ray, with eye being the start point and v */
/* being the direction vector */
/* p is the point into which the intersection point value will be */
/* copied */
/* t is the value into which the line parameter will be copied for the */
/* ray. */
/* a,b,c,d,e,f,g are values for the 3-dimensional quadratic equation */
/* a*x^2 + b*y^2 + c*z^2 + d*x + e*y + f*z = g */
/* start and stop represent the bounds (when the equation is centered 
   at 0,0,0) in which to test the conic */
   /* example: if the bound around a conic were set at -1,-1,-1 to 1,1,1
      and the offset was 4,5,6 then the actual spatial extent of the
      object would be from 3,4,5 to 5,6,7 . */
/* So, the conic (3-d quadratic) should contain within its own data
   structure the offset, extent values (start,stop), and a,b,c,d,e,f,g
   constants */

vector offset,
       eye,
       v,
       p;
	   
float     *t,
           a,
           b,
	   c,
	   d,
	   e,
	   f,
	   g;
	   
vector start,
       stop; 

    { 
    /*************************************************/
    /* this code is a little messy, but it does work */
    /*************************************************/

      /* create some local points to use in testing */
      vector m,p2;  
      float radical,Ay,Be,Ce,t1,t2; /* constants for quadratic formula */
      /* generated for solving for the intersection of the equations for
	 the line and the equation for the quadratic */
      /* subtract offset from the ray start position to align ray and
	 quadratic*/
      m[0] = eye[0] - offset[0];
      m[1] = eye[1] - offset[1];
      m[2] = eye[2] - offset[2];

      /* Now, using the constant values, create values for the intersection
	 test formula */ 
      Ay = (a*v[0]*v[0]) + (b*v[1]*v[1]) + (c*v[2]*v[2]);
      Be = (2*a*m[0]*v[0]) + (2*b*m[1]*v[1]) + (2*c*m[2]*v[2]) + (d*v[0]) + (e*v[1]) + (f*v[2]);
      Ce = (a*m[0]*m[0]) + (b*m[1]*m[1]) + (c*m[2]*m[2]) + (d*m[0]) + (e*m[1]) + (f*m[2]) - g;
      radical = ((Be*Be) - (4*Ay*Ce));
      if (radical < 0.0) {
         return FALSE;
      }
      t1 = ((-1*Be) + sqrt(radical))/(2*Ay);
      t2 = ((-1*Be) - sqrt(radical))/(2*Ay);

   /* immediately eliminate cases in which return is false */
      if (((t1 < 0)&&(t2 < 0))||((t1 < 0)&&(fabs(t2) < TINY))||((t2 < 0)&&(fabs(t1) < TINY))||((fabs(t1) < TINY)&&(fabs(t2) < TINY)))
      {
	 return FALSE;
      }else{
	 /* t1 a bad parameter, but t2 may not be */
	 if ((t1 < 0)||(fabs(t1) < TINY)) {
	   if (!(fabs(t2) < TINY)) /* prevent spurious self-shadowing */ 
	   {
	     /* using the parameter, find the point of intersection */
	     p[0] = m[0] + v[0]*t2;
	     p[1] = m[1] + v[1]*t2;
	     p[2] = m[2] + v[2]*t2;
	     /* test to see if the point is within the bounds for the
	     quadratic section */
	     if ((start[0] <= p[0])&&(stop[0] >= p[0])&&(start[1] <= p[1])&&(stop[1] >= p[1])&&(start[2] <= p[2])&&(stop[2] >= p[2]))
	     {
	       /* if it lies within the bounds, add offset back on and return
		  point */
		p[0] = p[0] + offset[0];
		p[1] = p[1] + offset[1];
		p[2] = p[2] + offset[2];
		*t = t2;
		return TRUE;
	     } else { /* point does not lie within the bounds */
		return FALSE;
	     }
	   }else{ /* t2 a bad parameter as well */
	     return FALSE;
	   }
	 }
	     
	 if ((t2 < 0)||(fabs(t2) < TINY)) {
	 /* t2 a false parameter, so test to see if t1 is good */
           if(!(fabs(t1) < TINY))
	   { /* find point by parameter */
	     p[0] = m[0] + v[0]*t1;
	     p[1] = m[1] + v[1]*t1;
	     p[2] = m[2] + v[2]*t1;
	     if ((start[0] <= p[0])&&(stop[0] >= p[0])&&(start[1] <= p[1])&&(stop[1] >= p[1])&&(start[2] <= p[2])&&(stop[2] >=p[2]))
	     { /* same as above, see if point lies within bounds */
		p[0] = p[0] + offset[0];
		p[1] = p[1] + offset[1];
		p[2] = p[2] + offset[2];
		*t = t1;
		return TRUE;
	     } else {
		return FALSE;
	     }
	   }else{
		return FALSE;
	   }
	 }
	 /* if the program has gotten here, t1 and t2 are greater than 0 */
         /* and greater than TINY */
         p[0] = m[0] + v[0]*t1;
	 p[1] = m[1] + v[1]*t1;
	 p[2] = m[2] + v[2]*t1;
	 
	 p2[0] = m[0] + v[0]*t2;
	 p2[1] = m[1] + v[1]*t2;
	 p2[2] = m[2] + v[2]*t2;
 
	 /* see if the first point is within bounds */
	 if ((start[0] <= p[0])&&(stop[0] >= p[0])&&(start[1] <= p[1])&&(stop[1] >= p[1])&&(start[2] <= p[2])&&(stop[2] >=p[2]))
         { /* now, see if second point is as well */
	     if ((start[0] <= p2[0])&&(stop[0] >= p2[0])&&(start[1] <= p2[1])&&(stop[1] >= p2[1])&&(start[2] <= p2[2])&&(stop[2] >=p2[2]))
             {  /* both points are within bbox */
		if (t1 <= t2) /*see which one is smaller */
		{ /* t1 yields a closer point */
		    *t = t1;
		    p[0] = p[0] + offset[0];
		    p[1] = p[1] + offset[1];
		    p[2] = p[2] + offset[2];
		    return TRUE;
		} else {
		 /* t2 yields a closer point */
		    *t = t2;
		    p[0] = p2[0] + offset[0];
		    p[1] = p2[1] + offset[1];
		    p[2] = p2[2] + offset[2];
                    return TRUE;
		}
	     } else { /* second point not within box */
		*t = t1;
		p[0] = p[0] + offset[0];
		p[1] = p[1] + offset[1];
		p[2] = p[2] + offset[2];
		return TRUE;
	     }
	 } else { /* t1 not within bbox */
	    if ((start[0] <= p2[0])&&(stop[0] >= p2[0])&&(start[1] <= p2[1])&&(stop[1] >= p2[1])&&(start[2] <= p2[2])&&(stop[2] >=p2[2]))
	    { /* see if t2 is within bbox */
		*t = t2;
		p[0] = p2[0] + offset[0];
		p[1] = p2[1] + offset[1];
		p[2] = p2[2] + offset[2];
		return TRUE;
	    } else { /* neither is within bounding box */
		return FALSE;
	    }
	}
      }   
 }


/* HERE IS THE PORTION OF THE CODE THAT RETURNS THE NORMAL TO THE 
   QUADRATIC */ 
void findnormal(np,p,n) 
   node       *np;
   vector       p,
       n;
/* np is the pointer to the object node, p is the point of intersection,
   and n is the normal vector returned */
  {
    vector point;
    switch (np->kind) {
       /* conic section a la Prem */
       case CONIC    : point[0] = p[0] - cptr(np)->offset[0];
                       point[1] = p[1] - cptr(np)->offset[1];
		       point[2] = p[2] - cptr(np)->offset[2];
		       n[0] = 2.0*cptr(np)->a*point[0] + cptr(np)->d;
		       n[1] = 2.0*cptr(np)->b*point[1] + cptr(np)->e;
		       n[2] = 2.0*cptr(np)->c*point[2] + cptr(np)->f;
                       normalize(n);
		       break;
       }

Susan.King@f270.n106.z1.fidonet.org (Susan King) (03/12/90)

 > 
 > From: tom@hp-ptp.HP.COM (Tom_Balon)
 > Date: 2 Mar 90 23:04:26 GMT
 > Organization: HP Pacific Technology Park - Sunnyvale, Ca.
 > Message-ID: <1580005@hp-ptp.HP.COM>
 > Newsgroups: comp.graphics
 > 
 > 
 > 
 > 
 >         I looking for information on computer animation. I know
 > there
 >         are a few companies in the Bay Area that are involved
 > with
 >         animation ( Pixar, Industrial Light and Magic ). What
 > I'm looking
 >         for is any information on software packages for creating
 > animated
 >         sequences. I'm also looking for any good books on graphics/animation.
 > 
 >         I'm interested in software for DOS (386) machines, HP
 > or Apollo 
 >         workstations. Also, if anyone knows any names of other
 > companies
 >         in the bay area involved with computer animation, that
 > would be
 >         helpful too. Any help would be appreciated.
 > 
 > 
 >                                                 tom
 > 
 >                                                 tom@hpdsla.HP.COM

 
Tom, we have been successfully doing some animation sequences which 
we have outputed on both disk and video.
 
We are using a program called GRASP that works very nicely on a 386 
machine.
 
We have used screen captures from CAD to bring in the basic drawings.. 
rendered them in a paint program like Colorix or PC Paintbrush Plus...
and then used GRASP to animate... 
 
The results have been great!

bdb@becker.UUCP (Bruce Becker) (03/16/90)

In article <1580005@hp-ptp.HP.COM> tom@hp-ptp.HP.COM (Tom_Balon) writes:
|
| I looking for information on computer animation. I know there
| are a few companies in the Bay Area that are involved with
| animation ( Pixar, Industrial Light and Magic ). What I'm looking
| for is any information on software packages for creating animated
| sequences. I'm also looking for any good books on graphics/animation.
| I'm interested in software for DOS (386) machines, HP or Apollo
| workstations. Also, if anyone knows any names of other companies
| in the bay area involved with computer animation, that would be
| helpful too. Any help would be appreciated.

	I think you're missing a good bet if you're
	not checking out what's available on Amiga
	systems. There's a very wide range of powerful
	animation software and ancillary support tools
	on this system. A local dealer can give you
	details...

-- 
  (__)	 Bruce Becker	Toronto, Ontario
w \@@/	 Internet: bdb@becker.UUCP, bruce@gpu.utcs.toronto.edu
 `/v/-e	 UUCP: ...!uunet!mnetor!becker!bdb
_/  \_	 "So far from God, so close to the United States" - Old Mexican proverb