All pastes #976428 Raw Edit

Unnamed

public text v1 · immutable
·published 2008-04-08 04:07 UTC
rendered paste body
/**************************************************************************** *               spheres.cpp * * This module implements the sphere primitive. * * from Persistence of Vision(tm) Ray Tracer version 3.6. * Copyright 1991-2003 Persistence of Vision Team * Copyright 2003-2004 Persistence of Vision Raytracer Pty. Ltd. *--------------------------------------------------------------------------- * NOTICE: This source code file is provided so that users may experiment * with enhancements to POV-Ray and to port the software to platforms other * than those supported by the POV-Ray developers. There are strict rules * regarding how you are permitted to use this file. These rules are contained * in the distribution and derivative versions licenses which should have been * provided with this file. * * These licences may be found online, linked from the end-user license * agreement that is located at http://www.povray.org/povlegal.html *--------------------------------------------------------------------------- * This program is based on the popular DKB raytracer version 2.12. * DKBTrace was originally written by David K. Buck. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. *--------------------------------------------------------------------------- * $File: //depot/povray/3.6-release/source/spheres.cpp $ * $Revision: #2 $ * $Change: 2939 $ * $DateTime: 2004/07/05 03:43:26 $ * $Author: root $ * $Log$ *****************************************************************************/#include "frame.h"#include "povray.h"#include "vector.h"#include "povproto.h"#include "bbox.h"#include "matrices.h"#include "objects.h"#include "spheres.h"BEGIN_POV_NAMESPACE/****************************************************************************** Local preprocessor defines******************************************************************************/const DBL DEPTH_TOLERANCE = 1.0e-6;/****************************************************************************** Static functions******************************************************************************/static int All_Sphere_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);static int All_Ellipsoid_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);static int Inside_Sphere (VECTOR IPoint, OBJECT *Object);static int Inside_Ellipsoid (VECTOR IPoint, OBJECT *Object);static void Sphere_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);static void Sphere_UVCoord (UV_VECT Result, OBJECT *Object, INTERSECTION *Inter);static void Ellipsoid_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);static void Translate_Sphere (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);static void Rotate_Sphere (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);static void Scale_Sphere (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);static void Invert_Sphere (OBJECT *Object);/****************************************************************************** Local variables******************************************************************************/METHODS Sphere_Methods ={  All_Sphere_Intersections,  Inside_Sphere, Sphere_Normal, Sphere_UVCoord,  (COPY_METHOD)Copy_Sphere,  Translate_Sphere, Rotate_Sphere,  Scale_Sphere, Transform_Sphere, Invert_Sphere,  Destroy_Sphere};METHODS Ellipsoid_Methods ={  All_Ellipsoid_Intersections,  Inside_Ellipsoid, Ellipsoid_Normal, Sphere_UVCoord,  (COPY_METHOD)Copy_Sphere,  Translate_Sphere, Rotate_Sphere,  Scale_Sphere, Transform_Sphere, Invert_Sphere,  Destroy_Sphere};/******************************************************************************* FUNCTION**   All_Sphere_Intersection** INPUT*   * OUTPUT*   * RETURNS*   * AUTHOR**   ?*   * DESCRIPTION**   -** CHANGES**   -*******************************************************************************/static int All_Sphere_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack){  register int Intersection_Found;  DBL Depth1, Depth2;  VECTOR IPoint;  SPHERE *Sphere = (SPHERE *)Object;  Intersection_Found = false;  if (Intersect_Sphere(Ray, Sphere->Center, Sqr(Sphere->Radius), &Depth1, &Depth2))  {    if ((Depth1 > DEPTH_TOLERANCE) && (Depth1 < Max_Distance))    {      VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction);      if (Point_In_Clip(IPoint, Object->Clip))      {        push_entry(Depth1, IPoint, Object, Depth_Stack);        Intersection_Found = true;      }    }    if ((Depth2 > DEPTH_TOLERANCE) && (Depth2 < Max_Distance))    {      VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction);      if (Point_In_Clip(IPoint, Object->Clip))      {        push_entry(Depth2, IPoint, Object, Depth_Stack);        Intersection_Found = true;      }    }  }  return(Intersection_Found);}/******************************************************************************* FUNCTION**   All_Ellipsoid_Intersection** INPUT*   * OUTPUT*   * RETURNS*   * AUTHOR**   ?*   * DESCRIPTION**   -** CHANGES**   -*******************************************************************************/static int All_Ellipsoid_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack){  register int Intersection_Found;  DBL Depth1, Depth2, len;  VECTOR IPoint;  RAY New_Ray;  SPHERE *Sphere = (SPHERE *)Object;  /* Transform the ray into the ellipsoid's space */  MInvTransPoint(New_Ray.Initial, Ray->Initial, ((SPHERE *)Object)->Trans);  MInvTransDirection(New_Ray.Direction, Ray->Direction, ((SPHERE *)Object)->Trans);  VLength(len, New_Ray.Direction);  VInverseScaleEq(New_Ray.Direction, len);  Intersection_Found = false;  if (Intersect_Sphere(&New_Ray, Sphere->Center, Sqr(Sphere->Radius), &Depth1, &Depth2))  {    if ((Depth1 > DEPTH_TOLERANCE) && (Depth1 < Max_Distance))    {      VEvaluateRay(IPoint, New_Ray.Initial, Depth1, New_Ray.Direction);      MTransPoint(IPoint, IPoint, ((SPHERE *)Object)->Trans);      if (Point_In_Clip(IPoint, Object->Clip))      {        push_entry(Depth1 / len, IPoint, Object, Depth_Stack);        Intersection_Found = true;      }    }    if ((Depth2 > DEPTH_TOLERANCE) && (Depth2 < Max_Distance))    {      VEvaluateRay(IPoint, New_Ray.Initial, Depth2, New_Ray.Direction);      MTransPoint(IPoint, IPoint, ((SPHERE *)Object)->Trans);      if (Point_In_Clip(IPoint, Object->Clip))      {        push_entry(Depth2 / len, IPoint, Object, Depth_Stack);        Intersection_Found = true;      }    }  }  return(Intersection_Found);}/******************************************************************************* FUNCTION**   Intersect_Sphere** INPUT**   Ray     - Ray to test intersection with*   Center  - Center of the sphere*   Radius2 - Squared radius of the sphere*   Depth1  - Lower intersection distance*   Depth2  - Upper intersection distance*   * OUTPUT*   * RETURNS*   * AUTHOR**   ?*   * DESCRIPTION**   -** CHANGES**   -*******************************************************************************/int Intersect_Sphere(RAY *Ray, VECTOR Center, DBL Radius2, DBL *Depth1, DBL  *Depth2){  DBL OCSquared, t_Closest_Approach, Half_Chord, t_Half_Chord_Squared;  VECTOR Origin_To_Center;  Increase_Counter(stats[Ray_Sphere_Tests]);  VSub(Origin_To_Center, Center, Ray->Initial);  VDot(OCSquared, Origin_To_Center, Origin_To_Center);  VDot(t_Closest_Approach, Origin_To_Center, Ray->Direction);  if ((OCSquared >= Radius2) && (t_Closest_Approach < EPSILON))  {    return(false);  }  t_Half_Chord_Squared = Radius2 - OCSquared + Sqr(t_Closest_Approach);  if (t_Half_Chord_Squared > EPSILON)  {    Half_Chord = sqrt(t_Half_Chord_Squared);    *Depth1 = t_Closest_Approach - Half_Chord;    *Depth2 = t_Closest_Approach + Half_Chord;    Increase_Counter(stats[Ray_Sphere_Tests_Succeeded]);    return(true);  }  return(false);}/******************************************************************************* FUNCTION**   Inside_Sphere** INPUT*   * OUTPUT*   * RETURNS*   * AUTHOR**   ?*   * DESCRIPTION**   -** CHANGES**   -*******************************************************************************/static int Inside_Sphere(VECTOR IPoint, OBJECT *Object){  DBL OCSquared;  VECTOR Origin_To_Center;  VSub(Origin_To_Center, ((SPHERE *)Object)->Center, IPoint);  VDot(OCSquared, Origin_To_Center, Origin_To_Center);  if (Test_Flag(Object, INVERTED_FLAG))  {    return(OCSquared > Sqr(((SPHERE *)Object)->Radius));  }  else  {    return(OCSquared < Sqr(((SPHERE *)Object)->Radius));  }}/******************************************************************************* FUNCTION**   Inside_Ellipsoid** INPUT** OUTPUT*   * RETURNS*   * AUTHOR**   ?*   * DESCRIPTION**   -** CHANGES**   -*******************************************************************************/static int Inside_Ellipsoid(VECTOR IPoint, OBJECT *Object){  DBL OCSquared;  VECTOR Origin_To_Center, New_Point;  /* Transform the point into the sphere's space */  MInvTransPoint(New_Point, IPoint, ((SPHERE *)Object)->Trans);  VSub(Origin_To_Center, ((SPHERE *)Object)->Center, New_Point);  VDot(OCSquared, Origin_To_Center, Origin_To_Center);  if (Test_Flag(Object, INVERTED_FLAG))  {    return(OCSquared > Sqr(((SPHERE *)Object)->Radius));  }  else  {    return(OCSquared < Sqr(((SPHERE *)Object)->Radius));  }}/******************************************************************************* FUNCTION**   Sphere_Normal** INPUT*   * OUTPUT*   * RETURNS*   * AUTHOR**   ?*   * DESCRIPTION**   -** CHANGES**   -*******************************************************************************/static void Sphere_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter){  VSub(Result, Inter->IPoint, ((SPHERE *)Object)->Center);  VInverseScaleEq(Result, ((SPHERE *)Object)->Radius);}/******************************************************************************* FUNCTION**   Ellipsoid_Normal** INPUT*   * OUTPUT*   * RETURNS*   * AUTHOR**   ?*   * DESCRIPTION**   -** CHANGES**   -*******************************************************************************/static void Ellipsoid_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter){  VECTOR New_Point;  /* Transform the point into the sphere's space */  MInvTransPoint(New_Point, Inter->IPoint, ((SPHERE *)Object)->Trans);  VSub(Result, New_Point, ((SPHERE *)Object)->Center);  MTransNormal(Result, Result, ((SPHERE *)Object)->Trans);  VNormalize(Result, Result);}/******************************************************************************* FUNCTION**   Copy_Shere** INPUT*   * OUTPUT*   * RETURNS*   * AUTHOR**   ?*   * DESCRIPTION**   -** CHANGES**   -*******************************************************************************/SPHERE *Copy_Sphere(OBJECT *Object){  SPHERE *New;  New = Create_Sphere();  *New = *((SPHERE *)Object);  New->Trans = Copy_Transform(((SPHERE *)Object)->Trans);  return(New);}/******************************************************************************* FUNCTION**   Translate_Sphere** INPUT** OUTPUT** RETURNS** AUTHOR**   ?** DESCRIPTION**   -** CHANGES**   -*******************************************************************************/static void Translate_Sphere(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans){  SPHERE *Sphere = (SPHERE *) Object;  if (Sphere->Trans == NULL)  {    VAddEq(Sphere->Center, Vector);    Compute_Sphere_BBox(Sphere);  }  else  {    Transform_Sphere(Object, Trans);  }}/******************************************************************************* FUNCTION**   Rotate_Sphere** INPUT** OUTPUT*   * RETURNS*   * AUTHOR**   ?*   * DESCRIPTION**   -** CHANGES**   -*******************************************************************************/static void Rotate_Sphere(OBJECT *Object, VECTOR, TRANSFORM *Trans){  SPHERE *Sphere = (SPHERE *) Object;  if (Sphere->Trans == NULL)  {    MTransPoint(Sphere->Center, Sphere->Center, Trans);    Compute_Sphere_BBox(Sphere);  }  else  {    Transform_Sphere(Object, Trans);  }}/******************************************************************************* FUNCTION**   Scale_Sphere** INPUT*   * OUTPUT*   * RETURNS*   * AUTHOR**   ?*   * DESCRIPTION**   -** CHANGES**   -*******************************************************************************/static void Scale_Sphere(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans){  SPHERE *Sphere = (SPHERE *) Object;  if ((Vector[X] != Vector[Y]) || (Vector[X] != Vector[Z]))  {    if (Sphere->Trans == NULL)    {      Sphere->Methods = &Ellipsoid_Methods;      Sphere->Trans = Create_Transform();    }  }  if (Sphere->Trans == NULL)  {    VScaleEq(Sphere->Center, Vector[X]);    Sphere->Radius *= fabs(Vector[X]);    Compute_Sphere_BBox(Sphere);  }  else  {    Transform_Sphere(Object, Trans);  }}/******************************************************************************* FUNCTION**   Invert_Sphere** INPUT*   * OUTPUT*   * RETURNS*   * AUTHOR**   ?*   * DESCRIPTION**   -** CHANGES**   -*******************************************************************************/static void Invert_Sphere(OBJECT *Object){  Invert_Flag(Object, INVERTED_FLAG);}/******************************************************************************* FUNCTION**   Create_Sphere** INPUT*   * OUTPUT*   * RETURNS*   * AUTHOR**   ?*   * DESCRIPTION**   -** CHANGES**   -*******************************************************************************/SPHERE *Create_Sphere(){  SPHERE *New;  New = (SPHERE *)POV_MALLOC(sizeof(SPHERE), "sphere");  INIT_OBJECT_FIELDS(New, SPHERE_OBJECT, &Sphere_Methods)  Make_Vector(New->Center, 0.0, 0.0, 0.0);  New->Radius = 1.0;  New->Trans = NULL;  return(New);}/******************************************************************************* FUNCTION**   Transform_Sphere** INPUT*   * OUTPUT*   * RETURNS*   * AUTHOR**   ?*   * DESCRIPTION**   -** CHANGES**   -*******************************************************************************/void Transform_Sphere(OBJECT *Object, TRANSFORM *Trans){  SPHERE *Sphere = (SPHERE *)Object;  if (Sphere->Trans == NULL)  {    Sphere->Methods = &Ellipsoid_Methods;    Sphere->Trans = Create_Transform();  }  Compose_Transforms(Sphere->Trans, Trans);  Compute_Sphere_BBox(Sphere);}/******************************************************************************* FUNCTION**   Destroy_Sphere** INPUT*   * OUTPUT*   * RETURNS*   * AUTHOR**   ?*   * DESCRIPTION**   -** CHANGES**   -*******************************************************************************/void Destroy_Sphere(OBJECT *Object){#if(DUMP_OBJECT_DATA == 1)  Debug_Info("{ // SPHERE \n");  DUMP_OBJECT_FIELDS(Object);  Debug_Info("\t{ %f, %f, %f }, // Center\n", \             (DBL)((SPHERE *)Object)->Center[X], \             (DBL)((SPHERE *)Object)->Center[Y], \             (DBL)((SPHERE *)Object)->Center[Z]); \  Debug_Info("\t%f // Radius\n", (DBL)((SPHERE *)Object)->Radius);  Debug_Info("}\n");#endif  Destroy_Transform(((SPHERE *)Object)->Trans);  POV_FREE (Object);}/******************************************************************************* FUNCTION**   Compute_Sphere_BBox** INPUT**   Sphere - Sphere*   * OUTPUT**   Sphere*   * RETURNS*   * AUTHOR**   Dieter Bayer*   * DESCRIPTION**   Calculate the bounding box of a sphere.** CHANGES**   Aug 1994 : Creation.*******************************************************************************/void Compute_Sphere_BBox(SPHERE *Sphere){  Make_BBox(Sphere->BBox, Sphere->Center[X] - Sphere->Radius, Sphere->Center[Y] - Sphere->Radius,  Sphere->Center[Z] - Sphere->Radius,    2.0 * Sphere->Radius, 2.0 * Sphere->Radius, 2.0 * Sphere->Radius);  if (Sphere->Trans != NULL)  {    Recompute_BBox(&Sphere->BBox, Sphere->Trans);  }}/******************************************************************************* FUNCTION**   Sphere_UVCoord** INPUT** OUTPUT** RETURNS** AUTHOR**   Nathan Kopp   (adapted from spherical_image_map)** DESCRIPTION**   Find the UV coordinates of a sphere.*   Map a point (x, y, z) on a sphere of radius 1 to a 2-d image. (Or is it the*   other way around?)** CHANGES**   -*******************************************************************************/static void Sphere_UVCoord(UV_VECT Result, OBJECT *Object, INTERSECTION *Inter){  DBL len, phi, theta;  DBL x,y,z;  VECTOR New_Point, New_Center;  SPHERE *Sphere = (SPHERE *)Object;  /* Transform the point into the sphere's space */  if (Object->UV_Trans != NULL)  {        MInvTransPoint(New_Point, Inter->IPoint, Object->UV_Trans);    if (Sphere->Trans != NULL)      MTransPoint(New_Center, Sphere->Center, Sphere->Trans);    else      Assign_Vector(New_Center, Sphere->Center);    MInvTransPoint(New_Center, New_Center, Object->UV_Trans);  }  else  {    Assign_Vector(New_Point, Inter->IPoint);    Assign_Vector(New_Center, Sphere->Center);  }  x = New_Point[X]-New_Center[X];  y = New_Point[Y]-New_Center[Y];  z = New_Point[Z]-New_Center[Z];  len = sqrt(x * x + y * y + z * z);  if (len == 0.0)    return;  else  {    x /= len;    y /= len;    z /= len;  }  /* Determine its angle from the x-z plane. */  phi = 0.5 + asin(y) / M_PI; /* This will be from 0 to 1 */  /* Determine its angle from the point (1, 0, 0) in the x-z plane. */  len = x * x + z * z;  if (len > EPSILON)  {    len = sqrt(len);    if (z == 0.0)    {      if (x > 0)        theta = 0.0;      else        theta = M_PI;    }    else    {      theta = acos(x / len);      if (z < 0.0)        theta = TWO_M_PI - theta;    }    theta /= TWO_M_PI;  /* This will be from 0 to 1 */  }  else    /* This point is at one of the poles. Any value of xcoord will be ok... */    theta = 0;  Result[U] = theta;  Result[V] = phi;}END_POV_NAMESPACE