Main Page Class Hierarchy Compound List File List Compound Members File Members

RT_Prim.cc

Go to the documentation of this file.
00001 /*
00002 File: RT_Prim.cc
00003 
00004 Function: Implements various ray-trace primitives
00005 
00006 Author: Andrew Willmott
00007 
00008 Notes: 
00009 */
00010 
00011 #include "RT_Prim.h"
00012 #include "gcl/VecUtil.h"
00013 
00014 // --- Triangle methods -------------------------------------------------------
00015 
00016 
00017 Int RT_Prim::gStamp = 1;
00018 Int RT_Object::gStamp = 1;
00019 
00020  Void RT_Tri::Init(Int v1, Int v2, Int v3, RT_Object *obj, Int triID)
00021 {
00022 v[0] = v1;
00023 v[1] = v2;
00024 v[2] = v3;
00025 flags = 0;
00026 stamp = 0;
00027 primType = rt_triangle;
00028 object = obj;
00029 id = triID;
00030 }
00031 
00032  #define CROSS_X_3(a, b, c) ((a[1] - b[1]) * (c[2] - b[2]) \
00033 - (a[2] - b[2]) * (c[1] - b[1]))
00034 // returns (a - b) x (c - a) . (1, 0, 0)
00035  #define CROSS_Y_3(a, b, c) ((a[2] - b[2]) * (c[0] - b[0]) \
00036 - (a[0] - b[0]) * (c[2] - b[2]))
00037 // returns (a - b) x (c - a) . (0, 1, 0)
00038  #define CROSS_Z_3(a, b, c) ((a[0] - b[0]) * (c[1] - b[1]) \
00039 - (a[1] - b[1]) * (c[0] - b[0]))
00040 // returns (a - b) x (c - a) . (0, 0, 1)
00041 
00042  static const GCLReal kEdgeFuzz = 0.0; 
00043  static const GCLReal kNegEdgeFuzz = -kEdgeFuzz; 
00044 
00045  Bool RT_Tri::PointIsInside(Point& point)
00046 {
00047 Point* points = object->points;
00048 Int i0 = v[0], i1 = v[1], i2 = v[2];
00049 GCLReal temp, a, b;
00050 
00051 #ifdef RT_TRI_CACHE 
00052 // Time stamp object so we can reuse this intersection test if necessary.
00053 
00054 Stamp();
00055 #endif
00056 
00057 flags &= ~TRI_HIT;
00058 
00059 // Given a point lying in the plane of the triangle, we return false
00060 // if it lies outside the triangle, and its barycentric coordinates if it
00061 // lies inside.
00062 
00063 temp = normal[normMajorAxis];
00064 
00065 switch(normMajorAxis)
00066 {
00067 case 0:
00068 a = CROSS_X_3(points[i2], points[i1], point) / temp;
00069 if (a < kEdgeFuzz) return(false);
00070 
00071 b = CROSS_X_3(points[i0], points[i2], point) / temp;
00072 if (b < kEdgeFuzz) return(false);
00073 
00074 a = 1.0 - a - b;
00075 if (a < kEdgeFuzz) return(false);
00076 
00077 flags |= TRI_HIT;
00078 return(true);
00079 
00080 case 1:
00081 a = CROSS_Y_3(points[i2], points[i1], point) / temp; 
00082 if (a < kEdgeFuzz) return(false);
00083 
00084 b = CROSS_Y_3(points[i0], points[i2], point) / temp; 
00085 if (b < kEdgeFuzz) return(false);
00086 
00087 a = 1.0 - a - b;
00088 if (a < kEdgeFuzz) return(false);
00089 
00090 flags |= TRI_HIT;
00091 return(true);
00092 
00093 case 2:
00094 a = CROSS_Z_3(points[i2], points[i1], point) / temp;
00095 if (a < kEdgeFuzz) return(false);
00096 
00097 b = CROSS_Z_3(points[i0], points[i2], point) / temp;
00098 if (b < kEdgeFuzz) return(false);
00099 
00100 a = 1.0 - a - b;
00101 if (a < kEdgeFuzz) return(false);
00102 
00103 flags |= TRI_HIT;
00104 return(true);
00105 }
00106 
00107 return(true); // to keep the compiler happy.
00108 }
00109 
00110  Void RT_Tri::FindBaryCoords(Point& point, Vector &coords)
00111 {
00112 Point* points = object->points;
00113 Int i0 = v[0], i1 = v[1], i2 = v[2];
00114 GCLReal temp;
00115 
00116 #ifdef RT_TRI_CACHE 
00117 // Time stamp object so we can reuse this intersection test if necessary.
00118 
00119 Stamp();
00120 #endif
00121 
00122 flags &= ~TRI_HIT;
00123 
00124 // Given a point lying in the plane of the triangle, we return false
00125 // if it lies outside the triangle, and its barycentric coordinates if it
00126 // lies inside.
00127 
00128 temp = normal[normMajorAxis];
00129 
00130 switch(normMajorAxis)
00131 {
00132 case 0:
00133 coords[0] = CROSS_X_3(points[i2], points[i1], point) / temp;
00134 coords[1] = CROSS_X_3(points[i0], points[i2], point) / temp;
00135 coords[2] = 1.0 - coords[0] - coords[1];
00136 return;
00137 
00138 case 1:
00139 coords[0] = CROSS_Y_3(points[i2], points[i1], point) / temp; 
00140 coords[1] = CROSS_Y_3(points[i0], points[i2], point) / temp; 
00141 coords[2] = 1.0 - coords[0] - coords[1];
00142 return;
00143 
00144 case 2:
00145 coords[0] = CROSS_Z_3(points[i2], points[i1], point) / temp; 
00146 coords[1] = CROSS_Z_3(points[i0], points[i2], point) / temp; 
00147 coords[2] = 1.0 - coords[0] - coords[1];
00148 return;
00149 }
00150 }
00151 
00152 
00153  Void RT_Tri::UpdateBounds(Point& min, Point& max)
00154 // Use the tri's vertices to update the given min & max bounds.
00155 {
00156 Int i;
00157 Point *points = object->points;
00158 
00159 for (i = 0; i < 3; i++)
00160 ::UpdateBounds(points[v[i]], min, max);
00161 }
00162 
00163  Void RT_Tri::MakeNormal()
00164 {
00165 GCLReal xf, yf, zf;
00166 Point* points = object->points;
00167 
00168 // Calculate face normal & other info
00169 
00170 CalcTriAreaNormal(points[v[0]], points[v[1]], points[v[2]], normal);
00171 
00172 d = -dot(normal, points[v[2]]);
00173 
00174 xf = abs(normal[0]);
00175 yf = abs(normal[1]);
00176 zf = abs(normal[2]);
00177 
00178 if (xf > yf)
00179 {
00180 if (xf > zf)
00181 normMajorAxis = 0;
00182 else
00183 normMajorAxis = 2;
00184 }
00185 else 
00186 {
00187 if (yf > zf)
00188 normMajorAxis = 1;
00189 else
00190 normMajorAxis = 2;
00191 }
00192 
00193 area = 0.5 * len(normal);
00194 }
00195 
00196 
00197 // --- RT_Sphere methods ------------------------------------------------------
00198 
00199  Void RT_Sphere::Init(const Point &c, GCLReal r, RT_Object *obj, Int genID)
00200 {
00201 centre = c;
00202 radius = r;
00203 sqrRad = sqr(r);
00204 area = vl_pi * sqrRad;
00205 primType = rt_gen;
00206 object = obj;
00207 id = genID;
00208 }
00209 
00210 
00211  Bool RT_Sphere::Intersect(Point &start, Vector &dir, GCLReal tMin, GCLReal tMax)
00212 // Assumes dir is normalised.
00213 {
00214 Vector v = centre - start;
00215 GCLReal b = dot(v, dir);
00216 GCLReal disc = sqr(b) - sqrlen(v) + sqrRad;
00217 GCLReal t0;
00218 
00219 flags &= ~TRI_HIT;
00220 
00221 // Root must be smaller than current value of t...
00222 // and larger than tMin
00223 
00224 if (disc <= 0.0)
00225 return(false); // no intersection
00226 
00227 disc = sqrt(disc);
00228 t0 = b - disc; // 1st root
00229 
00230 if (t0 >= tMin && t0 < tMax)
00231 {
00232 hitT = t0;
00233 flags |= TRI_HIT;
00234 return(true);
00235 }
00236 
00237 t0 = b + disc; // 2nd root
00238 
00239 if (t0 >= tMin && t0 < tMax)
00240 {
00241 hitT = t0;
00242 flags |= TRI_HIT;
00243 return(true);
00244 }
00245 
00246 return(false); // intersection is behind
00247 }
00248 
00249  Void RT_Sphere::UpdateBounds(Point &min, Point &max)
00250 {
00251 Point sMin, sMax;
00252 
00253 FindBounds(sMin, sMax);
00254 FindMinElts(sMin, min, min); 
00255 FindMaxElts(sMax, max, max); 
00256 }
00257 
00258  Void RT_Sphere::FindBounds(Point &min, Point &max)
00259 {
00260 max.MakeBlock(radius);
00261 min = centre - max;
00262 max += centre;
00263 }
00264 
00265 
00266 // --- RT_Object methods -------------------------------------------------------
00267 
00268 
00269  Void RT_Object::Init(Int numTris, Int numGens)
00270 {
00271 SELF.numTris = numTris;
00272 SELF.numGens = numGens;
00273 if (numTris == 0)
00274 tris = 0;
00275 else
00276 tris = new RT_Tri[numTris];
00277 if (numGens == 0)
00278 gens = 0;
00279 else
00280 gens = new RT_GenPtr[numGens];
00281 
00282 points = 0;
00283 numPoints = 0;
00284 normals = 0;
00285 numNormals = 0;
00286 
00287 tag = 1;
00288 id = 0;
00289 }
00290 
00291  Void RT_Object::Setup()
00292 {
00293 Int i;
00294 
00295 for (i = 0; i < numTris; i++)
00296 {
00297 tris[i].object = this;
00298 tris[i].MakeNormal();
00299 }
00300 }
00301 
00302  Void RT_Object::Free()
00303 {
00304 Int i;
00305 
00306 for (i = 0; i < numGens; i++)
00307 delete gens[i];
00308 
00309 delete[] tris;
00310 delete[] gens;
00311 delete[] points;
00312 delete[] normals;
00313 }

Generated at Sat Aug 5 00:26:54 2000 for Radiator by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000

AltStyle によって変換されたページ (->オリジナル) /