Pnt3.h
上传用户:kellyonhid
上传日期:2013-10-12
资源大小:932k
文件大小:28k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. //###############################################################
  2. // Pnt3.h
  3. // Kari Pulli
  4. // 11/08/1996
  5. //###############################################################
  6. #ifndef _pnt3_h
  7. #define _pnt3_h
  8. #include<math.h>
  9. #include<assert.h>
  10. #include<iostream.h>
  11. #ifdef WIN32
  12. #include<float.h>
  13. #endif
  14. #ifdef sgi
  15. #include<ieeefp.h>
  16. #endif
  17. #ifdef sun
  18. #define sqrtf(x) sqrt(x)
  19. #endif
  20. #define SHOW(X) cout << #X " = " << X << endl
  21. class Pnt3 {
  22. protected:
  23.   float v[3];
  24. public: 
  25.   Pnt3(float a=0.0, float b=0.0, float c=0.0) 
  26.     { v[0] = a, v[1] = b, v[2] = c;}
  27.   Pnt3(const float *a)    { v[0] = a[0], v[1] = a[1], v[2] = a[2];}
  28.   Pnt3(const double *a)   { v[0] = a[0], v[1] = a[1], v[2] = a[2];}
  29.   Pnt3 &set(float a=0.0, float b=0.0, float c=0.0) 
  30.     { v[0] = a, v[1] = b, v[2] = c; return *this; }
  31.   Pnt3 &set(const float *a) 
  32.     { v[0] = a[0], v[1] = a[1], v[2] = a[2]; return *this; }
  33.   Pnt3 &set(const double *a)
  34.     { v[0] = a[0], v[1] = a[1], v[2] = a[2]; return *this; }
  35.   
  36.   // linear interpolation
  37.   Pnt3 &lerp(float t, const Pnt3 &a, const Pnt3 &b)
  38.     {
  39.       float u = 1.0 - t;
  40.       v[0]=u*a[0]+t*b[0]; 
  41.       v[1]=u*a[1]+t*b[1]; 
  42.       v[2]=u*a[2]+t*b[2];
  43.       return *this;
  44.     }
  45.   Pnt3 &set_max(const Pnt3 &p)
  46.     { 
  47.       if (p.v[0] > v[0]) v[0] = p.v[0];
  48.       if (p.v[1] > v[1]) v[1] = p.v[1];
  49.       if (p.v[2] > v[2]) v[2] = p.v[2];
  50.       return *this;
  51.     }
  52.   Pnt3 &set_min(const Pnt3 &p)
  53.     { 
  54.       if (p.v[0] < v[0]) v[0] = p.v[0];
  55.       if (p.v[1] < v[1]) v[1] = p.v[1];
  56.       if (p.v[2] < v[2]) v[2] = p.v[2];
  57.       return *this;
  58.     }
  59. #ifdef WIN32
  60.   bool  isfinite(void) { return _finite(v[0]) && _finite(v[1]) && _finite(v[2]); }
  61. #else
  62.   bool  isfinite(void) { return finite(v[0]) && finite(v[1]) && finite(v[2]); }
  63. #endif
  64.   Pnt3  operator-() const       { return Pnt3(-v[0],-v[1],-v[2]); }
  65.   Pnt3& operator+=(const Pnt3 &);
  66.   Pnt3& operator-=(const Pnt3 &);
  67.   Pnt3& operator*=(const float &);
  68.   Pnt3& operator/=(const float &);
  69.   int   operator==(const Pnt3 &);
  70.   int   operator!=(const Pnt3 &);
  71.   operator const float *(void) const   { return v; }
  72.   operator       float *(void)         { return v; }
  73.   operator const char  *(void) const   { return (char *)v; }
  74.   operator       char  *(void)         { return (char *)v; }
  75.   float& operator[](int i)             { return v[i]; }
  76.   const float& operator[](int i) const { return v[i]; }
  77.   friend ostream& operator<<(ostream &out, const Pnt3 &a);
  78.   friend istream& operator>>(istream &in, Pnt3 &a);
  79.   // operators that are not part of class: +,-,*,/
  80.   float         norm(void) const;
  81.   float         norm2(void) const;
  82.   Pnt3 &        normalize(void);
  83.   Pnt3 &        set_norm(float len);
  84.   friend float  dist(const Pnt3 &, const Pnt3 &);
  85.   friend float  dist2(const Pnt3 &, const Pnt3 &);
  86.   friend float  dist_2d(const Pnt3 &, const Pnt3 &);
  87.   friend float  dist2_2d(const Pnt3 &, const Pnt3 &);
  88.   friend float  dist_manhattan(const Pnt3 &, const Pnt3 &);
  89.   friend float  dist2_lineseg(const Pnt3 &, const Pnt3 &, const Pnt3 &);
  90.   friend float  dist2_tri(const Pnt3 &, 
  91.   const Pnt3 &, const Pnt3 &, const Pnt3 &);
  92.   friend bool   closer_on_lineseg(const Pnt3 &, Pnt3 &, 
  93.   const Pnt3 &, 
  94.   const Pnt3 &, float &);
  95.   friend bool   closer_on_tri(const Pnt3 &, Pnt3 &, const Pnt3 &, 
  96.       const Pnt3 &, const Pnt3 &, float &);
  97.   friend float  dot(const Pnt3 &a, const Pnt3 &b);
  98.   friend Pnt3   cross(const Pnt3 &a, const Pnt3 &b);
  99.   friend Pnt3   cross(const Pnt3 &a, const Pnt3 &b,
  100.       const Pnt3 &c);
  101.   friend Pnt3   normal(const Pnt3 &, const Pnt3 &, const Pnt3 &);
  102.   friend float  det(const Pnt3 &, const Pnt3 &, const Pnt3 &);
  103.   friend void   line_plane_X(const Pnt3& p, const Pnt3& dir,
  104.      const Pnt3& t1, const Pnt3& t2,
  105.      const Pnt3& t3,
  106.      Pnt3 &x, float &dist);
  107.   friend void   line_plane_X(const Pnt3& p, const Pnt3& dir,
  108.      const Pnt3& nrm, float d,
  109.      Pnt3 &x, float &dist);
  110.   friend void   bary(const Pnt3& p,  const Pnt3& t1,
  111.      const Pnt3& t2, const Pnt3& t3,
  112.      float &b1, float &b2, float &b3);
  113.   friend void   bary_fast(const Pnt3& p, const Pnt3& n, 
  114.   const Pnt3 &t0, const Pnt3& v1, const Pnt3& v2,
  115.   float &b1, float &b2, float &b3);
  116.   friend void   bary(const Pnt3& p,  const Pnt3& dir,
  117.      const Pnt3& t1, const Pnt3& t2, 
  118.      const Pnt3& t3,
  119.      float &b1, float &b2, float &b3);
  120.   friend int    above_plane(const Pnt3& p, const Pnt3& a, 
  121.     const Pnt3& b, const Pnt3& c);
  122.   float         smallest_circle(const Pnt3 &, const Pnt3 &, const Pnt3 &);
  123.   // functions used for closest point searching in KDtrees and octrees
  124.   friend bool   ball_within_bounds(const Pnt3 &, float,
  125.    const Pnt3 &, float);
  126.   friend bool   ball_within_bounds(const Pnt3 &, float,
  127.    const Pnt3 &, const Pnt3 &);
  128.   friend bool   bounds_overlap_ball(const Pnt3 &, float,
  129.     const Pnt3 &, float);
  130.   friend bool   bounds_overlap_ball(const Pnt3 &, float,
  131.     const Pnt3 &, const Pnt3 &);
  132.   friend bool   spheres_intersect(const Pnt3 &, const Pnt3 &,
  133.   float, float);
  134.   friend bool   lines_intersect(const Pnt3 &p1,
  135. const Pnt3 &p2,
  136. const Pnt3 &p3,
  137. const Pnt3 &p4,
  138. Pnt3 &isect);
  139.   // rigid transformations only (rot + trans)
  140.   Pnt3 &        xform(float m[16]);// OpenGL matrix: p . M = p'
  141.   Pnt3 &        xform(double m[16]);// OpenGL matrix: p . M = p'
  142.   Pnt3 &        xform(float r[3][3], float  t[3]);
  143.   Pnt3 &        xform(float r[3][3], double t[3]);
  144.   Pnt3 &        invxform(float m[16]);// OpenGL matrix: p . M = p'
  145.   Pnt3 &        invxform(double m[16]);// OpenGL matrix: p . M = p'
  146.   Pnt3 &        invxform(float r[3][3], float  t[3]);
  147.   Pnt3 &        invxform(float r[3][3], double t[3]);
  148.   Pnt3 & setXformed(const Pnt3 &p, float r[3][3], float t[3]);
  149.   Pnt3 & setRotated(const Pnt3 &p, float r[3][3]);
  150. };
  151. inline Pnt3& 
  152. Pnt3::operator+=(const Pnt3 &a)
  153. {
  154.   v[0] += a.v[0]; v[1] += a.v[1]; v[2] += a.v[2];
  155.   return *this;
  156. }
  157. inline Pnt3& 
  158. Pnt3::operator-=(const Pnt3 &a)
  159. {
  160.   v[0] -= a.v[0]; v[1] -= a.v[1]; v[2] -= a.v[2];
  161.   return *this;
  162. }
  163. inline Pnt3& 
  164. Pnt3::operator*=(const float &a)
  165. {
  166.   v[0] *= a; v[1] *= a; v[2] *= a;
  167.   return *this;
  168. }
  169. inline Pnt3& 
  170. Pnt3::operator/=(const float &a)
  171. {
  172.   float tmp = 1.0f / a;
  173.   v[0] *= tmp; v[1] *= tmp; v[2] *= tmp;
  174.   return *this;
  175. }
  176. inline int
  177. Pnt3::operator==(const Pnt3 &a)
  178. {
  179.   return (a.v[0]==v[0] && a.v[1]==v[1] && a.v[2]==v[2]);
  180. }
  181. inline int
  182. Pnt3::operator!=(const Pnt3 &a)
  183. {
  184.   return (a.v[0]!=v[0] || a.v[1]!=v[1] || a.v[2]!=v[2]);
  185. }
  186. inline Pnt3
  187. operator+(const Pnt3 &a, const Pnt3 &b)
  188. {
  189.   Pnt3 tmp = a; 
  190.   return (tmp += b);
  191. }
  192. inline Pnt3
  193. operator-(const Pnt3 &a, const Pnt3 &b)
  194. {
  195.   Pnt3 tmp = a; 
  196.   return (tmp -= b);
  197. }
  198. inline Pnt3
  199. operator*(const Pnt3 &a, const float &b)
  200. {
  201.   Pnt3 tmp = a; 
  202.   return (tmp *= b);
  203. }
  204. inline Pnt3
  205. operator*(const float &a, const Pnt3 &b)
  206. {
  207.   Pnt3 tmp = b; 
  208.   return (tmp *= a);
  209. }
  210. inline Pnt3
  211. operator/(const Pnt3 &a, const float &b)
  212. {
  213.   Pnt3 tmp = a; 
  214.   return (tmp /= b);
  215. }
  216. inline ostream& 
  217. operator<<(ostream &out, const Pnt3 &a)
  218.   return out << "["<< a.v[0] <<" "<< a.v[1] <<" "<< a.v[2] << "]";
  219. }
  220. inline istream& 
  221. operator>>(istream &in, Pnt3 &a)
  222. {
  223.   char c = 0;
  224.   in >> ws >> c;
  225.   if (c == '[') {
  226.     in >> a.v[0] >> a.v[1] >> a.v[2];
  227.     in >> c;
  228.     if (c != ']') in.clear(ios::badbit);
  229.   } else {
  230.     in.putback(c);
  231.     in >> a.v[0] >> a.v[1] >> a.v[2];
  232.   }
  233.   return in;
  234. }
  235. inline float 
  236. Pnt3::norm() const
  237.   return sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  238. }
  239. inline float 
  240. Pnt3::norm2() const
  241.   return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  242. }
  243. inline Pnt3 &
  244. Pnt3::normalize(void)
  245. {
  246.   float a = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  247.   if (a != 0) { 
  248.     a = 1.0/sqrtf(a); 
  249.     v[0] *= a; v[1] *= a; v[2] *= a; 
  250.   }
  251.   return *this;
  252. }
  253. inline Pnt3 &
  254. Pnt3::set_norm(float len)
  255. {
  256.   float a = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  257.   if (a != 0) { 
  258.     a = len/sqrtf(a); 
  259.     v[0] *= a; v[1] *= a; v[2] *= a; 
  260.   }
  261.   return *this;
  262. }
  263. inline float
  264. dist2(const Pnt3 &a, const Pnt3 &b)
  265. {
  266.   float x = a.v[0]-b.v[0];
  267.   float y = a.v[1]-b.v[1];
  268.   float z = a.v[2]-b.v[2];
  269.   return x*x + y*y + z*z;
  270. }
  271. inline float
  272. dist(const Pnt3 &a, const Pnt3 &b)
  273. {
  274.   return sqrtf(dist2(a,b));
  275. }
  276. inline float
  277. dist2_2d(const Pnt3 &a, const Pnt3 &b)
  278. {
  279.   float x = a.v[0]-b.v[0];
  280.   float y = a.v[1]-b.v[1];
  281.   return x*x + y*y;
  282. }
  283. inline float
  284. dist_2d(const Pnt3 &a, const Pnt3 &b)
  285. {
  286.   return sqrtf(dist2_2d(a,b));
  287. }
  288. inline float
  289. dist_manhattan(const Pnt3 &a, const Pnt3 &b)
  290. {
  291.   float d = fabs(a[0]-b[0]);
  292.   float t = fabs(a[1]-b[1]);
  293.   if (t > d) d = t;
  294.   t = fabs(a[2]-b[2]);
  295.   if (t > d) return t;
  296.   return d;
  297. }
  298. // distance from x to linesegment from a to b
  299. inline float  
  300. dist2_lineseg(const Pnt3 &x, const Pnt3 &a, const Pnt3 &b)
  301. {
  302.   Pnt3 ba = b; ba -= a;
  303.   Pnt3 xa = x; xa -= a;
  304.   float xa_ba = dot(xa,ba);
  305.   // if the dot product is negative, the point is closest to a
  306.   if (xa_ba < 0.0)   return dist2(x,a);
  307.   // if the dot product is greater than squared segment length,
  308.   // the point is closest to b
  309.   float nba2 = ba.norm2();
  310.   if (xa_ba >= nba2) return dist2(x,b);
  311.   // take the squared dist x-a, squared dot of x-a to unit b-a,
  312.   // use Pythagoras' rule
  313.   return xa.norm2() - xa_ba*xa_ba/nba2;
  314. }
  315. inline float
  316. dist2_tri(const Pnt3 &x, 
  317.   const Pnt3 &t1, const Pnt3 &t2, const Pnt3 &t3)
  318. {
  319.   // calculate the normal and distance from the plane
  320.   Pnt3 v1(t2.v[0]-t1.v[0], t2.v[1]-t1.v[1], t2.v[2]-t1.v[2]);
  321.   Pnt3 v2(t3.v[0]-t1.v[0], t3.v[1]-t1.v[1], t3.v[2]-t1.v[2]);
  322.   Pnt3 n = cross(v1,v2);
  323.   float n_inv_mag2 = 1.0/n.norm2();
  324.   float tmp  = (x.v[0]-t1.v[0])*n.v[0] + 
  325.                (x.v[1]-t1.v[1])*n.v[1] + 
  326.                (x.v[2]-t1.v[2])*n.v[2];
  327.   float distp2 = tmp * tmp * n_inv_mag2;
  328.   // calculate the barycentric coordinates of the point 
  329.   // (projected onto tri plane) with respect to v123
  330.   float b1,b2,b3;
  331.   float f = tmp*n_inv_mag2;
  332.   Pnt3  pp(x[0]-f*n[0], x[1]-f*n[1], x[2]-f*n[2]);
  333.   bary_fast(pp, n, t1,v1,v2, b1,b2,b3);
  334.   // all non-negative, the point is within the triangle
  335.   if (b1 >= 0.0 && b2 >= 0.0 && b3 >= 0.0) {
  336.     return distp2;
  337.   }
  338.   // look at the signs of the barycentric coordinates
  339.   // if there are two negative signs, the positive
  340.   // one tells the vertex that's closest
  341.   // if there's one negative sign, the opposite edge
  342.   // (with endpoints) is closest
  343.   if (b1 < 0.0) {
  344.     if (b2 < 0.0) { 
  345.       return dist2(x,t3);
  346.     } else if (b3 < 0.0) {
  347.       return dist2(x,t2);
  348.     } else return dist2_lineseg(x, t2,t3);
  349.   } else if (b2 < 0.0) {
  350.     if (b3 < 0.0) {
  351.       return dist2(x,t1);
  352.     } else return dist2_lineseg(x, t1,t3);
  353.   } else   return dist2_lineseg(x, t1,t2);
  354. }
  355. inline bool
  356. closer_on_lineseg(const Pnt3 &x, Pnt3 &cp, const Pnt3 &a, 
  357.   const Pnt3 &b, float &d2)
  358. {
  359.   Pnt3 ba(b.v[0]-a.v[0], b.v[1]-a.v[1], b.v[2]-a.v[2]);
  360.   Pnt3 xa(x.v[0]-a.v[0], x.v[1]-a.v[1], x.v[2]-a.v[2]);
  361.   float xa_ba = dot(xa,ba);
  362.   // if the dot product is negative, the point is closest to a
  363.   if (xa_ba < 0.0) {
  364.     float nd = dist2(x,a);
  365.     if (nd < d2) { cp = a; d2 = nd; return true; }
  366.     return false;
  367.   }
  368.   // if the dot product is greater than squared segment length,
  369.   // the point is closest to b
  370.   float fact = xa_ba/ba.norm2();
  371.   if (fact >= 1.0) {
  372.     float nd = dist2(x,b);
  373.     if (nd < d2) { cp = b; d2 = nd; return true; }
  374.     return false;
  375.   }
  376.   // take the squared dist x-a, squared dot of x-a to unit b-a,
  377.   // use Pythagoras' rule
  378.   float nd = xa.norm2() - xa_ba*fact;
  379.   if (nd < d2) { 
  380.     d2 = nd;
  381.     cp.v[0] = a.v[0] + fact * ba.v[0];
  382.     cp.v[1] = a.v[1] + fact * ba.v[1];
  383.     cp.v[2] = a.v[2] + fact * ba.v[2];
  384.     return true;
  385.   }
  386.   return false;
  387. }
  388.  
  389. inline bool
  390. closer_on_tri(const Pnt3 &x, Pnt3 &cp, const Pnt3 &t1, 
  391.       const Pnt3 &t2, const Pnt3 &t3, float &d2)
  392. {
  393.   // calculate the normal and distance from the plane
  394.   Pnt3 v1(t2.v[0]-t1.v[0], t2.v[1]-t1.v[1], t2.v[2]-t1.v[2]);
  395.   Pnt3 v2(t3.v[0]-t1.v[0], t3.v[1]-t1.v[1], t3.v[2]-t1.v[2]);
  396.   Pnt3 n = cross(v1,v2);
  397.   float n_inv_mag2 = 1.0/n.norm2();
  398.   float tmp  = (x.v[0]-t1.v[0])*n.v[0] + 
  399.                (x.v[1]-t1.v[1])*n.v[1] + 
  400.                (x.v[2]-t1.v[2])*n.v[2];
  401.   float distp2 = tmp * tmp * n_inv_mag2;
  402.   if (distp2 >= d2) return false;
  403.   // calculate the barycentric coordinates of the point 
  404.   // (projected onto tri plane) with respect to v123
  405.   float b1,b2,b3;
  406.   float f = tmp*n_inv_mag2;
  407.   Pnt3  pp(x[0]-f*n[0], x[1]-f*n[1], x[2]-f*n[2]);
  408.   bary_fast(pp, n, t1,v1,v2, b1,b2,b3);
  409.   // all non-negative, the point is within the triangle
  410.   if (b1 >= 0.0 && b2 >= 0.0 && b3 >= 0.0) {
  411.     d2 = distp2;
  412.     cp = pp;
  413.     return true;
  414.   }
  415.   // look at the signs of the barycentric coordinates
  416.   // if there are two negative signs, the positive
  417.   // one tells the vertex that's closest
  418.   // if there's one negative sign, the opposite edge
  419.   // (with endpoints) is closest
  420.   if (b1 < 0.0) {
  421.     if (b2 < 0.0) { 
  422.       float nd = dist2(x,t3);
  423.       if (nd < d2) { d2 = nd; cp = t3; return true; }
  424.       else         { return false; }
  425.     } else if (b3 < 0.0) {
  426.       float nd = dist2(x,t2);
  427.       if (nd < d2) { d2 = nd; cp = t2; return true; }
  428.       else         { return false; }
  429.     } else return closer_on_lineseg(x, cp, t2,t3, d2);
  430.   } else if (b2 < 0.0) {
  431.     if (b3 < 0.0) {
  432.       float nd = dist2(x,t1);
  433.       if (nd < d2) { d2 = nd; cp = t1; return true; }
  434.       else         { return false; }
  435.     } else return closer_on_lineseg(x, cp, t1,t3, d2);
  436.   } else   return closer_on_lineseg(x, cp, t1,t2, d2);
  437. }
  438. inline float 
  439. dot(const Pnt3 &a, const Pnt3 &b)
  440.   return (a.v[0]*b.v[0] + a.v[1]*b.v[1] + a.v[2]*b.v[2]);
  441. }
  442. inline Pnt3 
  443. cross(const Pnt3 &a, const Pnt3 &b)
  444.   return Pnt3(a.v[1]*b.v[2] - a.v[2]*b.v[1],
  445.       a.v[2]*b.v[0] - a.v[0]*b.v[2],
  446.       a.v[0]*b.v[1] - a.v[1]*b.v[0]);
  447. }
  448. // two vectors, a and b, starting from c
  449. inline Pnt3
  450. cross(const Pnt3 &a, const Pnt3 &b, const Pnt3 &c)
  451. {
  452.   float a0 = a.v[0]-c.v[0];
  453.   float a1 = a.v[1]-c.v[1];
  454.   float a2 = a.v[2]-c.v[2];
  455.   float b0 = b.v[0]-c.v[0];
  456.   float b1 = b.v[1]-c.v[1];
  457.   float b2 = b.v[2]-c.v[2];
  458.   return Pnt3(a1*b2 - a2*b1, a2*b0 - a0*b2, a0*b1 - a1*b0);
  459. }
  460. // get a normal from triangle ABC, points given in ccw order
  461. inline Pnt3 
  462. normal(const Pnt3 &a, const Pnt3 &b, const Pnt3 &c)
  463.   float a0 = a.v[0]-c.v[0];
  464.   float a1 = a.v[1]-c.v[1];
  465.   float a2 = a.v[2]-c.v[2];
  466.   float b0 = b.v[0]-c.v[0];
  467.   float b1 = b.v[1]-c.v[1];
  468.   float b2 = b.v[2]-c.v[2];
  469.   float x = a1*b2 - a2*b1;
  470.   float y = a2*b0 - a0*b2;
  471.   float z = a0*b1 - a1*b0;
  472.   float n = x*x+y*y+z*z;
  473.   if (n == 0) {
  474.     return Pnt3();
  475.   } else {
  476.     n = 1.0/sqrtf(n);
  477.     return Pnt3(x*n, y*n, z*n);
  478.   }
  479. }
  480. // determinant of 3 points
  481. inline float  
  482. det(const Pnt3 &a, const Pnt3 &b, const Pnt3 &c)
  483. {
  484.   return a[0]*(b[1]*c[2]-b[2]*c[1]) 
  485.     -    a[1]*(b[0]*c[2]-b[2]*c[0])
  486.     +    a[2]*(b[0]*c[1]-b[1]*c[0]);
  487. }
  488. // calculate the intersection of a line going through p
  489. // to direction dir with a plane spanned by t1,t2,t3
  490. // (modified from Graphics Gems, p.299)
  491. inline void
  492. line_plane_X(const Pnt3& p, const Pnt3& dir,
  493.      const Pnt3& t1, const Pnt3& t2, const Pnt3& t3, 
  494.      Pnt3 &x, float &dist)
  495. {
  496.   // note: normal doesn't need to be unit vector
  497.   Pnt3  nrm = cross(t1,t2,t3);
  498.   float tmp = dot(nrm,dir);
  499.   if (tmp == 0.0) {
  500.     cerr << "Cannot intersect plane with a parallel line" << endl;
  501.     return;
  502.   }
  503.   // d  = -dot(nrm,t1)
  504.   // t  = - (d + dot(p,nrm))/dot(dir,nrm)
  505.   // is = p + dir * t
  506.   x = dir;
  507.   dist = (dot(nrm,t1)-dot(nrm,p))/tmp;
  508.   x *= dist;
  509.   x += p;
  510.   if (dist < 0.0) dist = -dist;
  511. }
  512. inline void   
  513. line_plane_X(const Pnt3& p, const Pnt3& dir,
  514.     const Pnt3& nrm, float d, Pnt3 &x, float &dist)
  515. {
  516.   float tmp = dot(nrm,dir);
  517.   if (tmp == 0.0) {
  518.     cerr << "Cannot intersect plane with a parallel line" << endl;
  519.     return;
  520.   }
  521.   x = dir;
  522.   dist = -(d+dot(nrm,p))/tmp;
  523.   x *= dist;
  524.   x += p;
  525.   if (dist < 0.0) dist = -dist;
  526. }
  527. // calculate barycentric coordinates of the point p
  528. // on triangle t1 t2 t3
  529. inline void 
  530. bary(const Pnt3& p, 
  531.      const Pnt3& t1, const Pnt3& t2, const Pnt3& t3,
  532.      float &b1, float &b2, float &b3)
  533. {
  534.   // figure out the plane onto which to project the vertices
  535.   // by calculating a cross product and finding its largest dimension
  536.   // then use Cramer's rule to calculate two of the
  537.   // barycentric coordinates
  538.   // e.g., if the z coordinate is ignored, and v1 = t1-t3, v2 = t2-t3
  539.   // b1 = det[x[0] v2[0]; x[1] v2[1]] / det[v1[0] v2[0]; v1[1] v2[1]]
  540.   // b2 = det[v1[0] x[0]; v1[1] x[1]] / det[v1[0] v2[0]; v1[1] v2[1]]
  541.   float v10 = t1.v[0]-t3.v[0];
  542.   float v11 = t1.v[1]-t3.v[1];
  543.   float v12 = t1.v[2]-t3.v[2];
  544.   float v20 = t2.v[0]-t3.v[0];
  545.   float v21 = t2.v[1]-t3.v[1];
  546.   float v22 = t2.v[2]-t3.v[2];
  547.   float c[2];
  548.   c[0] = fabs(v11*v22 - v12*v21);
  549.   c[1] = fabs(v12*v20 - v10*v22);
  550.   int i = 0;
  551.   if (c[1] > c[0]) i = 1;
  552.   if (fabs(v10*v21 - v11*v20) > c[i]) {
  553.     // ignore z
  554.     float d = 1.0 / (v10*v21-v11*v20);
  555.     float x0 = (p.v[0]-t3.v[0]);
  556.     float x1 = (p.v[1]-t3.v[1]);
  557.     b1 = (x0*v21 - x1*v20) * d;
  558.     b2 = (v10*x1 - v11*x0) * d;
  559.   } else if (i==0) {
  560.     // ignore x
  561.     float d = 1.0 / (v11*v22-v12*v21);
  562.     float x0 = (p.v[1]-t3.v[1]);
  563.     float x1 = (p.v[2]-t3.v[2]);
  564.     b1 = (x0*v22 - x1*v21) * d;
  565.     b2 = (v11*x1 - v12*x0) * d;
  566.   } else {
  567.     // ignore y
  568.     float d = 1.0 / (v12*v20-v10*v22);
  569.     float x0 = (p.v[2]-t3.v[2]);
  570.     float x1 = (p.v[0]-t3.v[0]);
  571.     b1 = (x0*v20 - x1*v22) * d;
  572.     b2 = (v12*x1 - v10*x0) * d;
  573.   }
  574.   b3 = 1.0 - b1 - b2;
  575. }
  576. // calculate barycentric coordinates of the point p
  577. // (already on the triangle plane) with normal vector n
  578. // and two edge vectors v1 and v2, 
  579. // starting from a common vertex t0
  580. inline void 
  581. bary_fast(const Pnt3& p, const Pnt3& n, 
  582.   const Pnt3 &t0, const Pnt3& v1, const Pnt3& v2,
  583.   float &b1, float &b2, float &b3)
  584. {
  585.   // see bary above
  586.   int i = 0;
  587.   if (n.v[1] > n.v[0]) i = 1;
  588.   if (n.v[2] > n.v[i]) {
  589.     // ignore z
  590.     float d = 1.0 / (v1.v[0]*v2.v[1]-v1.v[1]*v2.v[0]);
  591.     float x0 = (p.v[0]-t0.v[0]);
  592.     float x1 = (p.v[1]-t0.v[1]);
  593.     b1 = (x0*v2.v[1] - x1*v2.v[0]) * d;
  594.     b2 = (v1.v[0]*x1 - v1.v[1]*x0) * d;
  595.   } else if (i==0) {
  596.     // ignore x
  597.     float d = 1.0 / (v1.v[1]*v2.v[2]-v1.v[2]*v2.v[1]);
  598.     float x0 = (p.v[1]-t0.v[1]);
  599.     float x1 = (p.v[2]-t0.v[2]);
  600.     b1 = (x0*v2.v[2] - x1*v2.v[1]) * d;
  601.     b2 = (v1.v[1]*x1 - v1.v[2]*x0) * d;
  602.   } else {
  603.     // ignore y
  604.     float d = 1.0 / (v1.v[2]*v2.v[0]-v1.v[0]*v2.v[2]);
  605.     float x0 = (p.v[2]-t0.v[2]);
  606.     float x1 = (p.v[0]-t0.v[0]);
  607.     b1 = (x0*v2.v[0] - x1*v2.v[2]) * d;
  608.     b2 = (v1.v[2]*x1 - v1.v[0]*x0) * d;
  609.   }
  610.   b3 = 1.0 - b1 - b2;
  611. }
  612. // calculate barycentric coordinates for the intersection of
  613. // a line starting from p, going to direction dir, and the plane
  614. // of the triangle t1 t2 t3
  615. inline void 
  616. bary(const Pnt3& p, const Pnt3& dir,
  617.      const Pnt3& t1, const Pnt3& t2, const Pnt3& t3,
  618.      float &b1, float &b2, float &b3)
  619. {
  620.   Pnt3 x; float d;
  621.   line_plane_X(p, dir, t1, t2, t3, x, d);
  622.   bary(x, t1,t2,t3, b1,b2,b3);
  623. }
  624. // is p above the plane spanned by triangle abc (ccw order)?
  625. inline int    
  626. above_plane(const Pnt3& p, const Pnt3& a, 
  627.     const Pnt3& b, const Pnt3& c)
  628. {
  629.   Pnt3 nrm = cross(a,b,c);
  630.   return dot(p,nrm) > dot(a,nrm);
  631. }
  632. // find the smallest circle that covers a,b,c
  633. // set self to the center, return radius
  634. inline float
  635. Pnt3::smallest_circle(const Pnt3 &A, const Pnt3 &B, const Pnt3 &C)
  636. {
  637.   Pnt3 a(B); a-=A;
  638.   Pnt3 b(C); b-=B;
  639.   Pnt3 c(A); c-=C;
  640.   float da = a.norm2();
  641.   float db = b.norm2();
  642.   float dc = c.norm2();
  643.   //const float *x;
  644.   if (da > db && da > dc) {
  645.     // da longest
  646.     if (da >= db + dc) {
  647.       // over 90 deg angle, solution is the center of the 
  648.       // longest edge
  649.       v[0] = .5 * (A.v[0]+B.v[0]);
  650.       v[1] = .5 * (A.v[1]+B.v[1]);
  651.       v[2] = .5 * (A.v[2]+B.v[2]);
  652.       return .5*sqrtf(da);
  653.     }
  654.   } else if (dc > db) {
  655.     // dc longest
  656.     if (dc >= db + da) {
  657.       // over 90 deg angle, solution is the center of the 
  658.       // longest edge
  659.       v[0] = .5 * (A.v[0]+C.v[0]);
  660.       v[1] = .5 * (A.v[1]+C.v[1]);
  661.       v[2] = .5 * (A.v[2]+C.v[2]);
  662.       return .5*sqrtf(dc);
  663.     }
  664.   } else {
  665.     // db longest
  666.     if (db >= da + dc) {
  667.       // over 90 deg angle, solution is the center of the 
  668.       // longest edge
  669.       v[0] = .5 * (B.v[0]+C.v[0]);
  670.       v[1] = .5 * (B.v[1]+C.v[1]);
  671.       v[2] = .5 * (B.v[2]+C.v[2]);
  672.       return .5*sqrtf(db);
  673.     }
  674.   }
  675.     
  676.   // solution is the circumcircle (see GGems 4 p.144)
  677.   Pnt3 aperp = cross(a, cross(a,b));
  678.   float fact = dot(b,c) / dot(aperp, c);
  679.   v[0] = A.v[0] + .5 * (a.v[0] + fact * aperp.v[0]);
  680.   v[1] = A.v[1] + .5 * (a.v[1] + fact * aperp.v[1]);
  681.   v[2] = A.v[2] + .5 * (a.v[2] + fact * aperp.v[2]);
  682.   return .5 * sqrtf(da*fact*fact+da);
  683. }
  684. // is the ball centered at b with radius r
  685. // fully within the box centered at bc, with radius br?
  686. inline bool
  687. ball_within_bounds(const Pnt3 &b, float r,
  688.    const Pnt3 &bc, float br)
  689. {
  690.   r -= br;
  691.   if ((b.v[0] - bc.v[0] <= r) ||
  692.       (bc.v[0] - b.v[0] <= r) ||
  693.       (b.v[1] - bc.v[1] <= r) ||
  694.       (bc.v[1] - b.v[1] <= r) ||
  695.       (b.v[2] - bc.v[2] <= r) ||
  696.       (bc.v[2] - b.v[2] <= r)) return false;
  697.   return true;
  698. }
  699. // is the ball centered at b with radius r
  700. // fully within the box centered from min to max?
  701. inline bool
  702. ball_within_bounds(const Pnt3 &b,
  703.    float r,
  704.    const Pnt3 &min, 
  705.    const Pnt3 &max)
  706. {
  707.   if ((b.v[0] - min.v[0] <= r) ||
  708.       (max.v[0] - b.v[0] <= r) ||
  709.       (b.v[1] - min.v[1] <= r) ||
  710.       (max.v[1] - b.v[1] <= r) ||
  711.       (b.v[2] - min.v[2] <= r) ||
  712.       (max.v[2] - b.v[2] <= r)) return false;
  713.   return true;
  714. }
  715. // does the ball centered at b, with radius r,
  716. // intersect the box centered at bc, with radius br?
  717. inline bool
  718. bounds_overlap_ball(const Pnt3 &b, float r,
  719.     const Pnt3 &bc, float br)
  720. {
  721.   float sum = 0.0, tmp;
  722.   if        ((tmp = bc.v[0]-br - b.v[0]) > 0.0) {
  723.     if (tmp>r) return false; sum += tmp*tmp; 
  724.   } else if ((tmp = b.v[0] - (bc.v[0]+br)) > 0.0) { 
  725.     if (tmp>r) return false; sum += tmp*tmp; 
  726.   }
  727.   if        ((tmp = bc.v[1]-br - b.v[1]) > 0.0) {
  728.     if (tmp>r) return false; sum += tmp*tmp; 
  729.   } else if ((tmp = b.v[1] - (bc.v[1]+br)) > 0.0) { 
  730.     if (tmp>r) return false; sum += tmp*tmp; 
  731.   }
  732.   if        ((tmp = bc.v[2]-br - b.v[2]) > 0.0) {
  733.     if (tmp>r) return false; sum += tmp*tmp; 
  734.   } else if ((tmp = b.v[2] - (bc.v[2]+br)) > 0.0) { 
  735.     if (tmp>r) return false; sum += tmp*tmp; 
  736.   }
  737.   return (sum < r*r);
  738. }
  739. inline bool 
  740. bounds_overlap_ball(const Pnt3 &b,
  741.     float r,
  742.     const Pnt3 &min, 
  743.     const Pnt3 &max)
  744. {
  745.   float sum = 0.0, tmp;
  746.   if        (b.v[0] < min.v[0]) { 
  747.     tmp = min.v[0] - b.v[0]; if (tmp>r) return false; sum+=tmp*tmp;
  748.   } else if (b.v[0] > max.v[0]) { 
  749.     tmp = b.v[0] - max.v[0]; if (tmp>r) return false; sum+=tmp*tmp;
  750.   }
  751.   if        (b.v[1] < min.v[1]) { 
  752.     tmp = min.v[1] - b.v[1]; sum+=tmp*tmp;
  753.   } else if (b.v[1] > max.v[1]) { 
  754.     tmp = b.v[1] - max.v[1]; sum+=tmp*tmp;
  755.   }
  756.   r *= r;
  757.   if (sum > r) return false;
  758.   if        (b.v[2] < min.v[2]) { 
  759.     tmp = min.v[2] - b.v[2]; sum+=tmp*tmp;
  760.   } else if (b.v[2] > max.v[2]) { 
  761.     tmp = b.v[2] - max.v[2]; sum+=tmp*tmp;
  762.   }
  763.   return (sum < r);
  764. }
  765. // this function tests for the intersection
  766. // of two spheres, for one of which we have the
  767. // squared radius
  768. inline bool
  769. spheres_intersect(const Pnt3 &c1, const Pnt3 &c2,
  770.   float r1sqr, float r2)
  771. {
  772.   float x = c1.v[0]-c2.v[0];
  773.   float y = c1.v[1]-c2.v[1];
  774.   float z = c1.v[2]-c2.v[2];
  775.   // try to avoid square root
  776.   //float r2sqr = r2*r2;
  777.   //float R2 = (x*x + y*y + z*z - r1sqr - r2sqr)*.5;
  778.   float R2 = (x*x + y*y + z*z - r1sqr - r2*r2);
  779.   // check against underestimate
  780.   if (R2 < 0.0) return true;
  781.   /*
  782.   // check against overestimate
  783.   //R2 *= .5;
  784.   if (r1sqr > r2sqr) {
  785.     if (R2 > r1sqr) return false;
  786.   } else {
  787.     if (R2 > r2sqr) return false;
  788.   }
  789.   */
  790.   // had to take square root...
  791.   return (R2 < 2.0*sqrtf(r1sqr)*r2);  
  792. }
  793. //GGems II, p. 142
  794. inline bool
  795. lines_intersect(const Pnt3 &p1,
  796. const Pnt3 &p2,
  797. const Pnt3 &p3,
  798. const Pnt3 &p4,
  799. Pnt3 &isect)
  800. {
  801.   Pnt3 a = p2 - p1;
  802.   Pnt3 b = p4 - p3;
  803.   Pnt3 axb = cross(a,b);
  804.   float d2 = axb.norm2();
  805.   if (d2 < 1.e-7) return false;
  806.   isect = p1 + a * dot(axb, cross((p3-p1),b)) / d2;
  807.   return true;
  808. }
  809. inline Pnt3 &
  810. Pnt3::xform(float m[16])
  811. {
  812.   float x = m[0]*v[0] + m[4]*v[1] + m[8] *v[2] + m[12];
  813.   float y = m[1]*v[0] + m[5]*v[1] + m[9] *v[2] + m[13];
  814.   v[2]    = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14];
  815.   v[0] = x; v[1] = y;
  816.   return *this;
  817. }
  818. inline Pnt3 &
  819. Pnt3::xform(double m[16])
  820. {
  821.   float x = m[0]*v[0] + m[4]*v[1] + m[8] *v[2] + m[12];
  822.   float y = m[1]*v[0] + m[5]*v[1] + m[9] *v[2] + m[13];
  823.   v[2]    = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14];
  824.   v[0] = x; v[1] = y;
  825.   return *this;
  826. }
  827. inline Pnt3 &
  828. Pnt3::xform(float r[3][3], float t[3])
  829. {
  830.   float x = t[0] + r[0][0]*v[0] + r[0][1]*v[1] + r[0][2]*v[2];
  831.   float y = t[1] + r[1][0]*v[0] + r[1][1]*v[1] + r[1][2]*v[2];
  832.   v[2]    = t[2] + r[2][0]*v[0] + r[2][1]*v[1] + r[2][2]*v[2];
  833.   v[0] = x; v[1] = y;
  834.   return *this;
  835. }
  836. inline Pnt3 &
  837. Pnt3::xform(float r[3][3], double t[3])
  838. {
  839.   float x = t[0] + r[0][0]*v[0] + r[0][1]*v[1] + r[0][2]*v[2];
  840.   float y = t[1] + r[1][0]*v[0] + r[1][1]*v[1] + r[1][2]*v[2];
  841.   v[2]    = t[2] + r[2][0]*v[0] + r[2][1]*v[1] + r[2][2]*v[2];
  842.   v[0] = x; v[1] = y;
  843.   return *this;
  844. }
  845. inline Pnt3 &
  846. Pnt3::invxform(float m[16])
  847. {
  848.   float tx = v[0] - m[12];
  849.   float ty = v[1] - m[13];
  850.   float tz = v[2] - m[14];
  851.   v[0] = m[0]*tx + m[1]*ty + m[2]*tz;
  852.   v[1] = m[4]*tx + m[5]*ty + m[6]*tz;
  853.   v[2] = m[8]*tx + m[9]*ty + m[10]*tz;
  854.   return *this;
  855. }
  856. inline Pnt3 &
  857. Pnt3::invxform(double m[16])
  858. {
  859.   double tx = v[0] - m[12];
  860.   double ty = v[1] - m[13];
  861.   double tz = v[2] - m[14];
  862.   v[0] = m[0]*tx + m[1]*ty + m[2]*tz;
  863.   v[1] = m[4]*tx + m[5]*ty + m[6]*tz;
  864.   v[2] = m[8]*tx + m[9]*ty + m[10]*tz;
  865.   return *this;
  866. }
  867. inline Pnt3 &
  868. Pnt3::invxform(float r[3][3], float t[3])
  869. {
  870.   float tx = v[0] - t[0];
  871.   float ty = v[1] - t[1];
  872.   float tz = v[2] - t[2];
  873.   v[0] = r[0][0]*tx + r[1][0]*ty + r[2][0]*tz;
  874.   v[1] = r[0][1]*tx + r[1][1]*ty + r[2][1]*tz;
  875.   v[2] = r[0][2]*tx + r[1][2]*ty + r[2][2]*tz;
  876.   return *this;
  877. }
  878. inline Pnt3 &
  879. Pnt3::invxform(float r[3][3], double t[3])
  880. {
  881.   float tx = v[0] - t[0];
  882.   float ty = v[1] - t[1];
  883.   float tz = v[2] - t[2];
  884.   v[0] = r[0][0]*tx + r[1][0]*ty + r[2][0]*tz;
  885.   v[1] = r[0][1]*tx + r[1][1]*ty + r[2][1]*tz;
  886.   v[2] = r[0][2]*tx + r[1][2]*ty + r[2][2]*tz;
  887.   return *this;
  888. }
  889. inline Pnt3 &
  890. Pnt3::setXformed(const Pnt3 &p, float r[3][3], float t[3])
  891. {
  892.   v[0] = r[0][0]*p.v[0] + r[0][1]*p.v[1] + r[0][2]*p.v[2] + t[0];
  893.   v[1] = r[1][0]*p.v[0] + r[1][1]*p.v[1] + r[1][2]*p.v[2] + t[1];
  894.   v[2] = r[2][0]*p.v[0] + r[2][1]*p.v[1] + r[2][2]*p.v[2] + t[2];
  895.   return *this;
  896. }
  897. inline Pnt3 &
  898. Pnt3::setRotated(const Pnt3 &p, float r[3][3])
  899. {
  900.   v[0] = r[0][0]*p.v[0] + r[0][1]*p.v[1] + r[0][2]*p.v[2];
  901.   v[1] = r[1][0]*p.v[0] + r[1][1]*p.v[1] + r[1][2]*p.v[2];
  902.   v[2] = r[2][0]*p.v[0] + r[2][1]*p.v[1] + r[2][2]*p.v[2];
  903.   return *this;
  904. }
  905. class Vec3 : public Pnt3 {
  906. public:
  907.   Vec3(float a=0.0, float b=0.0, float c=0.0) 
  908.     { v[0] = a, v[1] = b, v[2] = c; normalize(); }
  909.   Vec3(const Pnt3 &p)
  910.     { v[0] = p[0]; v[1] = p[1]; v[2] = p[2]; normalize(); }
  911.   Vec3 &xform(float m[16]); // OpenGL model matrix
  912.   Vec3 &xform(float r[3][3]);
  913. };
  914. inline Vec3 &
  915. Vec3::xform(float m[16])
  916. {
  917.   float x = m[0]*v[0] + m[4]*v[1] + m[8] *v[2];
  918.   float y = m[1]*v[0] + m[5]*v[1] + m[9] *v[2];
  919.   v[2]    = m[2]*v[0] + m[6]*v[1] + m[10]*v[2];
  920.   v[0] = x; v[1] = y;
  921.   return *this;
  922. }
  923. inline Vec3 &
  924. Vec3::xform(float r[3][3])
  925. {
  926.   float x = r[0][0]*v[0] + r[0][1]*v[1] + r[0][2]*v[2];
  927.   float y = r[1][0]*v[0] + r[1][1]*v[1] + r[1][2]*v[2];
  928.   v[2]    = r[2][0]*v[0] + r[2][1]*v[1] + r[2][2]*v[2];
  929.   v[0] = x; v[1] = y;
  930.   return *this;
  931. }
  932. #endif
  933. #ifdef PNT3_MAIN
  934. #include <iostream.h>
  935. #define SHOW(X) cout << #X " = " << X << endl
  936. void
  937. main(void)
  938. {
  939.   Pnt3 a;
  940.   Pnt3 b(1,1,1);
  941.   SHOW(a);
  942.   SHOW(b);
  943.   SHOW(dist2_lineseg(a, a, b));
  944.   SHOW(dist2_lineseg(b, a, b));
  945.   SHOW(dist2_lineseg(.5*(a+b), a, b));
  946.   SHOW(dist2_lineseg(a+Pnt3(1,0,0), a, b));
  947.   SHOW(dist2_lineseg(b+Pnt3(1,0,0), a, b));
  948.   SHOW(dist2_lineseg(2*b, a, b));
  949.   SHOW(dist2_lineseg( -b, a, b));
  950.   Pnt3 c(1,0,0);
  951.   SHOW(c);
  952.   
  953.   SHOW(dist2_tri(a, a,b,c));
  954.   SHOW(dist2_tri(b, a,b,c));
  955.   SHOW(dist2_tri(c, a,b,c));
  956.   SHOW(dist2_tri((a+b+c)/3.0, a,b,c));
  957.   SHOW(dist2_tri(Pnt3(0,-1,1), a,b,c));
  958.   SHOW(dist2_tri((a+b+c)/3.0 + 2*Pnt3(0,-1,1), a,b,c));
  959. }
  960. #endif