| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271 |
- /****************************************************************************
- * bezier.c
- *
- * This module implements the code for Bezier bicubic patch shapes
- *
- * This file was written by Alexander Enzmann. He wrote the code for
- * bezier bicubic patches 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 "bezier.h"
- #include "matrices.h"
- #include "objects.h"
- #include "povray.h"
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
- #define BEZIER_EPSILON 1.0e-10
- #define BEZIER_TOLERANCE 1.0e-5
- /*****************************************************************************
- * Local typedefs
- ******************************************************************************/
- /*****************************************************************************
- * Static functions
- ******************************************************************************/
- static int InvertMatrix (VECTOR in[3], VECTOR out[3]);
- static void bezier_value (VECTOR(*Control_Points)[4][4], DBL u0, DBL v0, VECTOR P, VECTOR N);
- static int intersect_subpatch (BICUBIC_PATCH *, RAY *, VECTOR [3], DBL [3], DBL [3], DBL *, VECTOR , VECTOR , DBL *, DBL *);
- static void find_average (int, VECTOR *, VECTOR , DBL *);
- static int spherical_bounds_check (RAY *, VECTOR , DBL);
- static int intersect_bicubic_patch0 (RAY *, BICUBIC_PATCH *, ISTACK *);
- static DBL point_plane_distance (VECTOR , VECTOR , DBL *);
- static DBL determine_subpatch_flatness (VECTOR(*)[4][4]);
- static int flat_enough (BICUBIC_PATCH *, VECTOR(*)[4][4]);
- static void bezier_bounding_sphere (VECTOR(*)[4][4], VECTOR , DBL *);
- static int bezier_subpatch_intersect (RAY *, BICUBIC_PATCH *, VECTOR(*)[4][4], DBL, DBL, DBL, DBL, ISTACK *);
- static void bezier_split_left_right (VECTOR(*)[4][4], VECTOR(*)[4][4], VECTOR(*)[4][4]);
- static void bezier_split_up_down (VECTOR(*)[4][4], VECTOR(*)[4][4], VECTOR(*)[4][4]);
- static int bezier_subdivider (RAY *, BICUBIC_PATCH *, VECTOR(*)[4][4], DBL, DBL, DBL, DBL, int, ISTACK *);
- static void bezier_tree_deleter (BEZIER_NODE *Node);
- static BEZIER_NODE *bezier_tree_builder (BICUBIC_PATCH *Object, VECTOR(*Patch)[4][4], DBL u0, DBL u1, DBL v0, DBL v1, int depth);
- static int bezier_tree_walker (RAY *, BICUBIC_PATCH *, BEZIER_NODE *, ISTACK *);
- static BEZIER_NODE *create_new_bezier_node (void);
- static BEZIER_VERTICES *create_bezier_vertex_block (void);
- static BEZIER_CHILDREN *create_bezier_child_block (void);
- static int subpatch_normal (VECTOR v1, VECTOR v2, VECTOR v3, VECTOR Result, DBL *d);
- static int All_Bicubic_Patch_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
- static int Inside_Bicubic_Patch (VECTOR IPoint, OBJECT *Object);
- static void Bicubic_Patch_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
- static BICUBIC_PATCH *Copy_Bicubic_Patch (OBJECT *Object);
- static void Translate_Bicubic_Patch (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
- static void Rotate_Bicubic_Patch (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
- static void Scale_Bicubic_Patch (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
- static void Transform_Bicubic_Patch (OBJECT *Object, TRANSFORM *Trans);
- static void Invert_Bicubic_Patch (OBJECT *Object);
- static void Destroy_Bicubic_Patch (OBJECT *Object);
- /*****************************************************************************
- * Local variables
- ******************************************************************************/
- static METHODS Bicubic_Patch_Methods =
- {
- All_Bicubic_Patch_Intersections,
- Inside_Bicubic_Patch, Bicubic_Patch_Normal, (COPY_METHOD)Copy_Bicubic_Patch,
- Translate_Bicubic_Patch, Rotate_Bicubic_Patch,
- Scale_Bicubic_Patch, Transform_Bicubic_Patch, Invert_Bicubic_Patch,
- Destroy_Bicubic_Patch
- };
- static int max_depth_reached;
- static DBL C[4] = { 1.0, 3.0, 3.0, 1.0 };
- /*****************************************************************************
- *
- * FUNCTION
- *
- * create_new_bezier_node
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static BEZIER_NODE *create_new_bezier_node()
- {
- BEZIER_NODE *Node = (BEZIER_NODE *)POV_MALLOC(sizeof(BEZIER_NODE), "bezier node");
-
- Node->Data_Ptr = NULL;
- return (Node);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * create_bezier_vertex_block
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static BEZIER_VERTICES *create_bezier_vertex_block()
- {
- BEZIER_VERTICES *Vertices;
- Vertices = (BEZIER_VERTICES *)POV_MALLOC(sizeof(BEZIER_VERTICES), "bezier vertices");
-
- return (Vertices);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * create_bezier_child_block
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static BEZIER_CHILDREN *create_bezier_child_block()
- {
- BEZIER_CHILDREN *Children;
-
- Children = (BEZIER_CHILDREN *)POV_MALLOC(sizeof(BEZIER_CHILDREN), "bezier children");
-
- return (Children);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * bezier_tree_builder
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static BEZIER_NODE *bezier_tree_builder(BICUBIC_PATCH *Object, VECTOR (*Patch)[4][4], DBL u0, DBL u1, DBL v0, DBL v1, int depth)
- {
- VECTOR Lower_Left[4][4], Lower_Right[4][4];
- VECTOR Upper_Left[4][4], Upper_Right[4][4];
- BEZIER_CHILDREN *Children;
- BEZIER_VERTICES *Vertices;
- BEZIER_NODE *Node = create_new_bezier_node();
-
- if (depth > max_depth_reached)
- {
- max_depth_reached = depth;
- }
-
- /* Build the bounding sphere for this subpatch. */
-
- bezier_bounding_sphere(Patch, Node->Center, &(Node->Radius_Squared));
-
- /*
- * If the patch is close to being flat, then just perform
- * a ray-plane intersection test.
- */
-
- if (flat_enough(Object, Patch))
- {
- /* The patch is now flat enough to simply store the corners. */
-
- Node->Node_Type = BEZIER_LEAF_NODE;
-
- Vertices = create_bezier_vertex_block();
-
- Assign_Vector(Vertices->Vertices[0], (*Patch)[0][0]);
- Assign_Vector(Vertices->Vertices[1], (*Patch)[0][3]);
- Assign_Vector(Vertices->Vertices[2], (*Patch)[3][3]);
- Assign_Vector(Vertices->Vertices[3], (*Patch)[3][0]);
-
- Vertices->uvbnds[0] = u0;
- Vertices->uvbnds[1] = u1;
- Vertices->uvbnds[2] = v0;
- Vertices->uvbnds[3] = v1;
- Node->Data_Ptr = (void *)Vertices;
- }
- else
- {
- if (depth >= Object->U_Steps)
- {
- if (depth >= Object->V_Steps)
- {
- /* We are at the max recursion depth. Just store corners. */
-
- Node->Node_Type = BEZIER_LEAF_NODE;
-
- Vertices = create_bezier_vertex_block();
-
- Assign_Vector(Vertices->Vertices[0], (*Patch)[0][0]);
- Assign_Vector(Vertices->Vertices[1], (*Patch)[0][3]);
- Assign_Vector(Vertices->Vertices[2], (*Patch)[3][3]);
- Assign_Vector(Vertices->Vertices[3], (*Patch)[3][0]);
-
- Vertices->uvbnds[0] = u0;
- Vertices->uvbnds[1] = u1;
- Vertices->uvbnds[2] = v0;
- Vertices->uvbnds[3] = v1;
-
- Node->Data_Ptr = (void *)Vertices;
- }
- else
- {
- bezier_split_up_down(Patch, (VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Upper_Left);
-
- Node->Node_Type = BEZIER_INTERIOR_NODE;
-
- Children = create_bezier_child_block();
-
- Children->Children[0] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Lower_Left, u0, u1, v0, (v0 + v1) / 2.0, depth + 1);
- Children->Children[1] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Upper_Left, u0, u1, (v0 + v1) / 2.0, v1, depth + 1);
-
- Node->Count = 2;
-
- Node->Data_Ptr = (void *)Children;
- }
- }
- else
- {
- if (depth >= Object->V_Steps)
- {
- bezier_split_left_right(Patch, (VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Lower_Right);
-
- Node->Node_Type = BEZIER_INTERIOR_NODE;
-
- Children = create_bezier_child_block();
-
- Children->Children[0] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Lower_Left, u0, (u0 + u1) / 2.0, v0, v1, depth + 1);
- Children->Children[1] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Lower_Right, (u0 + u1) / 2.0, u1, v0, v1, depth + 1);
-
- Node->Count = 2;
-
- Node->Data_Ptr = (void *)Children;
- }
- else
- {
- bezier_split_left_right(Patch, (VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Lower_Right);
-
- bezier_split_up_down((VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Upper_Left);
-
- bezier_split_up_down((VECTOR(*)[4][4])Lower_Right, (VECTOR(*)[4][4])Lower_Right, (VECTOR(*)[4][4])Upper_Right);
-
- Node->Node_Type = BEZIER_INTERIOR_NODE;
-
- Children = create_bezier_child_block();
-
- Children->Children[0] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Lower_Left, u0, (u0 + u1) / 2.0, v0, (v0 + v1) / 2.0, depth + 1);
- Children->Children[1] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Upper_Left, u0, (u0 + u1) / 2.0, (v0 + v1) / 2.0, v1, depth + 1);
- Children->Children[2] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Lower_Right, (u0 + u1) / 2.0, u1, v0, (v0 + v1) / 2.0, depth + 1);
- Children->Children[3] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Upper_Right, (u0 + u1) / 2.0, u1, (v0 + v1) / 2.0, v1, depth + 1);
-
- Node->Count = 4;
-
- Node->Data_Ptr = (void *)Children;
- }
- }
- }
-
- return (Node);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * bezier_value
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Determine the position and normal at a single coordinate
- * point (u, v) on a Bezier patch.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void bezier_value(VECTOR (*Control_Points)[4][4], DBL u0, DBL v0, VECTOR P, VECTOR N)
- {
- int i, j;
- DBL c, t, ut, vt;
- DBL u[4], uu[4], v[4], vv[4];
- DBL du[4], duu[4], dv[4], dvv[4];
- VECTOR U1, V1;
-
- /* Calculate binomial coefficients times coordinate positions. */
-
- u[0] = 1.0; uu[0] = 1.0; du[0] = 0.0; duu[0] = 0.0;
- v[0] = 1.0; vv[0] = 1.0; dv[0] = 0.0; dvv[0] = 0.0;
- for (i = 1; i < 4; i++)
- {
- u[i] = u[i - 1] * u0; uu[i] = uu[i - 1] * (1.0 - u0);
- v[i] = v[i - 1] * v0; vv[i] = vv[i - 1] * (1.0 - v0);
- du[i] = i * u[i - 1]; duu[i] = -i * uu[i - 1];
- dv[i] = i * v[i - 1]; dvv[i] = -i * vv[i - 1];
- }
- /* Now evaluate position and tangents based on control points. */
- Make_Vector(P, 0, 0, 0);
- Make_Vector(U1, 0, 0, 0);
- Make_Vector(V1, 0, 0, 0);
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- c = C[i] * C[j];
-
- ut = u[i] * uu[3 - i];
- vt = v[j] * vv[3 - j];
-
- t = c * ut * vt;
-
- VAddScaledEq(P, t, (*Control_Points)[i][j]);
-
- t = c * vt * (du[i] * uu[3 - i] + u[i] * duu[3 - i]);
-
- VAddScaledEq(U1, t, (*Control_Points)[i][j]);
-
- t = c * ut * (dv[j] * vv[3 - j] + v[j] * dvv[3 - j]);
-
- VAddScaledEq(V1, t, (*Control_Points)[i][j]);
- }
- }
-
- /* Make the normal from the cross product of the tangents. */
-
- VCross(N, U1, V1);
-
- VDot(t, N, N);
-
- if (t > BEZIER_EPSILON)
- {
- t = 1.0 / sqrt(t);
-
- VScaleEq(N, t);
- }
- else
- {
- Make_Vector(N, 1, 0, 0)
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * subpatch_normal
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Calculate the normal to a subpatch (triangle) return the vector
- * <1.0 0.0 0.0> if the triangle is degenerate.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int subpatch_normal(VECTOR v1, VECTOR v2, VECTOR v3, VECTOR Result, DBL *d)
- {
- VECTOR V1, V2;
- DBL Length;
-
- VSub(V1, v1, v2);
- VSub(V2, v3, v2);
- VCross(Result, V1, V2);
- VLength(Length, Result);
- if (Length < BEZIER_EPSILON)
- {
- Make_Vector(Result, 1.0, 0.0, 0.0);
- *d = -1.0 * v1[X];
- return (0);
- }
- else
- {
- VInverseScale(Result, Result, Length);
- VDot(*d, Result, v1);
- *d = 0.0 - *d;
- return (1);
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * InvertMatrix
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int InvertMatrix(VECTOR in[3], VECTOR out[3])
- {
- int i;
- DBL det;
- out[0][X] = (in[1][Y] * in[2][Z] - in[1][Z] * in[2][Y]);
- out[1][X] = - (in[0][Y] * in[2][Z] - in[0][Z] * in[2][Y]);
- out[2][X] = (in[0][Y] * in[1][Z] - in[0][Z] * in[1][Y]);
- out[0][Y] = - (in[1][X] * in[2][Z] - in[1][Z] * in[2][X]);
- out[1][Y] = (in[0][X] * in[2][Z] - in[0][Z] * in[2][X]);
- out[2][Y] = - (in[0][X] * in[1][Z] - in[0][Z] * in[1][X]);
- out[0][Z] = (in[1][X] * in[2][Y] - in[1][Y] * in[2][X]);
- out[1][Z] = - (in[0][X] * in[2][Y] - in[0][Y] * in[2][X]);
- out[2][Z] = (in[0][X] * in[1][Y] - in[0][Y] * in[1][X]);
- det = in[0][X] * in[1][Y] * in[2][Z] +
- in[0][Y] * in[1][Z] * in[2][X] +
- in[0][Z] * in[1][X] * in[2][Y] -
- in[0][Z] * in[1][Y] * in[2][X] -
- in[0][X] * in[1][Z] * in[2][Y] -
- in[0][Y] * in[1][X] * in[2][Z];
- if (fabs(det) < BEZIER_EPSILON)
- {
- return (0);
- }
- det = 1.0 / det;
- for (i = 0; i < 3; i++)
- {
- VScaleEq(out[i], det)
- }
- return (1);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * intersect_subpatch
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int intersect_subpatch(BICUBIC_PATCH *Shape, RAY *ray, VECTOR V1[3], DBL uu[3], DBL vv[3], DBL *Depth, VECTOR P, VECTOR N, DBL *u, DBL *v)
- {
- DBL d, n, a, b, r;
- VECTOR B[3], IB[3], NN[3], Q, T1;
- VSub(B[0], V1[1], V1[0]);
- VSub(B[1], V1[2], V1[0]);
- VCross(B[2], B[0], B[1]);
- VDot(d, B[2], B[2]);
- if (d < BEZIER_EPSILON)
- {
- return (0);
- }
- d = 1.0 / sqrt(d);
- VScaleEq(B[2], d);
- /* Degenerate triangle. */
- if (!InvertMatrix(B, IB))
- {
- return (0);
- }
- VDot(d, ray->Direction, IB[2]);
- if (fabs(d) < BEZIER_EPSILON)
- {
- return (0);
- }
- VSub(Q, V1[0], ray->Initial);
- VDot(n, Q, IB[2]);
- *Depth = n / d;
- if (*Depth < BEZIER_TOLERANCE)
- {
- return (0);
- }
- VScale(T1, ray->Direction, *Depth);
- VAdd(P, ray->Initial, T1);
- VSub(Q, P, V1[0]);
- VDot(a, Q, IB[0]);
- VDot(b, Q, IB[1]);
- if ((a < 0.0) || (b < 0.0) || (a + b > 1.0))
- {
- return (0);
- }
- r = 1.0 - a - b;
- Make_Vector(N, 0.0, 0.0, 0.0);
- bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[0], vv[0], T1, NN[0]);
- bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[1], vv[1], T1, NN[1]);
- bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[2], vv[2], T1, NN[2]);
- VScale(T1, NN[0], r); VAddEq(N, T1);
- VScale(T1, NN[1], a); VAddEq(N, T1);
- VScale(T1, NN[2], b); VAddEq(N, T1);
- *u = r * uu[0] + a * uu[1] + b * uu[2];
- *v = r * vv[0] + a * vv[1] + b * vv[2];
- VDot(d, N, N);
- if (d > BEZIER_EPSILON)
- {
- d = 1.0 / sqrt(d);
- VScaleEq(N, d);
- }
- else
- {
- Make_Vector(N, 1, 0, 0);
- }
- return (1);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * find_average
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Find a sphere that contains all of the points in the list "vectors".
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void find_average(int vector_count, VECTOR *vectors, VECTOR center, DBL *radius)
- {
- int i;
- DBL r0, r1, xc = 0, yc = 0, zc = 0;
- DBL x0, y0, z0;
- for (i = 0; i < vector_count; i++)
- {
- xc += vectors[i][X];
- yc += vectors[i][Y];
- zc += vectors[i][Z];
- }
- xc /= (DBL)vector_count;
- yc /= (DBL)vector_count;
- zc /= (DBL)vector_count;
- r0 = 0.0;
- for (i = 0; i < vector_count; i++)
- {
- x0 = vectors[i][X] - xc;
- y0 = vectors[i][Y] - yc;
- z0 = vectors[i][Z] - zc;
- r1 = x0 * x0 + y0 * y0 + z0 * z0;
- if (r1 > r0)
- {
- r0 = r1;
- }
- }
- Make_Vector(center, xc, yc, zc);
- *radius = r0;
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * spherical_bounds_check
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int spherical_bounds_check(RAY *Ray, VECTOR center, DBL radius)
- {
- DBL x, y, z, dist1, dist2;
- x = center[X] - Ray->Initial[X];
- y = center[Y] - Ray->Initial[Y];
- z = center[Z] - Ray->Initial[Z];
- dist1 = x * x + y * y + z * z;
- if (dist1 < radius)
- {
- /* ray starts inside sphere - assume it intersects. */
- return (1);
- }
- else
- {
- dist2 = x*Ray->Direction[X] + y*Ray->Direction[Y] + z*Ray->Direction[Z];
- dist2 *= dist2;
- if ((dist2 > 0) && (dist1 - dist2 < radius))
- {
- return (1);
- }
- }
- return (0);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * bezier_bounding_sphere
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Find a sphere that bounds all of the control points of a Bezier patch.
- * The values returned are: the center of the bounding sphere, and the
- * square of the radius of the bounding sphere.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void bezier_bounding_sphere(VECTOR (*Patch)[4][4], VECTOR center, DBL *radius)
- {
- int i, j;
- DBL r0, r1, xc = 0, yc = 0, zc = 0;
- DBL x0, y0, z0;
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- xc += (*Patch)[i][j][X];
- yc += (*Patch)[i][j][Y];
- zc += (*Patch)[i][j][Z];
- }
- }
- xc /= 16.0;
- yc /= 16.0;
- zc /= 16.0;
- r0 = 0.0;
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- x0 = (*Patch)[i][j][X] - xc;
- y0 = (*Patch)[i][j][Y] - yc;
- z0 = (*Patch)[i][j][Z] - zc;
- r1 = x0 * x0 + y0 * y0 + z0 * z0;
- if (r1 > r0)
- {
- r0 = r1;
- }
- }
- }
- Make_Vector(center, xc, yc, zc);
- *radius = r0;
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Precompute_Patch_Values
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Precompute grid points and normals for a bezier patch.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- void Precompute_Patch_Values(BICUBIC_PATCH *Shape)
- {
- int i, j;
- VECTOR Control_Points[16];
- VECTOR(*Patch_Ptr)[4][4] = (VECTOR(*)[4][4]) Shape->Control_Points;
- /* Calculate the bounding sphere for the entire patch. */
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- Assign_Vector(Control_Points[4*i + j], Shape->Control_Points[i][j]);
- }
- }
- find_average(16, Control_Points, Shape->Bounding_Sphere_Center, &Shape->Bounding_Sphere_Radius);
- if (Shape->Patch_Type != 0)
- {
- if (Shape->Node_Tree != NULL)
- {
- bezier_tree_deleter(Shape->Node_Tree);
- }
- Shape->Node_Tree = bezier_tree_builder(Shape, Patch_Ptr, 0.0, 1.0, 0.0, 1.0, 0);
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * point_plane_distance
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Determine the distance from a point to a plane.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static DBL point_plane_distance(VECTOR p, VECTOR n, DBL *d)
- {
- DBL temp1, temp2;
- VDot(temp1, p, n);
- temp1 += *d;
- VLength(temp2, n);
- if (fabs(temp2) < EPSILON)
- {
- return (0.0);
- }
- temp1 /= temp2;
- return (temp1);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * bezier_subpatch_intersect
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int bezier_subpatch_intersect(RAY *ray, BICUBIC_PATCH *Shape, VECTOR (*Patch)[4][4], DBL u0, DBL u1, DBL v0, DBL v1, ISTACK *Depth_Stack)
- {
- int cnt = 0;
- VECTOR V1[3];
- DBL u, v, Depth, uu[3], vv[3];
- VECTOR P, N;
- Assign_Vector(V1[0], (*Patch)[0][0]);
- Assign_Vector(V1[1], (*Patch)[0][3]);
- Assign_Vector(V1[2], (*Patch)[3][3]);
- uu[0] = u0; uu[1] = u0; uu[2] = u1;
- vv[0] = v0; vv[1] = v1; vv[2] = v1;
- if (intersect_subpatch(Shape, ray, V1, uu, vv, &Depth, P, N, &u, &v))
- {
- push_normal_entry(Depth, P, N, (OBJECT *)Shape, Depth_Stack);
- cnt++;
- }
- Assign_Vector(V1[1], V1[2]);
- Assign_Vector(V1[2], (*Patch)[3][0]);
- uu[1] = uu[2]; uu[2] = u1;
- vv[1] = vv[2]; vv[2] = v0;
- if (intersect_subpatch(Shape, ray, V1, uu, vv, &Depth, P, N, &u, &v))
- {
- push_normal_entry(Depth, P, N, (OBJECT *)Shape, Depth_Stack);
- cnt++;
- }
- return (cnt);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * bezier_split_left_right
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void bezier_split_left_right(VECTOR (*Patch)[4][4], VECTOR (*Left_Patch)[4][4], VECTOR (*Right_Patch)[4][4])
- {
- int i, j;
- VECTOR Temp1[4], Temp2[4], Half;
- for (i = 0; i < 4; i++)
- {
- Assign_Vector(Temp1[0], (*Patch)[0][i]);
- VHalf(Temp1[1], (*Patch)[0][i], (*Patch)[1][i]);
- VHalf(Half, (*Patch)[1][i], (*Patch)[2][i]);
- VHalf(Temp1[2], Temp1[1], Half);
- VHalf(Temp2[2], (*Patch)[2][i], (*Patch)[3][i]);
- VHalf(Temp2[1], Half, Temp2[2]);
- VHalf(Temp1[3], Temp1[2], Temp2[1]);
- Assign_Vector(Temp2[0], Temp1[3]);
- Assign_Vector(Temp2[3], (*Patch)[3][i]);
- for (j = 0; j < 4; j++)
- {
- Assign_Vector((*Left_Patch)[j][i], Temp1[j]);
- Assign_Vector((*Right_Patch)[j][i], Temp2[j]);
- }
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * bezier_split_up_down
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void bezier_split_up_down(VECTOR (*Patch)[4][4], VECTOR (*Bottom_Patch)[4][4], VECTOR (*Top_Patch)[4][4])
- {
- int i, j;
- VECTOR Temp1[4], Temp2[4], Half;
- for (i = 0; i < 4; i++)
- {
- Assign_Vector(Temp1[0], (*Patch)[i][0]);
- VHalf(Temp1[1], (*Patch)[i][0], (*Patch)[i][1]);
- VHalf(Half, (*Patch)[i][1], (*Patch)[i][2]);
- VHalf(Temp1[2], Temp1[1], Half);
- VHalf(Temp2[2], (*Patch)[i][2], (*Patch)[i][3]);
- VHalf(Temp2[1], Half, Temp2[2]);
- VHalf(Temp1[3], Temp1[2], Temp2[1]);
- Assign_Vector(Temp2[0], Temp1[3]);
- Assign_Vector(Temp2[3], (*Patch)[i][3]);
- for (j = 0; j < 4; j++)
- {
- Assign_Vector((*Bottom_Patch)[i][j], Temp1[j]);
- Assign_Vector((*Top_Patch)[i][j] , Temp2[j]);
- }
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * determine_subpatch_flatness
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * See how close to a plane a subpatch is, the patch must have at least
- * three distinct vertices. A negative result from this function indicates
- * that a degenerate value of some sort was encountered.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static DBL determine_subpatch_flatness(VECTOR (*Patch)[4][4])
- {
- int i, j;
- DBL d, dist, temp1;
- VECTOR vertices[4], n, TempV;
- Assign_Vector(vertices[0], (*Patch)[0][0]);
- Assign_Vector(vertices[1], (*Patch)[0][3]);
- VSub(TempV, vertices[0], vertices[1]);
- VLength(temp1, TempV);
- if (fabs(temp1) < EPSILON)
- {
- /*
- * Degenerate in the V direction for U = 0. This is ok if the other
- * two corners are distinct from the lower left corner - I'm sure there
- * are cases where the corners coincide and the middle has good values,
- * but that is somewhat pathalogical and won't be considered.
- */
- Assign_Vector(vertices[1], (*Patch)[3][3]);
- VSub(TempV, vertices[0], vertices[1]);
- VLength(temp1, TempV);
- if (fabs(temp1) < EPSILON)
- {
- return (-1.0);
- }
- Assign_Vector(vertices[2], (*Patch)[3][0]);
- VSub(TempV, vertices[0], vertices[1]);
- VLength(temp1, TempV);
- if (fabs(temp1) < EPSILON)
- {
- return (-1.0);
- }
- VSub(TempV, vertices[1], vertices[2]);
- VLength(temp1, TempV);
- if (fabs(temp1) < EPSILON)
- {
- return (-1.0);
- }
- }
- else
- {
- Assign_Vector(vertices[2], (*Patch)[3][0]);
- VSub(TempV, vertices[0], vertices[1]);
- VLength(temp1, TempV);
- if (fabs(temp1) < EPSILON)
- {
- Assign_Vector(vertices[2], (*Patch)[3][3]);
- VSub(TempV, vertices[0], vertices[2]);
- VLength(temp1, TempV);
- if (fabs(temp1) < EPSILON)
- {
- return (-1.0);
- }
- VSub(TempV, vertices[1], vertices[2]);
- VLength(temp1, TempV);
- if (fabs(temp1) < EPSILON)
- {
- return (-1.0);
- }
- }
- else
- {
- VSub(TempV, vertices[1], vertices[2]);
- VLength(temp1, TempV);
- if (fabs(temp1) < EPSILON)
- {
- return (-1.0);
- }
- }
- }
- /*
- * Now that a good set of candidate points has been found,
- * find the plane equations for the patch.
- */
- if (subpatch_normal(vertices[0], vertices[1], vertices[2], n, &d))
- {
- /*
- * Step through all vertices and see what the maximum
- * distance from the plane happens to be.
- */
- dist = 0.0;
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- temp1 = fabs(point_plane_distance(((*Patch)[i][j]), n, &d));
- if (temp1 > dist)
- {
- dist = temp1;
- }
- }
- }
- return (dist);
- }
- else
- {
- /*
- Debug_Info("Subpatch normal failed in determine_subpatch_flatness\n");
- */
- return (-1.0);
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * flat_enough
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int flat_enough(BICUBIC_PATCH *Object, VECTOR (*Patch)[4][4])
- {
- DBL Dist;
- Dist = determine_subpatch_flatness(Patch);
- if (Dist < 0.0)
- {
- return (0);
- }
- else
- {
- if (Dist < Object->Flatness_Value)
- {
- return (1);
- }
- else
- {
- return (0);
- }
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * bezier_subdivider
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int bezier_subdivider(RAY *Ray, BICUBIC_PATCH *Object, VECTOR (*Patch)[4][4], DBL u0, DBL u1, DBL v0, DBL v1,
- int recursion_depth, ISTACK *Depth_Stack)
- {
- int cnt = 0;
- DBL ut, vt, radius;
- VECTOR Lower_Left[4][4], Lower_Right[4][4];
- VECTOR Upper_Left[4][4], Upper_Right[4][4];
- VECTOR center;
- /*
- * Make sure the ray passes through a sphere bounding
- * the control points of the patch.
- */
- bezier_bounding_sphere(Patch, center, &radius);
- if (!spherical_bounds_check(Ray, center, radius))
- {
- return (0);
- }
- /*
- * If the patch is close to being flat, then just
- * perform a ray-plane intersection test.
- */
- if (flat_enough(Object, Patch))
- {
- return bezier_subpatch_intersect(Ray, Object, Patch, u0, u1, v0, v1, Depth_Stack);
- }
- if (recursion_depth >= Object->U_Steps)
- {
- if (recursion_depth >= Object->V_Steps)
- {
- return bezier_subpatch_intersect(Ray, Object, Patch, u0, u1, v0, v1, Depth_Stack);
- }
- else
- {
- bezier_split_up_down(Patch, (VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Upper_Left);
- vt = (v1 + v0) / 2.0;
- cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Lower_Left, u0, u1, v0, vt, recursion_depth + 1, Depth_Stack);
- cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Upper_Left, u0, u1, vt, v1, recursion_depth + 1, Depth_Stack);
- }
- }
- else
- {
- if (recursion_depth >= Object->V_Steps)
- {
- bezier_split_left_right(Patch, (VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Lower_Right);
- ut = (u1 + u0) / 2.0;
- cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Lower_Left, u0, ut, v0, v1, recursion_depth + 1, Depth_Stack);
- cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Lower_Right, ut, u1, v0, v1, recursion_depth + 1, Depth_Stack);
- }
- else
- {
- ut = (u1 + u0) / 2.0;
- vt = (v1 + v0) / 2.0;
- bezier_split_left_right(Patch, (VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Lower_Right);
- bezier_split_up_down((VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Upper_Left) ;
- bezier_split_up_down((VECTOR(*)[4][4])Lower_Right, (VECTOR(*)[4][4])Lower_Right, (VECTOR(*)[4][4])Upper_Right);
- cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Lower_Left, u0, ut, v0, vt, recursion_depth + 1, Depth_Stack);
- cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Upper_Left, u0, ut, vt, v1, recursion_depth + 1, Depth_Stack);
- cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Lower_Right, ut, u1, v0, vt, recursion_depth + 1, Depth_Stack);
- cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Upper_Right, ut, u1, vt, v1, recursion_depth + 1, Depth_Stack);
- }
- }
- return (cnt);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * bezier_tree_deleter
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void bezier_tree_deleter(BEZIER_NODE *Node)
- {
- int i;
- BEZIER_CHILDREN *Children;
- /* If this is an interior node then continue the descent. */
- if (Node->Node_Type == BEZIER_INTERIOR_NODE)
- {
- Children = (BEZIER_CHILDREN *)Node->Data_Ptr;
- for (i = 0; i < Node->Count; i++)
- {
- bezier_tree_deleter(Children->Children[i]);
- }
- POV_FREE(Children);
- }
- else
- {
- if (Node->Node_Type == BEZIER_LEAF_NODE)
- {
- /* Free the memory used for the vertices. */
- POV_FREE(Node->Data_Ptr);
- }
- }
- /* Free the memory used for the node. */
- POV_FREE(Node);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * bezier_tree_walker
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int bezier_tree_walker(RAY *Ray, BICUBIC_PATCH *Shape, BEZIER_NODE *Node, ISTACK *Depth_Stack)
- {
- int i, cnt = 0;
- DBL Depth, u, v, uu[3], vv[3];
- VECTOR N, P, V1[3];
- BEZIER_CHILDREN *Children;
- BEZIER_VERTICES *Vertices;
- /*
- * Make sure the ray passes through a sphere bounding
- * the control points of the patch.
- */
- if (!spherical_bounds_check(Ray, Node->Center, Node->Radius_Squared))
- {
- return (0);
- }
- /*
- * If this is an interior node then continue the descent,
- * else do a check against the vertices.
- */
- if (Node->Node_Type == BEZIER_INTERIOR_NODE)
- {
- Children = (BEZIER_CHILDREN *)Node->Data_Ptr;
- for (i = 0; i < Node->Count; i++)
- {
- cnt += bezier_tree_walker(Ray, Shape, Children->Children[i], Depth_Stack);
- }
- }
- else if (Node->Node_Type == BEZIER_LEAF_NODE)
- {
- Vertices = (BEZIER_VERTICES *)Node->Data_Ptr;
- Assign_Vector(V1[0], Vertices->Vertices[0]);
- Assign_Vector(V1[1], Vertices->Vertices[1]);
- Assign_Vector(V1[2], Vertices->Vertices[2]);
- uu[0] = Vertices->uvbnds[0];
- uu[1] = Vertices->uvbnds[0];
- uu[2] = Vertices->uvbnds[1];
- vv[0] = Vertices->uvbnds[2];
- vv[1] = Vertices->uvbnds[3];
- vv[2] = Vertices->uvbnds[3];
- /*
- * Triangulate this subpatch, then check for
- * intersections in the triangles.
- */
- if (intersect_subpatch(Shape, Ray, V1, uu, vv, &Depth, P, N, &u, &v))
- {
- push_normal_entry(Depth, P, N, (OBJECT *)Shape, Depth_Stack);
- cnt++;
- }
- Assign_Vector(V1[1], V1[2]);
- Assign_Vector(V1[2], Vertices->Vertices[3]);
- uu[1] = uu[2]; uu[2] = Vertices->uvbnds[1];
- vv[1] = vv[2]; vv[2] = Vertices->uvbnds[2];
- if (intersect_subpatch(Shape, Ray, V1, uu, vv, &Depth, P, N, &u, &v))
- {
- push_normal_entry(Depth, P, N, (OBJECT *)Shape, Depth_Stack);
- cnt++;
- }
- }
- else
- {
- Error("Bad Node type in bezier_tree_walker().\n");
- }
- return (cnt);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * intersect_bicubic_patch0
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int intersect_bicubic_patch0(RAY *Ray, BICUBIC_PATCH *Shape, ISTACK *Depth_Stack)
- {
- VECTOR(*Patch)[4][4] = (VECTOR(*)[4][4]) Shape->Control_Points;
-
- return (bezier_subdivider(Ray, Shape, Patch, 0.0, 1.0, 0.0, 1.0, 0, Depth_Stack));
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * All_Bicubic_Patch_Intersections
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int All_Bicubic_Patch_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
- {
- int Found, cnt = 0;
- Found = FALSE;
- Increase_Counter(stats[Ray_Bicubic_Tests]);
- switch (((BICUBIC_PATCH *)Object)->Patch_Type)
- {
- case 0:
- cnt = intersect_bicubic_patch0(Ray, ((BICUBIC_PATCH *)Object), Depth_Stack);
- break;
- case 1:
- cnt = bezier_tree_walker(Ray, (BICUBIC_PATCH *)Object, ((BICUBIC_PATCH *)Object)->Node_Tree, Depth_Stack);
- break;
- default:
- Error("Bad patch type in All_Bicubic_Patch_Intersections.\n");
- }
-
- if (cnt > 0)
- {
- Increase_Counter(stats[Ray_Bicubic_Tests_Succeeded]);
-
- Found = TRUE;
- }
-
- return (Found);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Inside_Bicubic_Patch
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * A patch is not a solid, so an inside test doesn't make sense.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static int Inside_Bicubic_Patch(VECTOR IPoint, OBJECT *Object)
- {
- return (0);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Bicubic_Patch_Normal
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void Bicubic_Patch_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
- {
- /* Use preocmputed normal. */
- Assign_Vector(Result, Inter->INormal);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Translate_Bicubic_Patch
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void Translate_Bicubic_Patch(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
- {
- int i, j;
- BICUBIC_PATCH *Patch = (BICUBIC_PATCH *) Object;
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- VAdd(Patch->Control_Points[i][j], Patch->Control_Points[i][j], Vector)
- }
- }
- Precompute_Patch_Values(Patch);
- Compute_Bicubic_Patch_BBox(Patch);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Rotate_Bicubic_Patch
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void Rotate_Bicubic_Patch(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
- {
- Transform_Bicubic_Patch(Object, Trans);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Scale_Bicubic_Patch
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void Scale_Bicubic_Patch(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
- {
- int i, j;
- BICUBIC_PATCH *Patch = (BICUBIC_PATCH *) Object;
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- VEvaluate(Patch->Control_Points[i][j], Patch->Control_Points[i][j], Vector);
- }
- }
- Precompute_Patch_Values(Patch);
- Compute_Bicubic_Patch_BBox(Patch);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Transform_Bicubic_Patch
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void Transform_Bicubic_Patch(OBJECT *Object, TRANSFORM *Trans)
- {
- int i, j;
- BICUBIC_PATCH *Patch = (BICUBIC_PATCH *) Object;
-
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- MTransPoint(Patch->Control_Points[i][j], Patch->Control_Points[i][j], Trans);
- }
- }
-
- Precompute_Patch_Values(Patch);
-
- Compute_Bicubic_Patch_BBox(Patch);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Invert_Bicubic_Patch
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * Inversion of a patch really doesn't make sense.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void Invert_Bicubic_Patch(OBJECT *Object)
- {
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Create_Bicubic_Patch
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- BICUBIC_PATCH *Create_Bicubic_Patch()
- {
- BICUBIC_PATCH *New;
-
- New = (BICUBIC_PATCH *)POV_MALLOC(sizeof (BICUBIC_PATCH), "bicubic patch");
-
- INIT_OBJECT_FIELDS(New, BICUBIC_PATCH_OBJECT, &Bicubic_Patch_Methods)
-
- New->Patch_Type = - 1;
-
- New->U_Steps = 0;
- New->V_Steps = 0;
-
- New->Flatness_Value = 0.0;
-
- New->Node_Tree = NULL;
-
- /*
- * NOTE: Control_Points[4][4] is initialized in Parse_Bicubic_Patch.
- * Bounding_Sphere_Center,Bounding_Sphere_Radius, Normal_Vector[], and
- * IPoint[] are initialized in Precompute_Patch_Values.
- */
-
- return (New);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Copy_Bicubic_Patch
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static BICUBIC_PATCH *Copy_Bicubic_Patch(OBJECT *Object)
- {
- int i, j;
- BICUBIC_PATCH *New;
-
- New = Create_Bicubic_Patch();
-
- /* Do not do *New = *Old so that Precompute works right */
-
- New->Patch_Type = ((BICUBIC_PATCH *)Object)->Patch_Type;
- New->U_Steps = ((BICUBIC_PATCH *)Object)->U_Steps;
- New->V_Steps = ((BICUBIC_PATCH *)Object)->V_Steps;
-
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- Assign_Vector(New->Control_Points[i][j], ((BICUBIC_PATCH *)Object)->Control_Points[i][j]);
- }
- }
-
- New->Flatness_Value = ((BICUBIC_PATCH *)Object)->Flatness_Value;
-
- Precompute_Patch_Values(New);
-
- return (New);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Destroy_Bicubic_Patch
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Alexander Enzmann
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
- static void Destroy_Bicubic_Patch(OBJECT *Object)
- {
- BICUBIC_PATCH *Patch;
-
- Patch = (BICUBIC_PATCH *)Object;
-
- if (Patch->Patch_Type != 0)
- {
- if (Patch->Node_Tree != NULL)
- {
- bezier_tree_deleter(Patch->Node_Tree);
- }
- }
-
- POV_FREE(Patch);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Compute_Bicubic_Patch_BBox
- *
- * INPUT
- *
- * Bicubic_Patch - Bicubic patch
- *
- * OUTPUT
- *
- * Bicubic_Patch
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Calculate the bounding box of a bicubic patch.
- *
- * CHANGES
- *
- * Aug 1994 : Creation.
- *
- ******************************************************************************/
- void Compute_Bicubic_Patch_BBox(BICUBIC_PATCH *Bicubic_Patch)
- {
- int i, j;
- VECTOR Min, Max;
- Make_Vector(Min, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
- Make_Vector(Max, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- Min[X] = min(Min[X], Bicubic_Patch->Control_Points[i][j][X]);
- Min[Y] = min(Min[Y], Bicubic_Patch->Control_Points[i][j][Y]);
- Min[Z] = min(Min[Z], Bicubic_Patch->Control_Points[i][j][Z]);
- Max[X] = max(Max[X], Bicubic_Patch->Control_Points[i][j][X]);
- Max[Y] = max(Max[Y], Bicubic_Patch->Control_Points[i][j][Y]);
- Max[Z] = max(Max[Z], Bicubic_Patch->Control_Points[i][j][Z]);
- }
- }
-
- Make_BBox_from_min_max(Bicubic_Patch->BBox, Min, Max);
- }
|