| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517 |
- /****************************************************************************
- * poly.c
- *
- * This module implements the code for general 3 variable polynomial shapes
- *
- * This file was written by Alexander Enzmann. He wrote the code for
- * 4th - 6th order shapes and generously provided us these enhancements.
- *
- * 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 "vector.h"
- #include "povproto.h"
- #include "bbox.h"
- #include "polysolv.h"
- #include "matrices.h"
- #include "objects.h"
- #include "poly.h"
- #include "povray.h"
- /*
- * Basic form of a quartic equation:
- *
- * a00*x^4 + a01*x^3*y + a02*x^3*z + a03*x^3 + a04*x^2*y^2 +
- * a05*x^2*y*z+ a06*x^2*y + a07*x^2*z^2 + a08*x^2*z + a09*x^2 +
- * a10*x*y^3 + a11*x*y^2*z + a12*x*y^2 + a13*x*y*z^2 + a14*x*y*z +
- * a15*x*y + a16*x*z^3 + a17*x*z^2 + a18*x*z + a19*x + a20*y^4 +
- * a21*y^3*z + a22*y^3 + a23*y^2*z^2 + a24*y^2*z + a25*y^2 + a26*y*z^3 +
- * a27*y*z^2 + a28*y*z + a29*y + a30*z^4 + a31*z^3 + a32*z^2 + a33*z + a34
- *
- */
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
- #define DEPTH_TOLERANCE 1.0e-4
- #define INSIDE_TOLERANCE 1.0e-4
- #define ROOT_TOLERANCE 1.0e-4
- #define COEFF_LIMIT 1.0e-20
- #define BINOMSIZE 40
- /*****************************************************************************
- * Local typedefs
- ******************************************************************************/
- /*****************************************************************************
- * Static functions
- ******************************************************************************/
- static int intersect (RAY *Ray, int Order, DBL *Coeffs, int Sturm_Flag, DBL *Depths);
- static void normal0 (VECTOR Result, int Order, DBL *Coeffs, VECTOR IPoint);
- static void normal1 (VECTOR Result, int Order, DBL *Coeffs, VECTOR IPoint);
- static DBL inside (VECTOR IPoint, int Order, DBL *Coeffs);
- static int intersect_linear (RAY *ray, DBL *Coeffs, DBL *Depths);
- static int intersect_quadratic (RAY *ray, DBL *Coeffs, DBL *Depths);
- static int factor_out (int n, int i, int *c, int *s);
- static long binomial (int n, int r);
- static void factor1 (int n, int *c, int *s);
- /* unused
- static DBL evaluate_linear (VECTOR P, DBL *a);
- static DBL evaluate_quadratic (VECTOR P, DBL *a);
- */
- static int All_Poly_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
- static int Inside_Poly (VECTOR IPoint, OBJECT *Object);
- static void Poly_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
- static POLY *Copy_Poly (OBJECT *Object);
- static void Translate_Poly (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
- static void Rotate_Poly (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
- static void Scale_Poly (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
- static void Transform_Poly (OBJECT *Object, TRANSFORM *Trans);
- static void Invert_Poly (OBJECT *Object);
- static void Destroy_Poly (OBJECT *Object);
- /*****************************************************************************
- * Local variables
- ******************************************************************************/
- METHODS Poly_Methods =
- {
- All_Poly_Intersections,
- Inside_Poly, Poly_Normal, (COPY_METHOD)Copy_Poly,
- Translate_Poly, Rotate_Poly,
- Scale_Poly, Transform_Poly, Invert_Poly, Destroy_Poly
- };
- /* The following table contains the binomial coefficients up to 15 */
- static int binomials[15][15] =
- {
- {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {1, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {1, 4, 6, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {1, 5, 10, 10, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {1, 6, 15, 20, 15, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0},
- {1, 7, 21, 35, 35, 21, 7, 1, 0, 0, 0, 0, 0, 0, 0},
- {1, 8, 28, 56, 70, 56, 28, 8, 1, 0, 0, 0, 0, 0, 0},
- {1, 9, 36, 84, 126, 126, 84, 36, 9, 1, 0, 0, 0, 0, 0},
- {1, 10, 45,120, 210, 252, 210, 120, 45, 10, 1, 0, 0, 0, 0},
- {1, 11, 55,165, 330, 462, 462, 330, 165, 55, 11, 1, 0, 0, 0},
- {1, 12, 66,220, 495, 792, 924, 792, 495, 220, 66, 12, 1, 0, 0},
- {1, 13, 78,286, 715,1287,1716,1716,1287, 715, 286, 78, 13, 1, 0},
- {1, 14, 91,364,1001,2002,3003,3432,3003,2002,1001,364, 91, 14, 1}
- };
- static DBL eqn_v[3][MAX_ORDER+1], eqn_vt[3][MAX_ORDER+1];
- /*****************************************************************************
- *
- * FUNCTION
- *
- * All_Poly_Intersections
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int All_Poly_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
- {
- POLY *Poly = (POLY *) Object;
- DBL Depths[MAX_ORDER], len;
- VECTOR IPoint;
- int cnt, i, j, Intersection_Found, same_root;
- RAY New_Ray;
- /* Transform the ray into the polynomial's space */
- MInvTransPoint(New_Ray.Initial, Ray->Initial, Poly->Trans);
- MInvTransDirection(New_Ray.Direction, Ray->Direction, Poly->Trans);
- VLength(len, New_Ray.Direction);
- VInverseScaleEq(New_Ray.Direction, len);
- Intersection_Found = FALSE;
- Increase_Counter(stats[Ray_Poly_Tests]);
- switch (Poly->Order)
- {
- case 1:
- cnt = intersect_linear(&New_Ray, Poly->Coeffs, Depths);
- break;
- case 2:
- cnt = intersect_quadratic(&New_Ray, Poly->Coeffs, Depths);
- break;
- default:
- cnt = intersect(&New_Ray, Poly->Order, Poly->Coeffs, Test_Flag(Poly, STURM_FLAG), Depths);
- }
- if (cnt > 0)
- {
- Increase_Counter(stats[Ray_Poly_Tests_Succeeded]);
- }
- for (i = 0; i < cnt; i++)
- {
- if (Depths[i] > DEPTH_TOLERANCE)
- {
- same_root = FALSE;
- for (j = 0; j < i; j++)
- {
- if (Depths[i] == Depths[j])
- {
- same_root = TRUE;
- break;
- }
- }
- if (!same_root)
- {
- VEvaluateRay(IPoint, New_Ray.Initial, Depths[i], New_Ray.Direction);
- /* Transform the point into world space */
- MTransPoint(IPoint, IPoint, Poly->Trans);
- if (Point_In_Clip(IPoint, Object->Clip))
- {
- push_entry(Depths[i] / len,IPoint,Object,Depth_Stack);
- Intersection_Found = TRUE;
- }
- }
- }
- }
- return (Intersection_Found);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * evaluate_linear
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- /* For speedup of low order polynomials, expand out the terms
- involved in evaluating the poly. */
- /* unused
- static DBL evaluate_linear(VECTOR P, DBL *a)
- {
- return(a[0] * P[X]) + (a[1] * P[Y]) + (a[2] * P[Z]) + a[3];
- }
- */
- /*****************************************************************************
- *
- * FUNCTION
- *
- * evaluate_quadratic
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- /*
- static DBL evaluate_quadratic(VECTOR P, DBL *a)
- {
- DBL x, y, z;
- x = P[X];
- y = P[Y];
- z = P[Z];
- return(a[0] * x * x + a[1] * x * y + a[2] * x * z +
- a[3] * x + a[4] * y * y + a[5] * y * z +
- a[6] * y + a[7] * z * z + a[8] * z + a[9]);
- }
- */
- /*****************************************************************************
- *
- * FUNCTION
- *
- * factor_out
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Remove all factors of i from n.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int factor_out(int n, int i, int *c, int *s)
- {
- while (!(n % i))
- {
- n /= i;
- s[(*c)++] = i;
- }
- return(n);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * factor1
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Find all prime factors of n. (Note that n must be less than 2^15.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void factor1(int n, int *c, int *s)
- {
- int i,k;
- /* First factor out any 2s. */
- n = factor_out(n, 2, c, s);
- /* Now any odd factors. */
- k = (int)sqrt((DBL)n) + 1;
- for (i = 3; (n > 1) && (i <= k); i += 2)
- {
- if (!(n % i))
- {
- n = factor_out(n, i, c, s);
- k = (int)sqrt((DBL)n)+1;
- }
- }
- if (n > 1)
- {
- s[(*c)++] = n;
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * binomial
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Calculate the binomial coefficent of n, r.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static long binomial(int n, int r)
- {
- int h,i,j,k,l;
- unsigned long result;
- static int stack1[BINOMSIZE], stack2[BINOMSIZE];
- if ((n < 0) || (r < 0) || (r > n))
- {
- result = 0L;
- }
- else
- {
- if (r == n)
- {
- result = 1L;
- }
- else
- {
- if ((r < 15) && (n < 15))
- {
- result = (long)binomials[n][r];
- }
- else
- {
- j = 0;
- for (i = r + 1; i <= n; i++)
- {
- stack1[j++] = i;
- }
- for (i = 2; i <= (n-r); i++)
- {
- h = 0;
- factor1(i, &h, stack2);
- for (k = 0; k < h; k++)
- {
- for (l = 0; l < j; l++)
- {
- if (!(stack1[l] % stack2[k]))
- {
- stack1[l] /= stack2[k];
- goto l1;
- }
- }
- }
- /* Error if we get here */
- /* Debug_Info("Failed to factor\n");*/
- l1:;
- }
- result = 1;
- for (i = 0; i < j; i++)
- {
- result *= stack1[i];
- }
- }
- }
- }
- return(result);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * inside
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static DBL inside(VECTOR IPoint, int Order, DBL *Coeffs)
- {
- DBL x[MAX_ORDER+1], y[MAX_ORDER+1];
- DBL z[MAX_ORDER+1], c, Result;
- int i, j, k, term;
- x[0] = 1.0; y[0] = 1.0; z[0] = 1.0;
- x[1] = IPoint[X]; y[1] = IPoint[Y]; z[1] = IPoint[Z];
- for (i = 2; i <= Order; i++)
- {
- x[i] = x[1] * x[i-1];
- y[i] = y[1] * y[i-1];
- z[i] = z[1] * z[i-1];
- }
- Result = 0.0;
- term = 0;
- for (i = Order; i >= 0; i--)
- {
- for (j=Order-i;j>=0;j--)
- {
- for (k=Order-(i+j);k>=0;k--)
- {
- if ((c = Coeffs[term]) != 0.0)
- {
- Result += c * x[i] * y[j] * z[k];
- }
- term++;
- }
- }
- }
- return(Result);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * intersect
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Intersection of a ray and an arbitrary polynomial function.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int intersect(RAY *ray, int Order, DBL *Coeffs, int Sturm_Flag, DBL *Depths)
- {
- DBL eqn[MAX_ORDER+1];
- DBL t[3][MAX_ORDER+1];
- VECTOR P, D;
- DBL val;
- int h, i, j, k, i1, j1, k1, term;
- int offset;
- /* First we calculate the values of the individual powers
- of x, y, and z as they are represented by the ray */
- Assign_Vector(P,ray->Initial);
- Assign_Vector(D,ray->Direction);
- for (i = 0; i < 3; i++)
- {
- eqn_v[i][0] = 1.0;
- eqn_vt[i][0] = 1.0;
- }
- eqn_v[0][1] = P[X];
- eqn_v[1][1] = P[Y];
- eqn_v[2][1] = P[Z];
- eqn_vt[0][1] = D[X];
- eqn_vt[1][1] = D[Y];
- eqn_vt[2][1] = D[Z];
- for (i = 2; i <= Order; i++)
- {
- for (j=0;j<3;j++)
- {
- eqn_v[j][i] = eqn_v[j][1] * eqn_v[j][i-1];
- eqn_vt[j][i] = eqn_vt[j][1] * eqn_vt[j][i-1];
- }
- }
- for (i = 0; i <= Order; i++)
- {
- eqn[i] = 0.0;
- }
- /* Now walk through the terms of the polynomial. As we go
- we substitute the ray equation for each of the variables. */
- term = 0;
- for (i = Order; i >= 0; i--)
- {
- for (h = 0; h <= i; h++)
- {
- t[0][h] = binomial(i, h) * eqn_vt[0][i-h] * eqn_v[0][h];
- }
- for (j = Order-i; j >= 0; j--)
- {
- for (h = 0; h <= j; h++)
- {
- t[1][h] = binomial(j, h) * eqn_vt[1][j-h] * eqn_v[1][h];
- }
- for (k = Order-(i+j); k >= 0; k--)
- {
- if (Coeffs[term] != 0)
- {
- for (h = 0; h <= k; h++)
- {
- t[2][h] = binomial(k, h) * eqn_vt[2][k-h] * eqn_v[2][h];
- }
- /* Multiply together the three polynomials. */
- offset = Order - (i + j + k);
- for (i1 = 0; i1 <= i; i1++)
- {
- for (j1=0;j1<=j;j1++)
- {
- for (k1=0;k1<=k;k1++)
- {
- h = offset + i1 + j1 + k1;
- val = Coeffs[term];
- val *= t[0][i1];
- val *= t[1][j1];
- val *= t[2][k1];
- eqn[h] += val;
- }
- }
- }
- }
- term++;
- }
- }
- }
- for (i = 0, j = Order; i <= Order; i++)
- {
- if (eqn[i] != 0.0)
- {
- break;
- }
- else
- {
- j--;
- }
- }
- if (j > 1)
- {
- return(Solve_Polynomial(j, &eqn[i], Depths, Sturm_Flag, ROOT_TOLERANCE));
- }
- else
- {
- return(0);
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * intersect_linear
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Intersection of a ray and a quadratic.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int intersect_linear(RAY *ray, DBL *Coeffs, DBL *Depths)
- {
- DBL t0, t1, *a = Coeffs;
- t0 = a[0] * ray->Initial[X] + a[1] * ray->Initial[Y] + a[2] * ray->Initial[Z];
- t1 = a[0] * ray->Direction[X] + a[1] * ray->Direction[Y] +
- a[2] * ray->Direction[Z];
- if (fabs(t1) < EPSILON)
- {
- return(0);
- }
- Depths[0] = -(a[3] + t0) / t1;
- return(1);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * intersect_quadratic
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Intersection of a ray and a quadratic.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int intersect_quadratic(RAY *ray, DBL *Coeffs, DBL *Depths)
- {
- DBL x, y, z, x2, y2, z2;
- DBL xx, yy, zz, xx2, yy2, zz2;
- DBL *a, ac, bc, cc, d, t;
- x = ray->Initial[X];
- y = ray->Initial[Y];
- z = ray->Initial[Z];
- xx = ray->Direction[X];
- yy = ray->Direction[Y];
- zz = ray->Direction[Z];
- x2 = x * x; y2 = y * y; z2 = z * z;
- xx2 = xx * xx; yy2 = yy * yy; zz2 = zz * zz;
- a = Coeffs;
- /*
- * Determine the coefficients of t^n, where the line is represented
- * as (x,y,z) + (xx,yy,zz)*t.
- */
- ac = (a[0]*xx2 + a[1]*xx*yy + a[2]*xx*zz + a[4]*yy2 + a[5]*yy*zz + a[7]*zz2);
- bc = (2*a[0]*x*xx + a[1]*(x*yy + xx*y) + a[2]*(x*zz + xx*z) +
- a[3]*xx + 2*a[4]*y*yy + a[5]*(y*zz + yy*z) + a[6]*yy +
- 2*a[7]*z*zz + a[8]*zz);
- cc = a[0]*x2 + a[1]*x*y + a[2]*x*z + a[3]*x + a[4]*y2 +
- a[5]*y*z + a[6]*y + a[7]*z2 + a[8]*z + a[9];
- if (fabs(ac) < COEFF_LIMIT)
- {
- if (fabs(bc) < COEFF_LIMIT)
- {
- return(0);
- }
- Depths[0] = -cc / bc;
- return(1);
- }
- /*
- * Solve the quadratic formula & return results that are
- * within the correct interval.
- */
- d = bc * bc - 4.0 * ac * cc;
- if (d < 0.0)
- {
- return(0);
- }
- d = sqrt(d);
- bc = -bc;
- t = 2.0 * ac;
- Depths[0] = (bc + d) / t;
- Depths[1] = (bc - d) / t;
- return(2);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * normal0
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Normal to a polynomial (used for polynomials with order > 4).
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void normal0(VECTOR Result, int Order, DBL *Coeffs, VECTOR IPoint)
- {
- int i, j, k, term;
- DBL val, *a, x[MAX_ORDER+1], y[MAX_ORDER+1], z[MAX_ORDER+1];
- x[0] = 1.0;
- y[0] = 1.0;
- z[0] = 1.0;
- x[1] = IPoint[X];
- y[1] = IPoint[Y];
- z[1] = IPoint[Z];
- for (i = 2; i <= Order; i++)
- {
- x[i] = IPoint[X] * x[i-1];
- y[i] = IPoint[Y] * y[i-1];
- z[i] = IPoint[Z] * z[i-1];
- }
- a = Coeffs;
- term = 0;
- Make_Vector(Result, 0.0, 0.0, 0.0);
- for (i = Order; i >= 0; i--)
- {
- for (j = Order-i; j >= 0; j--)
- {
- for (k = Order-(i+j); k >= 0; k--)
- {
- if (i >= 1)
- {
- val = x[i-1] * y[j] * z[k];
- Result[X] += i * a[term] * val;
- }
- if (j >= 1)
- {
- val = x[i] * y[j-1] * z[k];
- Result[Y] += j * a[term] * val;
- }
- if (k >= 1)
- {
- val = x[i] * y[j] * z[k-1];
- Result[Z] += k * a[term] * val;
- }
- term++;
- }
- }
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * nromal1
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Normal to a polynomial (for polynomials of order <= 4).
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void normal1(VECTOR Result, int Order, DBL *Coeffs, VECTOR IPoint)
- {
- DBL *a, x, y, z, x2, y2, z2, x3, y3, z3;
- a = Coeffs;
- x = IPoint[X];
- y = IPoint[Y];
- z = IPoint[Z];
- switch (Order)
- {
- case 1:
- /* Linear partial derivatives */
- Make_Vector(Result, a[0], a[1], a[2])
- break;
- case 2:
- /* Quadratic partial derivatives */
- Result[X] = 2*a[0]*x+a[1]*y+a[2]*z+a[3];
- Result[Y] = a[1]*x+2*a[4]*y+a[5]*z+a[6];
- Result[Z] = a[2]*x+a[5]*y+2*a[7]*z+a[8];
- break;
- case 3:
- x2 = x * x; y2 = y * y; z2 = z * z;
- /* Cubic partial derivatives */
- Result[X] = 3*a[0]*x2 + 2*x*(a[1]*y + a[2]*z + a[3]) + a[4]*y2 +
- y*(a[5]*z + a[6]) + a[7]*z2 + a[8]*z + a[9];
- Result[Y] = a[1]*x2 + x*(2*a[4]*y + a[5]*z + a[6]) + 3*a[10]*y2 +
- 2*y*(a[11]*z + a[12]) + a[13]*z2 + a[14]*z + a[15];
- Result[Z] = a[2]*x2 + x*(a[5]*y + 2*a[7]*z + a[8]) + a[11]*y2 +
- y*(2*a[13]*z + a[14]) + 3*a[16]*z2 + 2*a[17]*z + a[18];
- break;
- case 4:
- /* Quartic partial derivatives */
- x2 = x * x; y2 = y * y; z2 = z * z;
- x3 = x * x2; y3 = y * y2; z3 = z * z2;
- Result[X] = 4*a[ 0]*x3+3*x2*(a[ 1]*y+a[ 2]*z+a[ 3])+
- 2*x*(a[ 4]*y2+y*(a[ 5]*z+a[ 6])+a[ 7]*z2+a[ 8]*z+a[ 9])+
- a[10]*y3+y2*(a[11]*z+a[12])+y*(a[13]*z2+a[14]*z+a[15])+
- a[16]*z3+a[17]*z2+a[18]*z+a[19];
- Result[Y] = a[ 1]*x3+x2*(2*a[ 4]*y+a[ 5]*z+a[ 6])+
- x*(3*a[10]*y2+2*y*(a[11]*z+a[12])+a[13]*z2+a[14]*z+a[15])+
- 4*a[20]*y3+3*y2*(a[21]*z+a[22])+2*y*(a[23]*z2+a[24]*z+a[25])+
- a[26]*z3+a[27]*z2+a[28]*z+a[29];
- Result[Z] = a[ 2]*x3+x2*(a[ 5]*y+2*a[ 7]*z+a[ 8])+
- x*(a[11]*y2+y*(2*a[13]*z+a[14])+3*a[16]*z2+2*a[17]*z+a[18])+
- a[21]*y3+y2*(2*a[23]*z+a[24])+y*(3*a[26]*z2+2*a[27]*z+a[28])+
- 4*a[30]*z3+3*a[31]*z2+2*a[32]*z+a[33];
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Inside_Poly
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int Inside_Poly (VECTOR IPoint, OBJECT *Object)
- {
- VECTOR New_Point;
- DBL Result;
- /* Transform the point into polynomial's space */
- MInvTransPoint(New_Point, IPoint, ((POLY *)Object)->Trans);
- Result = inside(New_Point, ((POLY *)Object)->Order, ((POLY *)Object)->Coeffs);
- if (Result < INSIDE_TOLERANCE)
- {
- return ((int)(!Test_Flag(Object, INVERTED_FLAG)));
- }
- else
- {
- return ((int)Test_Flag(Object, INVERTED_FLAG));
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Poly_Normal
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Normal to a polynomial.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void Poly_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
- {
- DBL val;
- VECTOR New_Point;
- POLY *Shape = (POLY *)Object;
- /* Transform the point into the polynomials space. */
- MInvTransPoint(New_Point, Inter->IPoint, Shape->Trans);
- if (((POLY *)Object)->Order > 4)
- {
- normal0(Result, Shape->Order, Shape->Coeffs, New_Point);
- }
- else
- {
- normal1(Result, Shape->Order, Shape->Coeffs, New_Point);
- }
- /* Transform back to world space. */
- MTransNormal(Result, Result, Shape->Trans);
- /* Normalize (accounting for the possibility of a 0 length normal). */
- VDot(val, Result, Result);
- if (val > 0.0)
- {
- val = 1.0 / sqrt(val);
- VScaleEq(Result, val);
- }
- else
- {
- Make_Vector(Result, 1.0, 0.0, 0.0)
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Translate_Poly
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void Translate_Poly (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
- {
- Transform_Poly(Object, Trans);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Rotate_Poly
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void Rotate_Poly (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
- {
- Transform_Poly(Object, Trans);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Scale_Poly
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void Scale_Poly (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
- {
- Transform_Poly(Object, Trans);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Transform_Poly
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void Transform_Poly(OBJECT *Object,TRANSFORM *Trans)
- {
- Compose_Transforms(((POLY *)Object)->Trans, Trans);
- Compute_Poly_BBox((POLY *)Object);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Invert_Poly
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void Invert_Poly(OBJECT *Object)
- {
- Invert_Flag(Object, INVERTED_FLAG);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Create_Poly
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- POLY *Create_Poly(int Order)
- {
- POLY *New;
- int i;
- New = (POLY *)POV_MALLOC(sizeof (POLY), "poly");
- INIT_OBJECT_FIELDS(New,POLY_OBJECT, &Poly_Methods);
- New->Order = Order;
- New->Trans = Create_Transform();
- New->Coeffs = (DBL *)POV_MALLOC(term_counts(Order) * sizeof(DBL), "coefficients for POLY");
- for (i = 0; i < term_counts(Order); i++)
- {
- New->Coeffs[i] = 0.0;
- }
- return(New);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Copy_Poly
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Make a copy of a polynomial object.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static POLY *Copy_Poly(OBJECT *Object)
- {
- POLY *New;
- int i;
- New = Create_Poly (((POLY *)Object)->Order);
- /* Get rid of transform created in Create_Poly. */
- Destroy_Transform(New->Trans);
- Copy_Flag(New, Object, STURM_FLAG);
- Copy_Flag(New, Object, INVERTED_FLAG);
- New->Trans = Copy_Transform(((POLY *)Object)->Trans);
- for (i = 0; i < term_counts(New->Order); i++)
- {
- New->Coeffs[i] = ((POLY *)Object)->Coeffs[i];
- }
- return (New);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Destroy_Poly
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void Destroy_Poly(OBJECT *Object)
- {
- Destroy_Transform (((POLY *)Object)->Trans);
- POV_FREE (((POLY *)Object)->Coeffs);
- POV_FREE (Object);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Compute_Poly_BBox
- *
- * INPUT
- *
- * Poly - Poly
- *
- * OUTPUT
- *
- * Poly
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Calculate the bounding box of a poly.
- *
- * CHANGES
- *
- * Aug 1994 : Creation.
- *
- ******************************************************************************/
- void Compute_Poly_BBox(POLY *Poly)
- {
- Make_BBox(Poly->BBox, -BOUND_HUGE/2, -BOUND_HUGE/2, -BOUND_HUGE/2, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
- if (Poly->Clip != NULL)
- {
- Poly->BBox = Poly->Clip->BBox;
- }
- }
|