| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601 |
- /****************************************************************************
- * super.c
- *
- * This module implements functions that manipulate superellipsoids.
- *
- * Original code written by Alexander Enzmann.
- * Adaption to POV-Ray 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:
- *
- * Superellipsoids are defined by the implicit equation
- *
- * f(x,y,z) = (|x|^(2/e) + |y|^(2/e))^(e/n) + |z|^(2/n) - 1
- *
- * Where e is the east/west exponent and n is the north/south exponent.
- *
- * NOTE: The exponents are precomputed and stored in the Power element.
- *
- * NOTE: Values of e and n that are close to degenerate (e.g.,
- * below around 0.1) appear to give the root solver fits.
- * Not sure quite where the problem lays just yet.
- *
- * Syntax:
- *
- * superellipsoid { <e, n> }
- *
- *
- * ---
- *
- * Oct 1994 : Creation.
- *
- *****************************************************************************/
- #include "frame.h"
- #include "povray.h"
- #include "vector.h"
- #include "povproto.h"
- #include "bbox.h"
- #include "matrices.h"
- #include "objects.h"
- #include "super.h"
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
- /* Minimal intersection depth for a valid intersection. */
- #define DEPTH_TOLERANCE 1.0e-4
- /* If |x| < ZERO_TOLERANCE it is regarded to be 0. */
- #define ZERO_TOLERANCE 1.0e-10
- /* This is not the signum function because SGNX(0) is 1. */
- #define SGNX(x) (((x) >= 0.0) ? 1.0 : -1.0)
- #define MIN_VALUE -1.0
- #define MAX_VALUE 1.0
- #define MAX_ITERATIONS 20
- #define PLANECOUNT 9
- /*****************************************************************************
- * Local typedefs
- ******************************************************************************/
- /*****************************************************************************
- * Static functions
- ******************************************************************************/
- static int intersect_superellipsoid (RAY *Ray, SUPERELLIPSOID *Superellipsoid, ISTACK *Depth_Stack);
- static int intersect_box (VECTOR P, VECTOR D, DBL *dmin, DBL *dmax);
- static DBL power (DBL x, DBL e);
- static DBL evaluate_superellipsoid (VECTOR P, SUPERELLIPSOID *Superellipsoid);
- static int compdists (CONST void *in_a, CONST void *in_b);
- static int find_ray_plane_points (VECTOR P, VECTOR D, int cnt, DBL *dists, DBL mindist, DBL maxdist);
- static void solve_hit1 (SUPERELLIPSOID *Super, DBL v0, VECTOR tP0, DBL v1, VECTOR tP1, VECTOR P);
- static int check_hit2 (SUPERELLIPSOID *Super, VECTOR P, VECTOR D, DBL t0, VECTOR P0, DBL v0, DBL t1, DBL *t, VECTOR Q);
- static int insert_hit (OBJECT *Object, RAY *Ray, DBL Depth, ISTACK *Depth_Stack);
- static int All_Superellipsoid_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
- static int Inside_Superellipsoid (VECTOR point, OBJECT *Object);
- static void Superellipsoid_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
- static SUPERELLIPSOID *Copy_Superellipsoid (OBJECT *Object);
- static void Translate_Superellipsoid (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
- static void Rotate_Superellipsoid (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
- static void Scale_Superellipsoid (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
- static void Transform_Superellipsoid (OBJECT *Object, TRANSFORM *Trans);
- static void Invert_Superellipsoid (OBJECT *Object);
- static void Destroy_Superellipsoid (OBJECT *Object);
- /*****************************************************************************
- * Local variables
- ******************************************************************************/
- static METHODS Superellipsoid_Methods =
- {
- All_Superellipsoid_Intersections,
- Inside_Superellipsoid, Superellipsoid_Normal,
- (COPY_METHOD)Copy_Superellipsoid,
- Translate_Superellipsoid, Rotate_Superellipsoid,
- Scale_Superellipsoid, Transform_Superellipsoid, Invert_Superellipsoid, Destroy_Superellipsoid
- };
- static DBL planes[PLANECOUNT][4] =
- {{1, 1, 0, 0}, {1,-1, 0, 0},
- {1, 0, 1, 0}, {1, 0,-1, 0},
- {0, 1, 1, 0}, {0, 1,-1, 0},
- {1, 0, 0, 0},
- {0, 1, 0, 0},
- {0, 0, 1, 0}};
- /*****************************************************************************
- *
- * FUNCTION
- *
- * All_Superellipsoid_Intersections
- *
- * INPUT
- *
- * Object - Object
- * Ray - Ray
- * Depth_Stack - Intersection stack
- *
- * OUTPUT
- *
- * Depth_Stack
- *
- * RETURNS
- *
- * int - TRUE, if a intersection was found
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Determine ray/superellipsoid intersection and clip intersection found.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- static int All_Superellipsoid_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
- {
- Increase_Counter(stats[Ray_Superellipsoid_Tests]);
- if (intersect_superellipsoid(Ray, (SUPERELLIPSOID *)Object, Depth_Stack))
- {
- Increase_Counter(stats[Ray_Superellipsoid_Tests_Succeeded]);
- return(TRUE);
- }
- else
- {
- return(FALSE);
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * intersect_superellipsoid
- *
- * INPUT
- *
- * Ray - Ray
- * Superellipsoid - Superellipsoid
- * Depth_Stack - Depth stack
- *
- * OUTPUT
- *
- * Intersection
- *
- * RETURNS
- *
- * int - TRUE if intersections were found.
- *
- * AUTHOR
- *
- * Alexander Enzmann, Dieter Bayer
- *
- * DESCRIPTION
- *
- * Determine ray/superellipsoid intersection.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- static int intersect_superellipsoid(RAY *Ray, SUPERELLIPSOID *Superellipsoid, ISTACK *Depth_Stack)
- {
- int i, cnt, Found = FALSE;
- DBL dists[PLANECOUNT+2];
- DBL t, t1, t2, v0, v1, len;
- VECTOR P, D, P0, P1, P2, P3;
- /* Transform the ray into the superellipsoid space. */
- MInvTransPoint(P, Ray->Initial, Superellipsoid->Trans);
- MInvTransDirection(D, Ray->Direction, Superellipsoid->Trans);
- VLength(len, D);
- VInverseScaleEq(D, len);
- /* Intersect superellipsoid's bounding box. */
- if (!intersect_box(P, D, &t1, &t2))
- {
- return(FALSE);
- }
- /* Test if superellipsoid lies 'behind' the ray origin. */
- if (t2 < DEPTH_TOLERANCE)
- {
- return(FALSE);
- }
- cnt = 0;
- if (t1 < DEPTH_TOLERANCE)
- {
- t1 = DEPTH_TOLERANCE;
- }
- dists[cnt++] = t1;
- dists[cnt++] = t2;
- /* Intersect ray with planes cutting superellipsoids in pieces. */
- cnt = find_ray_plane_points(P, D, cnt, dists, t1, t2);
- if (cnt <= 1)
- {
- return(FALSE);
- }
- VEvaluateRay(P0, P, dists[0], D)
- v0 = evaluate_superellipsoid(P0, Superellipsoid);
- if (fabs(v0) < ZERO_TOLERANCE)
- {
- if (insert_hit((OBJECT *)Superellipsoid, Ray, dists[0] / len, Depth_Stack))
- {
- if (Superellipsoid->Type & IS_CHILD_OBJECT)
- {
- Found = TRUE;
- }
- else
- {
- return(TRUE);
- }
- }
- }
- for (i = 1; i < cnt; i++)
- {
- VEvaluateRay(P1, P, dists[i], D)
- v1 = evaluate_superellipsoid(P1, Superellipsoid);
- if (fabs(v1) < ZERO_TOLERANCE)
- {
- if (insert_hit((OBJECT *)Superellipsoid, Ray, dists[i] / len, Depth_Stack))
- {
- if (Superellipsoid->Type & IS_CHILD_OBJECT)
- {
- Found = TRUE;
- }
- else
- {
- return(TRUE);
- }
- }
- }
- else
- {
- if (v0 * v1 < 0.0)
- {
- /* Opposite signs, there must be a root between */
- solve_hit1(Superellipsoid, v0, P0, v1, P1, P2);
- VSub(P3, P2, P);
- VLength(t, P3);
- if (insert_hit((OBJECT *)Superellipsoid, Ray, t / len, Depth_Stack))
- {
- if (Superellipsoid->Type & IS_CHILD_OBJECT)
- {
- Found = TRUE;
- }
- else
- {
- return(TRUE);
- }
- }
- }
- else
- {
- /*
- * Although there was no sign change, we may actually be approaching
- * the surface. In this case, we are being fooled by the shape of the
- * surface into thinking there isn't a root between sample points.
- */
- if (check_hit2(Superellipsoid, P, D, dists[i-1], P0, v0, dists[i], &t, P2))
- {
- if (insert_hit((OBJECT *)Superellipsoid, Ray, t / len, Depth_Stack))
- {
- if (Superellipsoid->Type & IS_CHILD_OBJECT)
- {
- Found = TRUE;
- }
- else
- {
- return(TRUE);
- }
- }
- else
- {
- break;
- }
- }
- }
- }
- v0 = v1;
- Assign_Vector(P0, P1);
- }
- return(Found);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Inside_Superellipsoid
- *
- * INPUT
- *
- * IPoint - Intersection point
- * Object - Object
- *
- * OUTPUT
- *
- * RETURNS
- *
- * int - TRUE if inside
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Test if a point lies inside the superellipsoid.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- static int Inside_Superellipsoid(VECTOR IPoint, OBJECT *Object)
- {
- DBL val;
- VECTOR P;
- SUPERELLIPSOID *Superellipsoid = (SUPERELLIPSOID *)Object;
- /* Transform the point into the superellipsoid space. */
- MInvTransPoint(P, IPoint, Superellipsoid->Trans);
- val = evaluate_superellipsoid(P, Superellipsoid);
- if (val < EPSILON)
- {
- return(!Test_Flag(Superellipsoid, INVERTED_FLAG));
- }
- else
- {
- return(Test_Flag(Superellipsoid, INVERTED_FLAG));
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Superellipsoid_Normal
- *
- * INPUT
- *
- * Result - Normal vector
- * Object - Object
- * Inter - Intersection found
- *
- * OUTPUT
- *
- * Result
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Calculate the normal of the superellipsoid in a given point.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- static void Superellipsoid_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
- {
- DBL k, x, y, z;
- VECTOR P, N, E;
- SUPERELLIPSOID *Superellipsoid = (SUPERELLIPSOID *)Object;
- /* Transform the point into the superellipsoid space. */
- MInvTransPoint(P, Inter->IPoint, Superellipsoid->Trans);
- Assign_Vector(E, Superellipsoid->Power);
- x = fabs(P[X]);
- y = fabs(P[Y]);
- z = fabs(P[Z]);
- k = power(power(x, E[X]) + power(y, E[X]), E[Y] - 1.0);
- N[X] = k * SGNX(P[X]) * power(x, E[X] - 1.0);
- N[Y] = k * SGNX(P[Y]) * power(y, E[X] - 1.0);
- N[Z] = SGNX(P[Z]) * power(z, E[Z] - 1.0);
- /* Transform the normalt out of the superellipsoid space. */
- MTransNormal(Result, N, Superellipsoid->Trans);
- VNormalize(Result, Result);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Translate_Superellipsoid
- *
- * INPUT
- *
- * Object - Object
- * Vector - Translation vector
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Translate a superellipsoid.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- static void Translate_Superellipsoid(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
- {
- Transform_Superellipsoid(Object, Trans);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Rotate_Superellipsoid
- *
- * INPUT
- *
- * Object - Object
- * Vector - Rotation vector
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Rotate a superellipsoid.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- static void Rotate_Superellipsoid(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
- {
- Transform_Superellipsoid(Object, Trans);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Scale_Superellipsoid
- *
- * INPUT
- *
- * Object - Object
- * Vector - Scaling vector
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Scale a superellipsoid.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- static void Scale_Superellipsoid(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
- {
- Transform_Superellipsoid(Object, Trans);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Transform_Superellipsoid
- *
- * INPUT
- *
- * Object - Object
- * Trans - Transformation to apply
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Transform a superellipsoid and recalculate its bounding box.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- static void Transform_Superellipsoid(OBJECT *Object, TRANSFORM *Trans)
- {
- Compose_Transforms(((SUPERELLIPSOID *)Object)->Trans, Trans);
- Compute_Superellipsoid_BBox((SUPERELLIPSOID *)Object);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Invert_Superellipsoid
- *
- * INPUT
- *
- * Object - Object
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Invert a superellipsoid.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- static void Invert_Superellipsoid(OBJECT *Object)
- {
- Invert_Flag(Object, INVERTED_FLAG);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Create_Superellipsoid
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * SUPERELLIPSOID * - new superellipsoid
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Create a new superellipsoid.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- SUPERELLIPSOID *Create_Superellipsoid()
- {
- SUPERELLIPSOID *New;
- New = (SUPERELLIPSOID *)POV_MALLOC(sizeof(SUPERELLIPSOID), "superellipsoid");
- INIT_OBJECT_FIELDS(New,SUPERELLIPSOID_OBJECT,&Superellipsoid_Methods)
- New->Trans = Create_Transform();
- Make_Vector(New->Power, 2.0, 2.0, 2.0);
- return(New);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Copy_Superellipsoid
- *
- * INPUT
- *
- * Object - Object
- *
- * OUTPUT
- *
- * RETURNS
- *
- * void * - New superellipsoid
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Copy a superellipsoid structure.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- static SUPERELLIPSOID *Copy_Superellipsoid(OBJECT *Object)
- {
- SUPERELLIPSOID *New, *Superellipsoid = (SUPERELLIPSOID *)Object;
- New = Create_Superellipsoid();
- /* Get rid of the transformation created in Create_Superellipsoid(). */
- Destroy_Transform(New->Trans);
- /* Copy superellipsoid. */
- *New = *Superellipsoid;
- New->Trans = Copy_Transform(Superellipsoid->Trans);
- return(New);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Destroy_Superellipsoid
- *
- * INPUT
- *
- * Object - Object
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Destroy a superellipsoid.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- static void Destroy_Superellipsoid(OBJECT *Object)
- {
- SUPERELLIPSOID *Superellipsoid = (SUPERELLIPSOID *)Object;
- Destroy_Transform(Superellipsoid->Trans);
- POV_FREE (Object);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Compute_Superellipsoid_BBox
- *
- * INPUT
- *
- * Superellipsoid - Superellipsoid
- *
- * OUTPUT
- *
- * Superellipsoid
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Calculate the bounding box of a superellipsoid.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- void Compute_Superellipsoid_BBox(SUPERELLIPSOID *Superellipsoid)
- {
- Make_BBox(Superellipsoid->BBox, -1.0001, -1.0001, -1.0001, 2.0002, 2.0002, 2.0002);
- Recompute_BBox(&Superellipsoid->BBox, Superellipsoid->Trans);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * intersect_box
- *
- * INPUT
- *
- * P, D - Ray origin and direction
- * dmin, dmax - Intersection depths
- *
- * OUTPUT
- *
- * dmin, dmax
- *
- * RETURNS
- *
- * int - TRUE, if hit
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Intersect a ray with an axis aligned unit box.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- static int intersect_box(VECTOR P, VECTOR D, DBL *dmin, DBL *dmax)
- {
- DBL tmin = 0.0, tmax = 0.0;
- /* Left/right. */
- if (fabs(D[X]) > EPSILON)
- {
- if (D[X] > EPSILON)
- {
- *dmin = (MIN_VALUE - P[X]) / D[X];
- *dmax = (MAX_VALUE - P[X]) / D[X];
- if (*dmax < EPSILON) return(FALSE);
- }
- else
- {
- *dmax = (MIN_VALUE - P[X]) / D[X];
- if (*dmax < EPSILON) return(FALSE);
- *dmin = (MAX_VALUE - P[X]) / D[X];
- }
- if (*dmin > *dmax) return(FALSE);
- }
- else
- {
- if ((P[X] < MIN_VALUE) || (P[X] > MAX_VALUE))
- {
- return(FALSE);
- }
- *dmin = -BOUND_HUGE;
- *dmax = BOUND_HUGE;
- }
- /* Top/bottom. */
- if (fabs(D[Y]) > EPSILON)
- {
- if (D[Y] > EPSILON)
- {
- tmin = (MIN_VALUE - P[Y]) / D[Y];
- tmax = (MAX_VALUE - P[Y]) / D[Y];
- }
- else
- {
- tmax = (MIN_VALUE - P[Y]) / D[Y];
- tmin = (MAX_VALUE - P[Y]) / D[Y];
- }
- if (tmax < *dmax)
- {
- if (tmax < EPSILON) return(FALSE);
- if (tmin > *dmin)
- {
- if (tmin > tmax) return(FALSE);
- *dmin = tmin;
- }
- else
- {
- if (*dmin > tmax) return(FALSE);
- }
- *dmax = tmax;
- }
- else
- {
- if (tmin > *dmin)
- {
- if (tmin > *dmax) return(FALSE);
- *dmin = tmin;
- }
- }
- }
- else
- {
- if ((P[Y] < MIN_VALUE) || (P[Y] > MAX_VALUE))
- {
- return(FALSE);
- }
- }
- /* Front/back. */
- if (fabs(D[Z]) > EPSILON)
- {
- if (D[Z] > EPSILON)
- {
- tmin = (MIN_VALUE - P[Z]) / D[Z];
- tmax = (MAX_VALUE - P[Z]) / D[Z];
- }
- else
- {
- tmax = (MIN_VALUE - P[Z]) / D[Z];
- tmin = (MAX_VALUE - P[Z]) / D[Z];
- }
- if (tmax < *dmax)
- {
- if (tmax < EPSILON) return(FALSE);
- if (tmin > *dmin)
- {
- if (tmin > tmax) return(FALSE);
- *dmin = tmin;
- }
- else
- {
- if (*dmin > tmax) return(FALSE);
- }
- *dmax = tmax;
- }
- else
- {
- if (tmin > *dmin)
- {
- if (tmin > *dmax) return(FALSE);
- *dmin = tmin;
- }
- }
- }
- else
- {
- if ((P[Z] < MIN_VALUE) || (P[Z] > MAX_VALUE))
- {
- return(FALSE);
- }
- }
- *dmin = tmin;
- *dmax = tmax;
- return(TRUE);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * evaluate_superellipsoid
- *
- * INPUT
- *
- * P - Point to evaluate
- * Superellipsoid - Pointer to superellipsoid
- *
- * OUTPUT
- *
- * RETURNS
- *
- * DBL
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Get superellipsoid value in the given point.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- static DBL evaluate_superellipsoid(VECTOR P, SUPERELLIPSOID *Superellipsoid)
- {
- VECTOR V1;
- V1[X] = power(fabs(P[X]), Superellipsoid->Power[X]);
- V1[Y] = power(fabs(P[Y]), Superellipsoid->Power[X]);
- V1[Z] = power(fabs(P[Z]), Superellipsoid->Power[Z]);
- return(power(V1[X] + V1[Y], Superellipsoid->Power[Y]) + V1[Z] - 1.0);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * power
- *
- * INPUT
- *
- * x - Argument
- * e - Power
- *
- * OUTPUT
- *
- * RETURNS
- *
- * DBL
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Raise x to the power of e.
- *
- * CHANGES
- *
- * Oct 1994 : Creation.
- *
- ******************************************************************************/
- static DBL power(DBL x, DBL e)
- {
- register int i;
- register DBL b;
- b = x;
- i = (int)e;
- /* Test if we have an integer power. */
- if (e == (DBL)i)
- {
- switch (i)
- {
- case 0: return(1.0);
- case 1: return(b);
- case 2: return(Sqr(b));
- case 3: return(Sqr(b) * b);
- case 4: b *= b; return(Sqr(b));
- case 5: b *= b; return(Sqr(b) * x);
- case 6: b *= b; return(Sqr(b) * b);
- default: return(pow(x, e));
- }
- }
- else
- {
- return(pow(x, e));
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * insert_hit
- *
- * INPUT
- *
- * Object - Object
- * Ray - Ray
- * Depth - Intersection depth
- * Depth_Stack - Intersection stack
- *
- * OUTPUT
- *
- * Depth_Stack
- *
- * RETURNS
- *
- * int - TRUE, if intersection is valid
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Push an intersection onto the depth stack if it is valid.
- *
- * CHANGES
- *
- * Nov 1994 : Creation.
- *
- ******************************************************************************/
- static int insert_hit(OBJECT *Object, RAY *Ray, DBL Depth, ISTACK *Depth_Stack)
- {
- VECTOR IPoint;
- if ((Depth > DEPTH_TOLERANCE) && (Depth < Max_Distance))
- {
- VEvaluateRay(IPoint, Ray->Initial, Depth, Ray->Direction);
- if (Point_In_Clip(IPoint, Object->Clip))
- {
- push_entry(Depth, IPoint, Object, Depth_Stack);
- return(TRUE);
- }
- }
- return(FALSE);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * compdists
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Compare two slabs.
- *
- * CHANGES
- *
- * Nov 1994 : Creation.
- *
- ******************************************************************************/
- static int compdists(CONST void *in_a, CONST void *in_b)
- {
- DBL a, b;
- a = *((DBL *)in_a);
- b = *((DBL *)in_b);
- if (a < b)
- {
- return(-1);
- }
- if (a == b)
- {
- return(0);
- }
- else
- {
- return(1);
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * find_ray_plane_points
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Find all the places where the ray intersects the set of
- * subdividing planes through the superquadric. Return the
- * number of valid hits (within the bounding box).
- *
- * CHANGES
- *
- * Nov 1994 : Creation.
- *
- ******************************************************************************/
- static int find_ray_plane_points(VECTOR P, VECTOR D, int cnt, DBL *dists, DBL mindist, DBL maxdist)
- {
- int i;
- DBL t, d;
- /* Since min and max dist are the distance to two of the bounding planes
- we are considering, there is a high probablity of missing them due to
- round off error. Therefore we adjust min and max. */
- t = EPSILON * (maxdist - mindist);
- mindist -= t;
- maxdist += t;
- /* Check the sets of planes that cut apart the superquadric. */
- for (i = 0; i < PLANECOUNT; i++)
- {
- d = (D[0] * planes[i][0] + D[1] * planes[i][1] + D[2] * planes[i][2]);
- if (fabs(d) < EPSILON)
- {
- /* Can't possibly get a hit for this combination of ray and plane. */
- continue;
- }
- t = (planes[i][3] - (P[0] * planes[i][0] + P[1] * planes[i][1] + P[2] * planes[i][2])) / d;
- if ((t >= mindist) && (t <= maxdist))
- {
- dists[cnt++] = t;
- }
- }
- /* Sort the results for further processing. */
- QSORT((void *)(dists), (size_t)cnt, sizeof(DBL), compdists);
- return(cnt);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * solve_hit1
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Home in on the root of a superquadric using a combination of
- * secant and bisection methods. This routine requires that
- * the sign of the function be different at P0 and P1, it will
- * fail drastically if this isn't the case.
- *
- * CHANGES
- *
- * Nov 1994 : Creation.
- *
- ******************************************************************************/
- static void solve_hit1(SUPERELLIPSOID *Super, DBL v0, VECTOR tP0, DBL v1, VECTOR tP1, VECTOR P)
- {
- int i;
- DBL x, v2, v3;
- VECTOR P0, P1, P2, P3;
- Assign_Vector(P0, tP0);
- Assign_Vector(P1, tP1);
- /* The sign of v0 and v1 changes between P0 and P1, this
- means there is an intersection point in there somewhere. */
- for (i = 0; i < MAX_ITERATIONS; i++)
- {
- if (fabs(v0) < ZERO_TOLERANCE)
- {
- /* Near point is close enough to an intersection - just use it. */
- Assign_Vector(P, P0);
- break;
- }
- if (fabs(v1) < ZERO_TOLERANCE)
- {
- /* Far point is close enough to an intersection. */
- Assign_Vector(P, P1);
- break;
- }
- /* Look at the chord connecting P0 and P1. */
- /* Assume a line between the points. */
- x = fabs(v0) / fabs(v1 - v0);
- VSub(P2, P1, P0);
- VAddScaled(P2, P0, x, P2);
- v2 = evaluate_superellipsoid(P2, Super);
- /* Look at the midpoint between P0 and P1. */
- VSub(P3, P1, P0);
- VAddScaled(P3, P0, 0.5, P3);
- v3 = evaluate_superellipsoid(P3, Super);
- if (v0 * v2 > 0.0)
- {
- if (v1 * v2 > 0.0)
- {
- /* This should be impossible, since v0 and v1 were opposite signs,
- v2 must be either 0 or opposite in sign to either v0 or v1. */
- Error("internal failure in function solve_sq_hit1: %d, %g, %g, %g", i, v0, v1, v2);
- }
- else
- {
- if (v0 * v3 > 0.0)
- {
- if (x < 0.5)
- {
- Assign_Vector(P0, P3);
- }
- else
- {
- Assign_Vector(P0, P2);
- }
- }
- else
- {
- /* We can move both ends. */
- Assign_Vector(P0, P2);
- Assign_Vector(P1, P3);
- }
- }
- }
- else
- {
- if (v0 * v3 > 0.0)
- {
- /* We can move both ends. */
- Assign_Vector(P0, P3);
- Assign_Vector(P1, P2);
- }
- else
- {
- if (x < 0.5)
- {
- Assign_Vector(P1, P2);
- }
- else
- {
- Assign_Vector(P1, P3);
- }
- }
- }
- }
- if (i == MAX_ITERATIONS)
- {
- /* The loop never quite closed in on the result - just use the point
- closest to zero. This really shouldn't happen since the max number
- of iterations is enough to converge with straight bisection. */
- if (fabs(v0) < fabs(v1))
- {
- Assign_Vector(P, P0);
- }
- else
- {
- Assign_Vector(P, P1);
- }
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * check_hit2
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Try to find the root of a superquadric using Newtons method.
- *
- * CHANGES
- *
- * Nov 1994 : Creation.
- *
- ******************************************************************************/
- static int check_hit2(SUPERELLIPSOID *Super, VECTOR P, VECTOR D, DBL t0, VECTOR P0, DBL v0, DBL t1, DBL *t, VECTOR Q)
- {
- int i;
- DBL dt0, dt1, v1, deltat, maxdelta;
- VECTOR P1;
- dt0 = t0;
- dt1 = t0 + 0.0001 * (t1 - t0);
- maxdelta = t1 - t0;
- for (i = 0; (dt0 < t1) && (i < MAX_ITERATIONS); i++)
- {
- VEvaluateRay(P1, P, dt1, D)
- v1 = evaluate_superellipsoid(P1, Super);
- if (v0 * v1 < 0)
- {
- /* Found a crossing point, go back and use normal root solving. */
- solve_hit1(Super, v0, P0, v1, P1, Q);
- VSub(P0, Q, P);
- VLength(*t, P0);
- return(TRUE);
- }
- else
- {
- if (fabs(v1) < ZERO_TOLERANCE)
- {
- VEvaluateRay(Q, P, dt1, D)
- *t = dt1;
- return(TRUE);
- }
- else
- {
- if (((v0 > 0.0) && (v1 > v0)) || ((v0 < 0.0) && (v1 < v0)))
- {
- /* We definitely failed */
- break;
- }
- else
- {
- if (v1 == v0)
- {
- break;
- }
- else
- {
- deltat = v1 * (dt1 - dt0) / (v1 - v0);
- }
- }
- }
- }
- if (fabs(deltat) > maxdelta)
- {
- break;
- }
- v0 = v1;
- dt0 = dt1;
- dt1 -= deltat;
- }
- return(FALSE);
- }
|