Cyl.cc

Go to the documentation of this file.
00001 
00004 #include <iostream>
00005 #include "Cyl.h"
00006 #include "BoundingBox.h"
00007 #include "HitRecord.h"
00008 #include "Point.h"
00009 #include "Plane.h"
00010 #include "Ray.h"
00011 #include "Vector.h"
00012 #include <math.h>
00013 #include <stdlib.h>
00014 #include <float.h>
00015 
00016 Cyl::Cyl(Material* material, const Point & b, const Point & t, const float rad)
00017     : Primitive(material), base(b), top(t), radius(rad)
00018 {
00019     A = top - base;
00020     topPlane = new Plane(material, A, t);
00021     basePlane = new Plane(material, -A, b);
00022 
00023     A.normalize();
00024 }
00025 
00026 
00027 Cyl::~Cyl()
00028 {
00029     delete basePlane;
00030     delete topPlane;
00031 }
00032 
00033 void Cyl::getBounds(BoundingBox& bbox) const
00034 {
00035 }
00036 
00037 
00038 void Cyl::normal(Vector& normal, const RenderContext&, const Point& hitpos,
00039                     const Ray& ray, const HitRecord& hit) const
00040 {
00041     Vector BH = hitpos - base;
00042     Vector N;
00043 
00044     switch (hit.scratchdata[0]) {
00045     case 0:
00046         N = BH - (Dot(BH, A) * A);
00047         N = N / radius;
00048 
00049         normal = N;
00050         break;
00051     case 1:
00052         // hit the base
00053         normal = -A;
00054         break;
00055     case 2:
00056         // hit the top
00057         normal = A;
00058         break;
00059     }
00060 }
00061 
00062 
00063 void Cyl::intersect(HitRecord& hit, const RenderContext& context, const Ray& ray) const
00064 {
00065     Vector D = Cross(ray.direction(), A);
00066 
00067     D.normalize();
00068 
00069     Vector BrMinusBc = ray.origin() - base;
00070 
00071     float d = Abs( Dot(BrMinusBc, D) );
00072 
00073     if (d > radius)
00074         return;
00075 
00076     Vector RcrossA = Cross(ray.direction(), A);
00077 
00078     float t_pca = Dot(Cross(BrMinusBc, A), RcrossA) / RcrossA.length2();
00079     t_pca *= -1.0;
00080 
00081 
00082     Vector O = Cross(D, A);
00083     O.normalize();
00084 
00085     float s = sqrt((radius*radius)-(d*d))/Dot(ray.direction(), O);
00086 
00087     float tmin = t_pca-s;
00088     float tmax = t_pca+s;
00089 
00090     if (tmin > tmax) {
00091         tmin = t_pca+s;
00092         tmax = t_pca-s;
00093     }
00094 
00095     int max_surf, min_surf;
00096     max_surf = min_surf = 0;
00097 
00098     double t_plane;
00099 
00100 
00101 
00102 #if 1
00103     HitRecord baseHit(DBL_MAX);
00104     basePlane->intersect(baseHit, context, ray);
00105     t_plane = baseHit.minT();
00106     if (Dot(-A, ray.direction()) >= 0) {
00107         // ray leaving base plane
00108         if (t_plane < tmax) {
00109             tmax = t_plane;
00110             max_surf = 1;
00111         }
00112     } else {
00113         // ray entering base plane
00114         if (t_plane > tmin) {
00115             tmin = t_plane;
00116             min_surf = 1;
00117         }
00118     }
00119 #endif
00120 
00121     HitRecord topHit(DBL_MAX);
00122     topPlane->intersect(topHit, context, ray);
00123     t_plane = topHit.minT();
00124     if (Dot(A, ray.direction()) >= 0) {
00125         // ray leaving top plane
00126         if (t_plane < tmax) {
00127             tmax = t_plane;
00128             max_surf = 2;
00129         }
00130     } else {
00131         // ray entering top plane
00132         if (t_plane > tmin) {
00133             tmin = t_plane;
00134             min_surf = 2;
00135         }
00136     }
00137 
00138 
00139     if (tmin > tmax)
00140         return;
00141 
00142     if (hit.hit(tmin, this, matl)) {
00143         hit.scratchdata[0] = min_surf;
00144     } else if (hit.hit(tmax, this, matl)) {
00145         hit.scratchdata[0] = max_surf;
00146     }
00147 }

Generated on Tue Jan 29 21:34:53 2008 for specter by  doxygen 1.4.6