| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932 |
- /****************************************************************************
- * torus.c
- *
- * This module implements functions that manipulate torii.
- *
- * This module was written by Dieter Bayer [DB].
- *
- * 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.
- *
- *****************************************************************************/
- /****************************************************************************
- *
- * Explanation:
- *
- * ---
- *
- * June 1994 : Creation. [DB]
- *
- *****************************************************************************/
- #include "frame.h"
- #include "povray.h"
- #include "vector.h"
- #include "povproto.h"
- #include "bbox.h"
- #include "polysolv.h"
- #include "matrices.h"
- #include "objects.h"
- #include "torus.h"
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
- /* Minimal depth for a valid intersection. */
- #define DEPTH_TOLERANCE 1.0e-4
- /* Tolerance used for order reduction during root finding. */
- #define ROOT_TOLERANCE 1.0e-4
- /*****************************************************************************
- * Static functions
- ******************************************************************************/
- static int intersect_torus (RAY *Ray, TORUS *Torus, DBL *Depth);
- static int All_Torus_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
- static int Inside_Torus (VECTOR point, OBJECT *Object);
- static void Torus_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
- static TORUS *Copy_Torus (OBJECT *Object);
- static void Translate_Torus (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
- static void Rotate_Torus (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
- static void Scale_Torus (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
- static void Transform_Torus (OBJECT *Object, TRANSFORM *Trans);
- static void Invert_Torus (OBJECT *Object);
- static void Destroy_Torus (OBJECT *Object);
- /*****************************************************************************
- * Local variables
- ******************************************************************************/
- static METHODS Torus_Methods =
- {
- All_Torus_Intersections, Inside_Torus, Torus_Normal,
- (COPY_METHOD)Copy_Torus, Translate_Torus, Rotate_Torus,
- Scale_Torus, Transform_Torus, Invert_Torus, Destroy_Torus
- };
- /*****************************************************************************
- *
- * FUNCTION
- *
- * All_Torus_Intersections
- *
- * INPUT
- *
- * Object - Object
- * Ray - Ray
- * Depth_Stack - Intersection stack
- *
- * OUTPUT
- *
- * Depth_Stack
- *
- * RETURNS
- *
- * int - TRUE, if an intersection was found
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Determine ray/torus intersection and clip intersection found.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
- static int All_Torus_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
- {
- int i, max_i, Found;
- DBL Depth[4];
- VECTOR IPoint;
- Found = FALSE;
- if ((max_i = intersect_torus(Ray, (TORUS *)Object, Depth)) > 0)
- {
- for (i = 0; i < max_i; i++)
- {
- if ((Depth[i] > DEPTH_TOLERANCE) && (Depth[i] < Max_Distance))
- {
- VEvaluateRay(IPoint, Ray->Initial, Depth[i], Ray->Direction);
- if (Point_In_Clip(IPoint, Object->Clip))
- {
- push_entry(Depth[i], IPoint, Object, Depth_Stack);
- Found = TRUE;
- }
- }
- }
- }
- return(Found);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * intersect_torus
- *
- * INPUT
- *
- * Ray - Ray
- * Torus - Torus
- * Depth - Intersections found
- *
- * OUTPUT
- *
- * Depth
- *
- * RETURNS
- *
- * int - Number of intersections found
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Determine ray/torus intersection.
- *
- * Note that the torus is rotated about the y-axis!
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
- static int intersect_torus(RAY *Ray, TORUS *Torus, DBL *Depth)
- {
- int i, n;
- DBL len, R2, Py2, Dy2, PDy2, k1, k2;
- DBL y1, y2, r1, r2;
- DBL c[5], r[4];
- VECTOR P, D;
- Increase_Counter(stats[Ray_Torus_Tests]);
- /* Transform the ray into the torus space. */
- MInvTransPoint(P, Ray->Initial, Torus->Trans);
- MInvTransDirection(D, Ray->Direction, Torus->Trans);
- VLength(len, D);
- VInverseScaleEq(D, len);
- i = 0;
- y1 = -Torus->r;
- y2 = Torus->r;
- r1 = Sqr(Torus->R - Torus->r);
- r2 = Sqr(Torus->R + Torus->r);
- #ifdef TORUS_EXTRA_STATS
- Increase_Counter(stats[Torus_Bound_Tests]);
- #endif
- if (Test_Thick_Cylinder(P, D, y1, y2, r1, r2))
- {
- #ifdef TORUS_EXTRA_STATS
- Increase_Counter(stats[Torus_Bound_Tests_Succeeded]);
- #endif
- R2 = Sqr(Torus->R);
- r2 = Sqr(Torus->r);
- Py2 = P[Y] * P[Y];
- Dy2 = D[Y] * D[Y];
- PDy2 = P[Y] * D[Y];
- k1 = P[X] * P[X] + P[Z] * P[Z] + Py2 - R2 - r2;
- k2 = P[X] * D[X] + P[Z] * D[Z] + PDy2;
- c[0] = 1.0;
- c[1] = 4.0 * k2;
- c[2] = 2.0 * (k1 + 2.0 * (k2 * k2 + R2 * Dy2));
- c[3] = 4.0 * (k2 * k1 + 2.0 * R2 * PDy2);
- c[4] = k1 * k1 + 4.0 * R2 * (Py2 - r2);
- n = Solve_Polynomial(4, c, r, Test_Flag(Torus, STURM_FLAG), ROOT_TOLERANCE);
- while(n--)
- {
- Depth[i++] = r[n] / len;
- }
- }
- if (i)
- {
- Increase_Counter(stats[Ray_Torus_Tests_Succeeded]);
- }
- return(i);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Inside_Torus
- *
- * INPUT
- *
- * IPoint - Intersection point
- * Object - Object
- *
- * OUTPUT
- *
- * RETURNS
- *
- * int - TRUE if inside
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Test if a point lies inside the torus.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
- static int Inside_Torus(VECTOR IPoint, OBJECT *Object)
- {
- DBL r, r2;
- VECTOR P;
- TORUS *Torus = (TORUS *)Object;
- /* Transform the point into the torus space. */
- MInvTransPoint(P, IPoint, Torus->Trans);
- r = sqrt(Sqr(P[X]) + Sqr(P[Z]));
- r2 = Sqr(P[Y]) + Sqr(r - Torus->R);
- if (r2 <= Sqr(Torus->r))
- {
- return(!Test_Flag(Torus, INVERTED_FLAG));
- }
- else
- {
- return(Test_Flag(Torus, INVERTED_FLAG));
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Torus_Normal
- *
- * INPUT
- *
- * Result - Normal vector
- * Object - Object
- * Inter - Intersection found
- *
- * OUTPUT
- *
- * Result
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Calculate the normal of the torus in a given point.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
- static void Torus_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
- {
- DBL dist;
- VECTOR P, N, M;
- TORUS *Torus = (TORUS *)Object;
- /* Transform the point into the torus space. */
- MInvTransPoint(P, Inter->IPoint, Torus->Trans);
- /* Get normal from derivatives. */
- dist = sqrt(P[X] * P[X] + P[Z] * P[Z]);
- if (dist > EPSILON)
- {
- M[X] = Torus->R * P[X] / dist;
- M[Y] = 0.0;
- M[Z] = Torus->R * P[Z] / dist;
- }
- else
- {
- Make_Vector(M, 0.0, 0.0, 0.0);
- }
- VSub(N, P, M);
- /* Transform the normalt out of the torus space. */
- MTransNormal(Result, N, Torus->Trans);
- VNormalize(Result, Result);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Translate_Torus
- *
- * INPUT
- *
- * Object - Object
- * Vector - Translation vector
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Translate a torus.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
- static void Translate_Torus(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
- {
- Transform_Torus(Object, Trans);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Rotate_Torus
- *
- * INPUT
- *
- * Object - Object
- * Vector - Rotation vector
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Rotate a torus.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
- static void Rotate_Torus(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
- {
- Transform_Torus(Object, Trans);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Scale_Torus
- *
- * INPUT
- *
- * Object - Object
- * Vector - Scaling vector
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Scale a torus.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
- static void Scale_Torus(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
- {
- Transform_Torus(Object, Trans);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Transform_Torus
- *
- * INPUT
- *
- * Object - Object
- * Trans - Transformation to apply
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Transform a torus and recalculate its bounding box.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
- static void Transform_Torus(OBJECT *Object, TRANSFORM *Trans)
- {
- Compose_Transforms(((TORUS *)Object)->Trans, Trans);
- Compute_Torus_BBox((TORUS *)Object);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Invert_Torus
- *
- * INPUT
- *
- * Object - Object
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Invert a torus.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
- static void Invert_Torus(OBJECT *Object)
- {
- Invert_Flag(Object, INVERTED_FLAG);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Create_Torus
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * TORUS * - new torus
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Create a new torus.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
- TORUS *Create_Torus()
- {
- TORUS *New;
- New = (TORUS *)POV_MALLOC(sizeof(TORUS), "torus");
- INIT_OBJECT_FIELDS(New,TORUS_OBJECT,&Torus_Methods)
- New->Trans = Create_Transform();
- New->R =
- New->r = 0.0;
- return (New);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Copy_Torus
- *
- * INPUT
- *
- * Object - Object
- *
- * OUTPUT
- *
- * RETURNS
- *
- * void * - New torus
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Copy a torus.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- * Sep 1994 : fixed memory leakage [DB]
- *
- ******************************************************************************/
- static TORUS *Copy_Torus(OBJECT *Object)
- {
- TORUS *New, *Torus = (TORUS *)Object;
- New = Create_Torus();
- /* Get rid of the transformation created in Create_Torus(). */
- Destroy_Transform(New->Trans);
- /* Copy torus. */
- *New = *Torus;
- New->Trans = Copy_Transform(Torus->Trans);
- return (New);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Destroy_Torus
- *
- * INPUT
- *
- * Object - Object
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Destroy a torus.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
- static void Destroy_Torus (OBJECT *Object)
- {
- Destroy_Transform(((TORUS *)Object)->Trans);
- POV_FREE (Object);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Compute_Torus_BBox
- *
- * INPUT
- *
- * Torus - Torus
- *
- * OUTPUT
- *
- * Torus
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Calculate the bounding box of a torus.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
- void Compute_Torus_BBox(TORUS *Torus)
- {
- DBL r1, r2;
- r1 = Torus->r;
- r2 = Torus->R + Torus->r;
- Make_BBox(Torus->BBox, -r2, -r1, -r2, 2.0 * r2, 2.0 * r1, 2.0 * r2);
- Recompute_BBox(&Torus->BBox, Torus->Trans);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Test_Thick_Cylinder
- *
- * INPUT
- *
- * P - Ray initial
- * D - Ray direction
- * h1 - Height 1
- * h2 - Height 2
- * r1 - Square of inner radius
- * r2 - Square of outer radius
- *
- * OUTPUT
- *
- * RETURNS
- *
- * int - TRUE, if hit
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Test if a given ray defined in the lathe's coordinate system
- * intersects a "thick" cylinder (rotated about y-axis).
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
- int Test_Thick_Cylinder(VECTOR P, VECTOR D, DBL h1, DBL h2, DBL r1, DBL r2)
- {
- DBL a, b, c, d;
- DBL u, v, k, r, h;
- if (fabs(D[Y]) < EPSILON)
- {
- if ((P[Y] < h1) || (P[Y] > h2))
- {
- return(FALSE);
- }
- }
- else
- {
- /* Intersect ray with the cap-plane. */
- k = (h2 - P[Y]) / D[Y];
- u = P[X] + k * D[X];
- v = P[Z] + k * D[Z];
- if ((k > EPSILON) && (k < Max_Distance))
- {
- r = u * u + v * v;
- if ((r >= r1) && (r <= r2))
- {
- return(TRUE);
- }
- }
- /* Intersectionersect ray with the base-plane. */
- k = (h1 - P[Y]) / D[Y];
- u = P[X] + k * D[X];
- v = P[Z] + k * D[Z];
- if ((k > EPSILON) && (k < Max_Distance))
- {
- r = u * u + v * v;
- if ((r >= r1) && (r <= r2))
- {
- return(TRUE);
- }
- }
- }
- a = D[X] * D[X] + D[Z] * D[Z];
- if (a > EPSILON)
- {
- /* Intersect with outer cylinder. */
- b = P[X] * D[X] + P[Z] * D[Z];
- c = P[X] * P[X] + P[Z] * P[Z] - r2;
- d = b * b - a * c;
- if (d >= 0.0)
- {
- d = sqrt(d);
- k = (-b + d) / a;
- if ((k > EPSILON) && (k < Max_Distance))
- {
- h = P[Y] + k * D[Y];
- if ((h >= h1) && (h <= h2))
- {
- return(TRUE);
- }
- }
- k = (-b - d) / a;
- if ((k > EPSILON) && (k < Max_Distance))
- {
- h = P[Y] + k * D[Y];
- if ((h >= h1) && (h <= h2))
- {
- return(TRUE);
- }
- }
- }
- /* Intersect with inner cylinder. */
- c = P[X] * P[X] + P[Z] * P[Z] - r1;
- d = b * b - a * c;
- if (d >= 0.0)
- {
- d = sqrt(d);
- k = (-b + d) / a;
- if ((k > EPSILON) && (k < Max_Distance))
- {
- h = P[Y] + k * D[Y];
- if ((h >= h1) && (h <= h2))
- {
- return(TRUE);
- }
- }
- k = (-b - d) / a;
- if ((k > EPSILON) && (k < Max_Distance))
- {
- h = P[Y] + k * D[Y];
- if ((h >= h1) && (h <= h2))
- {
- return(TRUE);
- }
- }
- }
- }
- return(FALSE);
- }
|