home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / graphtal / sphere.c < prev    next >
C/C++ Source or Header  |  1992-10-22  |  3KB  |  146 lines

  1. /*
  2.  * Sphere.C - methods for sphere manipulations.
  3.  *
  4.  * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  */
  17.  
  18. #include "Sphere.h"
  19.  
  20. //___________________________________________________________ Sphere
  21.  
  22. Sphere::Sphere(real radius, const Vector& position)
  23. : r(radius), center(position)
  24. {
  25.   rsqr = r*r;
  26. }
  27.  
  28. GeoObject* Sphere::create(real radius, const Vector& position)
  29. {
  30.   if (radius < EPSILON)
  31.     return NULL;
  32.  
  33.   return new Sphere(radius, position);
  34. }
  35.  
  36. /*
  37.  * Compute the intersection between a ray and a sphere.
  38.  * This algorithm is adapted from Craig Colbs rayshade.
  39.  */
  40.  
  41. int Sphere::intersect(const Ray& ray, real minDist, real& maxDist) 
  42. {
  43.   real xadj, yadj, zadj;
  44.   real b, t, s;
  45.  
  46.   intersectionTests++;
  47.  
  48.   /*
  49.    * Translate ray origin to object space and negate everything.
  50.    * (Thus, we translate the sphere into ray space, which saves
  51.    * us a couple of negations below.)
  52.    */
  53.   xadj = center[0] - ray.getOrig()[0];
  54.   yadj = center[1] - ray.getOrig()[1];
  55.   zadj = center[2] - ray.getOrig()[2];
  56.  
  57.   /*
  58.    * Solve quadratic equation.
  59.    */
  60.   b = xadj*ray.getDir()[0] + yadj*ray.getDir()[1] + zadj*ray.getDir()[2];
  61.   t = b*b - xadj*xadj - yadj*yadj - zadj*zadj + rsqr;
  62.   if (t < 0.) 
  63.     return FALSE;
  64.  
  65.   t = sqrt(t);
  66.  
  67.   /*
  68.    * we may hit the sphere twice, test both cases
  69.    */
  70.   s = b - t;
  71.   if (s > minDist) {
  72.     if (s < maxDist) {
  73.       maxDist = s;
  74.       return TRUE;
  75.     }
  76.     return FALSE;
  77.   }
  78.  
  79.   s = b + t;
  80.   if (s > minDist && s < maxDist) {
  81.     maxDist = s;
  82.     intersections++;
  83.     return TRUE;
  84.   }
  85.   return FALSE;
  86. }
  87.  
  88. /*
  89.  * Compute sphere normal.
  90.  */
  91.  
  92. Vector Sphere::normal(const Vector& p) const
  93. {
  94.   return (p-center)/r;
  95. }
  96.  
  97. /*
  98.  * tesselate splits the sphere into polygons.
  99.  */
  100.  
  101. PolygonList* Sphere::tesselate(const BoundingBox&)
  102. {
  103.   PolygonList* polys = tesselate(center, r, 10);
  104.  
  105.   if (trans != NULL) {
  106.     for (register long i=0; i<polys->count(); i++)
  107.       polys->item(i)->transform(*trans);
  108.   }
  109.    
  110.   return polys;
  111. }
  112.  
  113. /*
  114.  * General sphere tesselation.
  115.  */
  116.  
  117. PolygonList* Sphere::tesselate(const Vector& pos, real r, int res)
  118. {
  119.   real delta = M_PI/res;
  120.   PolygonList* polySphere = new PolygonList(3*res);
  121.   Vector A, B, C, D;
  122.  
  123.   for (real alpha=0; alpha < 2*M_PI; alpha += delta) {
  124.     A = B = Vector(0,0,-r)+pos;
  125.     for (real beta=-M_PI_2+delta; beta<=M_PI_2-delta; beta += delta) {
  126.       C = computeSurfacePoint(alpha+delta, beta)*r+pos;
  127.       D = computeSurfacePoint(alpha, beta)*r+pos;
  128.       if (A==B)
  129.     polySphere->append(new Polygon(A, C, D));
  130.       else
  131.     polySphere->append(new Polygon(A, B, C, D));
  132.       A=D; B=C;
  133.     }
  134.     polySphere->append(new Polygon(A, B, Vector(0,0,r)+pos));
  135.   }
  136.   return polySphere;
  137. }
  138.  
  139. Vector Sphere::computeSurfacePoint(real alpha, real beta)
  140. {
  141.   real sin_a, cos_a, sin_b, cos_b;
  142.   SinCos(alpha, sin_a, cos_a);
  143.   SinCos(beta, sin_b, cos_b);
  144.   return Vector(cos_a*cos_b, sin_a*cos_b, sin_b);
  145. }
  146.