home *** CD-ROM | disk | FTP | other *** search
- /*
- * Sphere.C - methods for sphere manipulations.
- *
- * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
- * University of Berne, Switzerland
- * Copyright (C) 1989, 1991, Craig E. Kolb
- * All rights reserved.
- *
- * This software may be freely copied, modified, and redistributed
- * provided that this copyright notice is preserved on all copies.
- *
- * You may not distribute this software, in whole or in part, as part of
- * any commercial product without the express consent of the authors.
- *
- * There is no warranty or other guarantee of fitness of this software
- * for any purpose. It is provided solely "as is".
- *
- */
-
- #include "Sphere.h"
-
- //___________________________________________________________ Sphere
-
- Sphere::Sphere(real radius, const Vector& position)
- : r(radius), center(position)
- {
- rsqr = r*r;
- }
-
- GeoObject* Sphere::create(real radius, const Vector& position)
- {
- if (radius < EPSILON)
- return NULL;
-
- return new Sphere(radius, position);
- }
-
- /*
- * Compute the intersection between a ray and a sphere.
- * This algorithm is adapted from Craig Kolbs rayshade.
- */
-
- int Sphere::intersect(const Ray& ray, real minDist, real& maxDist)
- {
- real xadj, yadj, zadj;
- real b, t, s;
-
- intersectionTests++;
-
- /*
- * Translate ray origin to object space and negate everything.
- * (Thus, we translate the sphere into ray space, which saves
- * us a couple of negations below.)
- */
- xadj = center[0] - ray.getOrig()[0];
- yadj = center[1] - ray.getOrig()[1];
- zadj = center[2] - ray.getOrig()[2];
-
- /*
- * Solve quadratic equation.
- */
- b = xadj*ray.getDir()[0] + yadj*ray.getDir()[1] + zadj*ray.getDir()[2];
- t = b*b - xadj*xadj - yadj*yadj - zadj*zadj + rsqr;
- if (t < 0.)
- return FALSE;
-
- t = sqrt(t);
-
- /*
- * we may hit the sphere twice, test both cases
- */
- s = b - t;
- if (s > minDist) {
- if (s < maxDist) {
- maxDist = s;
- return TRUE;
- }
- return FALSE;
- }
-
- s = b + t;
- if (s > minDist && s < maxDist) {
- maxDist = s;
- intersections++;
- return TRUE;
- }
- return FALSE;
- }
-
- /*
- * Compute sphere normal.
- */
-
- Vector Sphere::normal(const Vector& p) const
- {
- return (p-center)/r;
- }
-
- /*
- * tesselate splits the sphere into polygons.
- */
-
- PolygonList* Sphere::tesselate(const BoundingBox&)
- {
- PolygonList* polys = tesselation(center, r, 10);
-
- if (trans != NULL) {
- for (register long i=0; i<polys->count(); i++)
- polys->item(i)->transform(*trans);
- }
-
- return polys;
- }
-
- /*
- * General sphere tesselation.
- */
-
- PolygonList* Sphere::tesselation(const Vector& pos, real r, int res)
- {
- real delta = M_PI/res;
- PolygonList* polySphere = new PolygonList(3*res);
- Vector A, B, C, D;
-
- for (real alpha=0; alpha < 2*M_PI; alpha += delta) {
- A = B = Vector(0,0,-r)+pos;
- for (real beta=-M_PI_2+delta; beta<=M_PI_2-delta; beta += delta) {
- C = computeSurfacePoint(alpha+delta, beta)*r+pos;
- D = computeSurfacePoint(alpha, beta)*r+pos;
- if (A==B)
- polySphere->append(new Polygon(A, C, D));
- else
- polySphere->append(new Polygon(A, B, C, D));
- A=D; B=C;
- }
- polySphere->append(new Polygon(A, B, Vector(0,0,r)+pos));
- }
- return polySphere;
- }
-
- Vector Sphere::computeSurfacePoint(real alpha, real beta)
- {
- real sin_a, cos_a, sin_b, cos_b;
- SinCos(alpha, sin_a, cos_a);
- SinCos(beta, sin_b, cos_b);
- return Vector(cos_a*cos_b, sin_a*cos_b, sin_b);
- }
-