| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860 |
- /****************************************************************************
- * spheres.c
- *
- * This module implements the sphere primitive.
- *
- * from Persistence of Vision(tm) Ray Tracer
- * Copyright 1996,1999 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * 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 Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file.
- * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by email to team-coord@povray.org or visit us on the web at
- * http://www.povray.org. The latest version of POV-Ray may be found at this site.
- *
- * 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.
- *
- *****************************************************************************/
- #include "frame.h"
- #include "povray.h"
- #include "vector.h"
- #include "povproto.h"
- #include "bbox.h"
- #include "matrices.h"
- #include "objects.h"
- #include "spheres.h"
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
- #define 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 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
- ******************************************************************************/
- static METHODS Sphere_Methods =
- {
- All_Sphere_Intersections,
- Inside_Sphere, Sphere_Normal,
- (COPY_METHOD)Copy_Sphere,
- Translate_Sphere, Rotate_Sphere,
- Scale_Sphere, Transform_Sphere, Invert_Sphere,
- Destroy_Sphere
- };
- static METHODS Ellipsoid_Methods =
- {
- All_Ellipsoid_Intersections,
- Inside_Ellipsoid, Ellipsoid_Normal,
- (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 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 *= 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)
- {
- 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);
- }
- }
|