home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Graphics / Graphics.zip / povsrc31.zip / parse.c < prev    next >
C/C++ Source or Header  |  2001-01-31  |  297KB  |  12,146 lines

  1. /****************************************************************************
  2. *                parse.c
  3. *
  4. *  ------------------------------------------------------------------------
  5. *  ATTENTION:
  6. *  This is an unofficial version of parse.c modified by
  7. *    Ryoichi Suzuki, rsuzuki@etl.go.jp for "isosurface".
  8. *
  9. *  WARNING: This is a changed copy of the original file.
  10. *  Support of sphere sweep primitive added by Jochen Lippert.
  11. *
  12. *  ------------------------------------------------------------------------
  13. *  This module implements a parser for the scene description files.
  14. *
  15. *  from Persistence of Vision(tm) Ray Tracer
  16. *  Copyright 1996,1999 Persistence of Vision Team
  17. *---------------------------------------------------------------------------
  18. *  NOTICE: This source code file is provided so that users may experiment
  19. *  with enhancements to POV-Ray and to port the software to platforms other
  20. *  than those supported by the POV-Ray Team.  There are strict rules under
  21. *  which you are permitted to use this file.  The rules are in the file
  22. *  named POVLEGAL.DOC which should be distributed with this file.
  23. *  If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  24. *  Team Coordinator by email to team-coord@povray.org or visit us on the web at
  25. *  http://www.povray.org. The latest version of POV-Ray may be found at this site.
  26. *
  27. * This program is based on the popular DKB raytracer version 2.12.
  28. * DKBTrace was originally written by David K. Buck.
  29. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  30. *
  31. * Modifications by Thomas Willhalm, March 1999, used with permission.
  32. *
  33. * Further modifications by Lummox JR to include isoblob support
  34. *
  35. *****************************************************************************/
  36.  
  37. #include "frame.h"
  38. #include "vector.h"
  39. #include "povproto.h"
  40. #include "parse.h"
  41. #include "parstxtr.h"
  42. #include "atmosph.h"
  43. #include "bezier.h"   
  44. #ifdef RBezierPatch
  45. #include "rbezier.h"
  46. #endif
  47. #include "blob.h"     
  48. #include "boxes.h"
  49. #include "bsphere.h"
  50. #include "colour.h"
  51. #include "cones.h"    
  52. #include "csg.h"
  53. #include "discs.h"
  54. #ifdef SplinePatch
  55. #include "splines.h"
  56. #endif
  57. #include "express.h"  
  58. #include "fractal.h"
  59. #ifndef BurnAllGifs
  60. #include "gif.h"      
  61. #endif
  62. #include "hfield.h"
  63. #include "iff.h"      
  64. #include "image.h"    
  65. #include "interior.h"    
  66. #ifdef IsoBlobPatch
  67. #include "isoblob.h"
  68. #endif
  69. #include "lathe.h"    
  70. #include "polysolv.h"
  71. #include "matrices.h"
  72. #include "mesh.h"
  73. #include "normal.h"
  74. #include "objects.h"
  75. #include "octree.h"
  76. #include "pigment.h"
  77. #include "planes.h"
  78. #include "poly.h"
  79. #include "polygon.h"
  80. #include "povray.h"   
  81. #include "pgm.h"      
  82. #include "ppm.h"      
  83. #include "prism.h"    
  84. #include "quadrics.h" 
  85. #include "radiosit.h"      
  86. #include "render.h"   
  87. #include "sor.h"      
  88. #include "spheres.h"  
  89. #include "sphsweep.h"   /* Sphere sweep support */
  90. #include "super.h"
  91. #include "targa.h"    
  92. #include "texture.h"  
  93. #include "tokenize.h" 
  94. #include "torus.h"
  95. #include "triangle.h" 
  96. #include "truetype.h" 
  97. /*YS*/
  98. #include "lightgrp.h"
  99. /*YS*/
  100. #include "uniutils.h"
  101. /* NK phmap */
  102. #include "photons.h"
  103. /* NK ---- */
  104. #include "optin.h"
  105. /** poviso: **/
  106. #ifdef POVISO
  107. #include "isosrf.h"  /* July 14 '96 R.S. */
  108. #include "f_expr.h"  /* Tue 06-04-1996 0rf */
  109. void Parse_Parm(int PMax, int *pnum);
  110. void Iso_Parse_Box(ISOSURFACE *Object);
  111. void Iso_Parse_Sphere(ISOSURFACE *Object);
  112.  
  113. #endif
  114. /** --- **/
  115.  
  116. #ifdef MotionBlurPatch
  117. #include "mblur.h"
  118. /*#include "mblur2.h"*/
  119. #endif
  120.  
  121. #ifdef PostProcessPatch
  122. #include "postproc.h"
  123. void Parse_Post_Process(void);
  124. #endif
  125. #ifdef GlowPatch
  126. #include "glow.h"
  127. #endif
  128. /* NK phmap */
  129. /*****************************************************************************
  130. * Global Variables
  131. ******************************************************************************/
  132. extern int backtraceFlag;
  133.  
  134. extern PHOTON_OPTIONS photonOptions;
  135. /* NK ---- */
  136.  
  137. /*****************************************************************************
  138. * Local preprocessor defines
  139. ******************************************************************************/
  140.  
  141. /* Volume that is considered to be infinite. [DB 9/94] */
  142.  
  143. #define INFINITE_VOLUME BOUND_HUGE
  144.  
  145.  
  146. /*****************************************************************************
  147. * Local typedefs
  148. ******************************************************************************/
  149. #ifdef BsplinePatch
  150. typedef struct Spline_Stack_1D_Struct SPLINE_STACK_1D;
  151.  
  152. struct Spline_Stack_1D_Struct
  153. {
  154.   DBL       t,y;
  155.   void     *next;
  156. };
  157.  
  158. typedef struct Spline_Stack_3D_Struct SPLINE_STACK_3D;
  159.  
  160. struct Spline_Stack_3D_Struct
  161. {
  162.   VECTOR    Knot;
  163.   void     *next;
  164. };
  165.  
  166. #endif
  167.  
  168.  
  169.  
  170. /*****************************************************************************
  171. * Local variables
  172. ******************************************************************************/
  173.  
  174. short Have_Vector;
  175. short Not_In_Default;
  176. short Ok_To_Declare;
  177. short LValue_Ok;
  178.  
  179. static TOKEN *Brace_Stack;
  180. static int Brace_Index;
  181. static CAMERA *Default_Camera;
  182.  
  183. /** poviso: July 8, '96 R.S. **/
  184. #ifdef POVISO
  185.    DBL iso_p[ISOSURFACE_MAXPARM];
  186. #endif
  187. /** --- **/
  188.  
  189. #ifdef BsplinePatch
  190.     SPLINE   *The_Splines;
  191.     SPLINE_3D *The_3D_Splines;
  192. #endif
  193.  
  194. #ifdef MotionBlurPatch
  195. static int parsedMotionBlurObject;
  196. #endif
  197.  
  198. /*****************************************************************************
  199. * Static functions
  200. ******************************************************************************/
  201.  
  202. #ifdef MotionBlurPatch
  203. static void Parse_MBlur_Transform (TRANSFORM *New);
  204. #endif
  205.  
  206. #ifndef TransformPatch /* Chris Huff april 2000 */
  207. static TRANSFORM *Parse_Transform (void);
  208. #else
  209. static TRANSFORM *Parse_Transform_Block (void);/*Chris Huff transform patch*/
  210. #endif
  211.  
  212. static void Frame_Init (void);
  213. static void Parse_Coeffs (int order, DBL *Coeffs);
  214.  
  215. static OBJECT *Parse_Bicubic_Patch (void);
  216. #ifndef BlobPatternPatch
  217. static OBJECT *Parse_Blob (void);
  218. #endif
  219. static OBJECT *Parse_Bound_Clip (void);
  220. static OBJECT *Parse_Box (void);
  221. static OBJECT *Parse_Cone (void);
  222. static OBJECT *Parse_CSG (int CSG_Type);
  223. static OBJECT *Parse_Cylinder (void);
  224. static OBJECT *Parse_Disc (void);
  225. static OBJECT *Parse_Julia_Fractal (void);
  226. static OBJECT *Parse_HField (void);
  227. static OBJECT *Parse_Lathe (void);
  228. static OBJECT *Parse_Light_Source (void);
  229. static OBJECT *Parse_Object_Id (void);
  230. static OBJECT *Parse_Plane (void);
  231. static OBJECT *Parse_Poly (int order);
  232. static OBJECT *Parse_Polygon (void);
  233. static OBJECT *Parse_Prism (void);
  234. static OBJECT *Parse_Quadric (void);
  235. static OBJECT *Parse_Smooth_Triangle (void);
  236. static OBJECT *Parse_Sor (void);
  237. static OBJECT *Parse_Sphere (void);
  238. static OBJECT *Parse_Superellipsoid (void);
  239. static OBJECT *Parse_Torus (void);
  240. static OBJECT *Parse_Triangle (void);
  241. static OBJECT *Parse_Mesh (void);
  242. /* NK 1998 */
  243. static OBJECT *Parse_Mesh2 (void);
  244. /* NK ---- */
  245. #ifdef ColorTrianglePatch
  246. static TEXTURE *Parse_Mesh_Texture (TEXTURE **t2, TEXTURE **t3);
  247. #else
  248. static TEXTURE *Parse_Mesh_Texture (void);
  249. #endif
  250. static OBJECT *Parse_TrueType (void);
  251. static void Parse_Blob_Element_Mods (BLOB_ELEMENT *Element);
  252.  
  253. #ifdef MotionBlurPatch
  254. static OBJECT *Parse_Motion_Blur ();
  255. /*static OBJECT *Parse_Motion_Blur2 ();*/
  256. #endif
  257.  
  258. static void Parse_Camera (CAMERA **Camera_Ptr);
  259. static void Parse_Frame (void);
  260.  
  261. static void Found_Instead (void);
  262. static void Link (OBJECT *New_Object,OBJECT **Field,OBJECT **Old_Object_List);
  263. static void Link_To_Frame (OBJECT *Object);
  264. static void Post_Process (OBJECT *Object, OBJECT *Parent);
  265. static void Parse_Global_Settings (void);
  266. static void Global_Setting_Warn (void);
  267. #ifdef BsplinePatch
  268.     static void Create_Spline_1D (SPLINE_STACK_1D *base,int nr,char *name,int type,DBL p1,DBL p2);
  269.     static void Create_Spline_3D (SPLINE_STACK_3D *base,int nr,char *name,int type,VECTOR temp1,VECTOR temp2);
  270.     static void Destroy_Splines (void);
  271.     static void Jacobi (DBL *a,DBL *b,DBL *c,DBL *rs,DBL *s,int n);
  272. #endif
  273.  
  274. static void Set_CSG_Children_Flag (OBJECT*, unsigned long, unsigned long, unsigned long);
  275. #ifdef NoImageNoReflectionPatch
  276. /* JG start */
  277. static void Set_CSG_Tree_Flag (OBJECT*, unsigned long);
  278. /* JG end */
  279. #endif
  280. static void *Copy_Identifier (void *Data, int Type);
  281.  
  282. /* NK layers - 1999 July 10 - for backwards compatiblity with layered textures */
  283. static void Convert_Filter_To_Transmit(PIGMENT *Pigment);
  284. /* NK ---- */
  285.  
  286. /* NK persist */
  287. static void Parse_Modify_Object(void);
  288. static void Parse_Destroy_Object(void);
  289. /* NK ---- */
  290.  
  291. #ifdef IsoBlobPatch
  292. /* Lummox JR, July 1999 */
  293. static OBJECT *Parse_Isoblob (void);
  294. static void Parse_Isolob_Element_Mods (ISOBLOB_ELEMENT *Element);
  295. /* end Lummox JR's additions */
  296. #endif
  297.  
  298. /* NK super */
  299. static OBJECT *Parse_Sphere_Sweep (void);       /* Sphere sweep support */
  300. static OBJECT *Parse_Mesh2 (void);
  301. /* NK ---- */
  302. /** poviso:  1/22 '96 R.S. **/
  303. #ifdef POVISO
  304. static OBJECT *Parse_IsoSurface (int parse_type);
  305. extern int Func_Parse_Flag;
  306.  
  307. #define PARSE_IMPFUN  1
  308. #define PARSE_FUNC_XY 2
  309.  
  310. FUNCTION *Parse_Function (void);
  311.  
  312. #endif
  313.  
  314. #ifdef RBezierPatch
  315. static OBJECT *Parse_RBezier_Patch (void);
  316. static void bicubic_patch_warning(BICUBIC_PATCH *Object,char flag);
  317. static TRIM_SHAPE *Parse_Trim (void);
  318. #endif
  319.  
  320. /* NK persist */
  321. int findObjectsByLabel(OBJECT **objHandle, OBJECT* parent, char **objectNames, int nameCount,
  322.                    int (*function)(OBJECT **objHandle, OBJECT* parent, void *handle), void *handle,
  323.                    int (*functionParent)(OBJECT **objHandle, OBJECT* parent, void *handle), void *handle2 );
  324. int modifyObjectCallback(OBJECT **objHandle, OBJECT* parent, void *handle);
  325. int modifyObjectParentCallback(OBJECT **objHandle, OBJECT *parent, void *handle);
  326. int destroyObjectCallback(OBJECT **objHandle, OBJECT* parent, void *handle);
  327. int destroyObjectParentCallback(OBJECT **objHandle, OBJECT *parent, void *handle);
  328. /* NK ---- */
  329. int Parse_Three_UVCoords(UV_VECT UV1, UV_VECT UV2, UV_VECT UV3);
  330.  
  331. /*****************************************************************************
  332. *
  333. * FUNCTION
  334. *
  335. * INPUT
  336. *
  337. * OUTPUT
  338. *
  339. * RETURNS
  340. *
  341. * AUTHOR
  342. *   
  343. * DESCRIPTION
  344. *
  345. * CHANGES
  346. *
  347. ******************************************************************************/
  348.  
  349. /* Parse the file. */
  350. void Parse ()
  351. {
  352. #ifdef BsplinePatch
  353.   The_Splines = NULL;
  354.   The_3D_Splines = NULL;
  355. #endif
  356.  
  357.   Initialize_Tokenizer();
  358.   Brace_Stack = (TOKEN *)POV_MALLOC(MAX_BRACES*sizeof (TOKEN), "brace stack");
  359.   Brace_Index = 0;
  360.  
  361.   Default_Camera = Create_Camera();
  362.  
  363.   Default_Texture = Create_Texture();
  364.  
  365.   Default_Texture->Pigment = Create_Pigment();
  366.   Default_Texture->Tnormal = NULL;
  367.   Default_Texture->Finish  = Create_Finish();
  368.  
  369.   Not_In_Default = TRUE;
  370.   Ok_To_Declare = TRUE;
  371.   LValue_Ok = FALSE;
  372.  
  373. #ifdef MotionBlurPatch
  374.   parsedMotionBlurObject = FALSE;
  375. #endif
  376.  
  377.   Frame_Init ();
  378.   
  379.   Stage = STAGE_PARSING;
  380.  
  381.   Parse_Frame ();
  382.  
  383.   Post_Media(Frame.Atmosphere);
  384.  
  385. #ifdef GlowPatch
  386.   if (Frame.Objects == NULL && Frame.NumOfGlows == 0)
  387.   {
  388.     Error ("No objects or glows in scene.");
  389.   }
  390. #else
  391.   if (Frame.Objects == NULL)
  392.   {
  393.     Error ("No objects in scene.");
  394.   }
  395. #endif
  396.   Stage = STAGE_CLEANUP_PARSE;
  397.  
  398.   Terminate_Tokenizer(FALSE);
  399.   Destroy_Textures(Default_Texture); 
  400.   Destroy_Camera(Default_Camera); 
  401.   POV_FREE (Brace_Stack);
  402.  
  403.   Default_Texture = NULL;
  404.   Default_Camera = NULL;
  405.   Brace_Stack = NULL;
  406. #ifdef BsplinePatch
  407.   Destroy_Splines();
  408. #endif
  409. }
  410.  
  411.  
  412.  
  413. /*****************************************************************************
  414. *
  415. * FUNCTION
  416. *
  417. * INPUT
  418. *   
  419. * OUTPUT
  420. *   
  421. * RETURNS
  422. *   
  423. * AUTHOR
  424. *   
  425. * DESCRIPTION
  426. *
  427. * CHANGES
  428. *
  429. ******************************************************************************/
  430.  
  431. /* Set up the fields in the frame to default values. */
  432. static void Frame_Init (void)
  433. {
  434.    Frame.Camera = Copy_Camera(Default_Camera);
  435.    Frame.Number_Of_Light_Sources = 0;  
  436.    Frame.Light_Sources = NULL;
  437. #ifdef GlowPatch 
  438.    Frame.Glows = NULL;
  439.    Frame.NumOfGlows = 0;
  440. #endif
  441.    /* NK persist - commented this out - do this in main/alt_main instead */
  442.    /*Frame.Objects = NULL;*/
  443.    Frame.Atmosphere_IOR = 1.0;
  444.    Frame.Atmosphere_Dispersion = 1.0;
  445.    Frame.Antialias_Threshold = opts.Antialias_Threshold;
  446.  
  447. /* dmf -- the first is physically "more correct".  The second works better */
  448. /*   Make_Colour (Frame.Irid_Wavelengths, 0.70, 0.52, 0.48); */
  449.    Make_Colour (Frame.Irid_Wavelengths, 0.25, 0.18, 0.14);
  450.    Make_Colour (Frame.Background_Colour, 0.0, 0.0, 0.0);
  451.    Make_Colour (Frame.Ambient_Light, 1.0, 1.0, 1.0);
  452.  
  453.    /* Init atmospheric stuff. [DB 12/94] */
  454.  
  455.    Frame.Atmosphere = NULL;
  456.  
  457.    Frame.Fog = NULL;
  458.  
  459.    Frame.Rainbow = NULL;
  460.  
  461.    Frame.Skysphere = NULL;
  462.   }
  463.  
  464.  
  465.  
  466. /*****************************************************************************
  467. *
  468. * FUNCTION
  469. *
  470. * INPUT
  471. *   
  472. * OUTPUT
  473. *   
  474. * RETURNS
  475. *   
  476. * AUTHOR
  477. *   
  478. * DESCRIPTION
  479. *
  480. * CHANGES
  481. *
  482. ******************************************************************************/
  483.  
  484. void Parse_Begin ()
  485. {
  486.    char *front;
  487.    
  488.    if (++Brace_Index >= MAX_BRACES)
  489.    {
  490.       Warn(0,"Too many nested '{' braces.\n");
  491.       Brace_Index--;
  492.    }
  493.  
  494.    Brace_Stack[Brace_Index]=Token.Token_Id;
  495.  
  496.    Get_Token ();
  497.  
  498.    if (Token.Token_Id == LEFT_CURLY_TOKEN)
  499.    {
  500.      return;
  501.    }
  502.    
  503.    front = Get_Token_String (Brace_Stack[Brace_Index]);
  504.  
  505.    Where_Error ();
  506.    Error_Line ("Missing { after %s, ", front);
  507.    Found_Instead ();
  508.   }
  509.  
  510.  
  511.  
  512. /*****************************************************************************
  513. *
  514. * FUNCTION
  515. *
  516. * INPUT
  517. *   
  518. * OUTPUT
  519. *   
  520. * RETURNS
  521. *   
  522. * AUTHOR
  523. *   
  524. * DESCRIPTION
  525. *
  526. * CHANGES
  527. *
  528. ******************************************************************************/
  529.  
  530. void Parse_End ()
  531. {
  532.    char *front;
  533.  
  534.    Get_Token ();
  535.  
  536.    if (Token.Token_Id == RIGHT_CURLY_TOKEN)
  537.    {
  538.       if(--Brace_Index < 0)
  539.       {
  540.         Warn(0,"Possible '}' brace missmatch.");
  541.         Brace_Index = 0;
  542.       }
  543.       return;
  544.    }
  545.  
  546.    front = Get_Token_String (Brace_Stack[Brace_Index]);
  547.  
  548.    Where_Error ();
  549.    Error_Line("No matching } in %s,", front);
  550.    Found_Instead ();
  551.   }
  552.  
  553.  
  554.  
  555. /*****************************************************************************
  556. *
  557. * FUNCTION
  558. *
  559. * INPUT
  560. *   
  561. * OUTPUT
  562. *   
  563. * RETURNS
  564. *   
  565. * AUTHOR
  566. *   
  567. * DESCRIPTION
  568. *
  569. * CHANGES
  570. *
  571. ******************************************************************************/
  572.  
  573. static OBJECT *Parse_Object_Id ()
  574. {
  575.    OBJECT *Object;
  576.  
  577.    EXPECT
  578.      CASE (OBJECT_ID_TOKEN)
  579.        Warn_State(OBJECT_ID_TOKEN, OBJECT_TOKEN);
  580.        Object = Copy_Object((OBJECT *) Token.Data);
  581.        Parse_Object_Mods (Object);
  582.        EXIT
  583.      END_CASE
  584.  
  585.      OTHERWISE
  586.        Object = NULL;
  587.        UNGET
  588.        EXIT
  589.      END_CASE
  590.    END_EXPECT
  591.  
  592.    return (Object);
  593.   }
  594.  
  595.  
  596.  
  597. /*****************************************************************************
  598. *
  599. * FUNCTION
  600. *
  601. * INPUT
  602. *   
  603. * OUTPUT
  604. *   
  605. * RETURNS
  606. *   
  607. * AUTHOR
  608. *   
  609. * DESCRIPTION
  610. *
  611. * CHANGES
  612. *
  613. ******************************************************************************/
  614.  
  615. void Parse_Comma (void)
  616. {
  617.    Get_Token();
  618.    if (Token.Token_Id != COMMA_TOKEN)
  619.    {
  620.       UNGET;
  621.    }
  622. }
  623.  
  624. void Parse_Semi_Colon (void)
  625. {
  626.    Get_Token();
  627.    if (Token.Token_Id != SEMI_COLON_TOKEN)
  628.    {
  629.       UNGET;
  630.       if (opts.Language_Version >= 310)
  631.       {
  632.          Warn(0,"All #version and #declares of float, vector, and color require semi-colon ';' at end.\n");
  633.       }
  634.    }
  635. }
  636.  
  637. /** poviso: Mar '96 R.S. **/
  638. #ifdef POVISO
  639. /*****************************************************************************
  640. *
  641. * FUNCTION  Parse_Parm
  642. *
  643. * INPUT
  644. *   
  645. * OUTPUT
  646. *   
  647. * RETURNS
  648. *   
  649. * AUTHOR R.Suzuki
  650. *   
  651. * DESCRIPTION
  652. *
  653. * CHANGES
  654. *
  655. ******************************************************************************/
  656.  
  657. /*---------  R.Suzuki  Mar '96-----------*/
  658. void Parse_Parm(int PMax, int *pnum)
  659.   {
  660.    int i;
  661.  
  662.    if (PMax==0) PMax = ISOSURFACE_MAXPARM;
  663.  
  664.    EXPECT
  665.      CASE (LEFT_ANGLE_TOKEN)
  666.        iso_p[0] = Parse_Float();
  667.        for (i = 1; i < PMax; i++)
  668.        {
  669.          Get_Token();
  670.          if (Token.Token_Id == COMMA_TOKEN) iso_p[i] = Parse_Float();
  671.            else {Unget_Token(); break;}
  672.        }
  673.        GET (RIGHT_ANGLE_TOKEN);
  674.        EXIT
  675.      END_CASE
  676.  
  677.      OTHERWISE
  678.        Parse_Error (LEFT_ANGLE_TOKEN);
  679.      END_CASE
  680.    END_EXPECT
  681.  
  682.    *pnum=i;
  683.   }
  684. #endif
  685. /** --- **/
  686.  
  687.  
  688. /*****************************************************************************
  689. *
  690. * FUNCTION
  691. *
  692. * INPUT
  693. *   
  694. * OUTPUT
  695. *   
  696. * RETURNS
  697. *   
  698. * AUTHOR
  699. *   
  700. * DESCRIPTION
  701. *
  702. * CHANGES
  703. *
  704. ******************************************************************************/
  705.  
  706. static void Parse_Coeffs(int order, DBL *Coeffs)
  707. {
  708.    int i;
  709.  
  710.    EXPECT
  711.      CASE (LEFT_ANGLE_TOKEN)
  712.        Coeffs[0] = Parse_Float();
  713.        for (i = 1; i < term_counts(order); i++)
  714.          {
  715.           Parse_Comma();
  716.           Coeffs[i] = Parse_Float();
  717.          }
  718.        GET (RIGHT_ANGLE_TOKEN);
  719.        EXIT
  720.      END_CASE
  721.  
  722.      OTHERWISE
  723.        Parse_Error (LEFT_ANGLE_TOKEN);
  724.      END_CASE
  725.    END_EXPECT
  726.   }
  727.  
  728.  
  729. /*****************************************************************************
  730. *
  731. * FUNCTION
  732. *
  733. * INPUT
  734. *
  735. * OUTPUT
  736. *
  737. * RETURNS
  738. *
  739. * AUTHOR
  740. *
  741. * DESCRIPTION
  742. *
  743. * CHANGES
  744. *
  745. ******************************************************************************/
  746.  
  747. static OBJECT *Parse_Bound_Clip (void)
  748. {
  749.    VECTOR Local_Vector;
  750.    MATRIX Local_Matrix;
  751.    TRANSFORM Local_Trans;
  752.    OBJECT *First, *Current, *Prev;
  753.  
  754.    First = Prev = NULL;
  755.  
  756.    while ((Current = Parse_Object ()) != NULL)
  757.      {
  758.       if (Current->Type & (TEXTURED_OBJECT+PATCH_OBJECT))
  759.         Error ("Illegal texture or patch in clip or bound.");
  760.       if (First == NULL)
  761.         First = Current;
  762.       if (Prev != NULL)
  763.         Prev->Sibling = Current;
  764.       Prev = Current;
  765.      }
  766.  
  767.    EXPECT
  768.      CASE (TRANSLATE_TOKEN)
  769.        Parse_Vector (Local_Vector);
  770.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  771.        for (Current = First; Current != NULL; Current = Current->Sibling)
  772.        {
  773.          Translate_Object (Current, Local_Vector, &Local_Trans);
  774.        }
  775.      END_CASE
  776.  
  777.      CASE (ROTATE_TOKEN)
  778.        Parse_Vector (Local_Vector);
  779.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  780.        for (Current = First; Current != NULL; Current = Current->Sibling)
  781.        {
  782.          Rotate_Object (Current, Local_Vector, &Local_Trans);
  783.        }
  784.      END_CASE
  785.  
  786.      CASE (SCALE_TOKEN)
  787.        Parse_Scale_Vector (Local_Vector);
  788.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  789.        for (Current = First; Current != NULL; Current = Current->Sibling)
  790.        {
  791.          Scale_Object (Current, Local_Vector, &Local_Trans);
  792.        }
  793.      END_CASE
  794.  
  795.      CASE (TRANSFORM_TOKEN)
  796. #ifndef TransformPatch /* Chris Huff april 2000 */
  797.        GET(TRANSFORM_ID_TOKEN)
  798.        for (Current = First; Current != NULL; Current = Current->Sibling)
  799.        {
  800.          Transform_Object (Current, (TRANSFORM *)Token.Data);
  801.        }
  802. #else
  803.        {
  804.            TRANSFORM * Trans = Parse_Transform();
  805.            for (Current = First; Current != NULL; Current = Current->Sibling)
  806.            {
  807.              Transform_Object (Current, Trans);
  808.            }
  809.             /*YS sept 17 2000 Memory leak*/
  810.            POV_FREE(Trans);
  811.        }
  812. #endif
  813.      END_CASE
  814.  
  815.      CASE (MATRIX_TOKEN)
  816.        Parse_Matrix (Local_Matrix);
  817.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  818.        for (Current = First; Current != NULL; Current = Current->Sibling)
  819.        {
  820.          Transform_Object (Current, &Local_Trans);
  821.        }
  822.      END_CASE
  823.  
  824.      OTHERWISE
  825.        UNGET
  826.        EXIT
  827.      END_CASE
  828.    END_EXPECT
  829.  
  830.    if (First==NULL)
  831.    {
  832.       Parse_Error_Str("object");
  833.    }
  834.  
  835.    return (First);
  836.   }
  837.  
  838.  
  839.  
  840. /*****************************************************************************
  841. *
  842. * FUNCTION
  843. *
  844. * INPUT
  845. *   
  846. * OUTPUT
  847. *   
  848. * RETURNS
  849. *   
  850. * AUTHOR
  851. *   
  852. * DESCRIPTION
  853. *
  854. * CHANGES
  855. *
  856. ******************************************************************************/
  857.  
  858. void Parse_Object_Mods (OBJECT *Object)
  859. {
  860.    DBL Temp_Water_Level;
  861.    DBL V1, V2;
  862.    VECTOR Min, Max;  
  863.    VECTOR Local_Vector;
  864.    MATRIX Local_Matrix;
  865.    TRANSFORM Local_Trans;
  866.    BBOX BBox;
  867.    OBJECT *Sib;
  868.    TEXTURE *Local_Texture;
  869. #ifdef InteriorTexturePatch
  870.    TEXTURE *Local_Int_Texture;
  871. #endif
  872.    MATERIAL Local_Material;
  873.    OBJECT *Temp1_Object;
  874.    OBJECT *Temp2_Object;
  875.    COLOUR Local_Colour;
  876.    int Tmp_Flag;
  877.  
  878.    EXPECT
  879.         #if(0) /*GlowPatch  in objects not implemented yet */
  880.             CASE(GLOW_TOKEN)
  881.             {
  882.                 if ( Ok_To_Declare ==false)
  883.                     Error("You can not use glow in a declared object (yet)\n");
  884.                     GLOW * NewGlow = Create_Glow();
  885.                     Parse_Glow(NewGlow);
  886.                     Add_Glow(NewGlow);/*Add glow to Frame*/
  887.  
  888.                     /*Add glow to list of glow pointers in object*/
  889.                     if(Object->glowList == NULL)
  890.                         Object->glowList = (GLOW**)POV_MALLOC(sizeof(GLOW_PTR), "glow pointer array");
  891.                     else
  892.                     {
  893.                         GLOW_PTR * newGlowList = (GLOW**)POV_MALLOC((Object->numOfGlows+2)*sizeof(GLOW_PTR), "glow pointer array");
  894.                         memcpy(newGlowList, Object->glowList, (Object->numOfGlows+1)*sizeof(GLOW_PTR));
  895.                         POV_FREE(Object->glowList);
  896.                         Object->glowList = newGlowList;
  897.                     }
  898.                     Object->glowList[Object->numOfGlows] = NewGlow;
  899.                     Object->numOfGlows++;
  900.                 }
  901.             END_CASE
  902.         #endif
  903.  
  904.      /* NK persist label */
  905.      CASE (LABEL_TOKEN)
  906. #ifdef UnofficialBlocking
  907.        parseUnofficialFeature(30);
  908. #endif
  909.        Get_Token();
  910.  
  911.        /* any valid token is OK as a label */
  912.  
  913.        if (Object->Label!=NULL)
  914.          POV_FREE(Object->Label);
  915.  
  916.        Object->Label = POV_STRDUP(Token.Token_String);
  917.  
  918.        /* now with a label, we can't split unions */
  919.        if (Object->Methods == &CSG_Union_Methods)
  920.        {
  921.          ((CSG*)Object)->do_split = FALSE;
  922.        }
  923.      END_CASE
  924.      /* NK ---- */
  925.  
  926.      /* NK phmap */
  927.      CASE(SPLIT_UNION_TOKEN)
  928. #ifdef UnofficialBlocking
  929.        parseUnofficialFeature(30);
  930. #endif
  931.        if (Object->Methods != &CSG_Union_Methods)
  932.        {
  933.          Error("split_union found in non-union object.\n");
  934.        }
  935.  
  936.        ((CSG*)Object)->do_split = (int)Parse_Float();
  937.      END_CASE
  938.      /* NK --- */
  939.  
  940.      /* NK 1998 */
  941.      CASE(UV_MAPPING_TOKEN)
  942. #ifdef UnofficialBlocking
  943.        parseUnofficialFeature(30);
  944. #endif
  945.        /* if no texture than allow uv_mapping
  946.           otherwise, warn user */
  947.        if (Object->Texture == NULL)
  948.        {
  949.          Set_Flag(Object, UV_FLAG);
  950.        }
  951.        else
  952.        {
  953.          Error ("uv_mapping must be specified before texture.");
  954.        }
  955.      END_CASE
  956.      /* NK ---- */
  957.  
  958.      /* NK phmap */
  959.      CASE(PHOTONS_TOKEN)
  960. #ifdef UnofficialBlocking
  961.        parseUnofficialFeature(30);
  962. #endif
  963.        Parse_Begin();
  964.        EXPECT
  965.          CASE(TARGET_TOKEN)
  966.            Object->Ph_Density = Allow_Float(1.0);
  967.            if (Object->Ph_Density > 0)
  968.            {
  969.              Object->Ph_Flags |= PH_FLAG_TARGET;
  970.              CheckPassThru(Object, PH_FLAG_TARGET);
  971.            }
  972.            else
  973.            {
  974.              Object->Ph_Flags &= ~PH_FLAG_TARGET;
  975.            }
  976.          END_CASE
  977.  
  978.          CASE(REFRACTION_TOKEN)
  979.            if((int)Parse_Float())
  980.            { 
  981.              SET_PH_FLAG(Object, PH_FLAG_RFR_ON, PH_FLAG_RFR_OFF);
  982.              CheckPassThru(Object, PH_FLAG_RFR_ON);
  983.            }
  984.            else
  985.            { CLEAR_PH_FLAG(Object, PH_FLAG_RFR_ON, PH_FLAG_RFR_OFF); }
  986.          END_CASE
  987.  
  988.          CASE(REFLECTION_TOKEN)
  989.            if((int)Parse_Float())
  990.            { SET_PH_FLAG(Object, PH_FLAG_RFL_ON, PH_FLAG_RFL_OFF); }
  991.            else
  992.            { CLEAR_PH_FLAG(Object, PH_FLAG_RFL_ON, PH_FLAG_RFL_OFF); }
  993.          END_CASE
  994.  
  995.          CASE(PASS_THROUGH_TOKEN)
  996.            if((int)Allow_Float(1.0))
  997.            {
  998.              Object->Ph_Flags |= PH_FLAG_PASSTHRU;
  999.              CheckPassThru(Object, PH_FLAG_PASSTHRU);
  1000.            }
  1001.            else
  1002.            {
  1003.              Object->Ph_Flags &= ~PH_FLAG_PASSTHRU;
  1004.            }
  1005.          END_CASE
  1006.  
  1007.          CASE(IGNORE_PHOTONS_TOKEN)
  1008.            Object->Ph_Flags |= PH_FLAG_IGNORE_PHOTONS;
  1009.          END_CASE
  1010.  
  1011.          OTHERWISE
  1012.            UNGET
  1013.            EXIT
  1014.          END_CASE
  1015.        END_EXPECT
  1016.        Parse_End();
  1017.  
  1018.      END_CASE
  1019.      /* NK ---- */
  1020.  
  1021. #ifdef MultiTextureCsgPatch
  1022.      CASE(CUTAWAY_TEXTURES_TOKEN)
  1023. #ifdef UnofficialBlocking
  1024.        parseUnofficialFeature(50);
  1025. #endif
  1026.        if (Object->Methods != &CSG_Intersection_Methods)
  1027.        {
  1028.          Error("cutaway_textures can only be used with intersection and difference.\n");
  1029.        }
  1030.  
  1031.        Set_Flag(Object, MULTITEXTURE_FLAG);
  1032.      END_CASE
  1033. #endif
  1034.  
  1035.      CASE_COLOUR
  1036.        Parse_Colour (Local_Colour);
  1037.        if (opts.Language_Version < 150)
  1038.          if (Object->Texture != NULL)
  1039.            if (Object->Texture->Type == PLAIN_PATTERN)
  1040.              if (opts.Quality_Flags & Q_QUICKC)
  1041.              {
  1042.               Assign_Colour(Object->Texture->Pigment->Colour,Local_Colour);
  1043.               break;  /* acts like END_CASE */
  1044.              }
  1045.        Warn(0, "Quick color belongs in texture. Color ignored.");
  1046.      END_CASE
  1047.  
  1048.      CASE (TRANSLATE_TOKEN)
  1049.        Parse_Vector (Local_Vector);
  1050.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  1051.        Translate_Object (Object, Local_Vector, &Local_Trans);
  1052.      END_CASE
  1053.  
  1054.      CASE (ROTATE_TOKEN)
  1055.        Parse_Vector (Local_Vector);
  1056.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  1057.        Rotate_Object (Object, Local_Vector, &Local_Trans);
  1058.      END_CASE
  1059.  
  1060.      CASE (SCALE_TOKEN)
  1061.        Parse_Scale_Vector (Local_Vector);
  1062.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  1063.        Scale_Object (Object, Local_Vector, &Local_Trans);
  1064.      END_CASE
  1065.  
  1066.      CASE (TRANSFORM_TOKEN)
  1067. #ifndef TransformPatch /* Chris Huff april 2000 */
  1068.        GET(TRANSFORM_ID_TOKEN)
  1069.        Transform_Object (Object, (TRANSFORM *)Token.Data);
  1070. #else
  1071.        {
  1072.            TRANSFORM * Trans = Parse_Transform();
  1073.            Transform_Object(Object, Trans);
  1074.             /*YS sept 17 2000 Memory leak*/
  1075.            POV_FREE(Trans);
  1076.        }
  1077. #endif
  1078.      END_CASE
  1079.  
  1080.      CASE (MATRIX_TOKEN)
  1081.        Parse_Matrix (Local_Matrix);
  1082.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  1083.        Transform_Object (Object, &Local_Trans);
  1084.      END_CASE
  1085.  
  1086.      CASE (BOUNDED_BY_TOKEN)
  1087.        Parse_Begin ();
  1088.        if (Object->Bound != NULL)
  1089.          if (Object->Clip == Object->Bound)
  1090.            Error ("Cannot add bounds after linking bounds and clips.");
  1091.  
  1092.        EXPECT
  1093.          CASE (CLIPPED_BY_TOKEN)
  1094.            if (Object->Bound != NULL)
  1095.              Error ("Cannot link clips with previous bounds.");
  1096.            Object->Bound = Object->Clip;
  1097.            EXIT
  1098.          END_CASE
  1099.  
  1100.          OTHERWISE
  1101.            UNGET
  1102.            Temp1_Object = Temp2_Object = Parse_Bound_Clip ();
  1103.            while (Temp2_Object->Sibling != NULL)
  1104.              Temp2_Object = Temp2_Object->Sibling;
  1105.            Temp2_Object->Sibling = Object->Bound;
  1106.            Object->Bound = Temp1_Object;
  1107.            EXIT
  1108.          END_CASE
  1109.        END_EXPECT
  1110.  
  1111.        Parse_End ();
  1112.      END_CASE
  1113.  
  1114.      CASE (CLIPPED_BY_TOKEN)
  1115.        Parse_Begin ();
  1116.        if (Object->Clip != NULL)
  1117.          if (Object->Clip == Object->Bound)
  1118.            Error ("Cannot add clips after linking bounds and clips.");
  1119.  
  1120.        EXPECT
  1121.          CASE (BOUNDED_BY_TOKEN)
  1122.            if (Object->Clip != NULL)
  1123.              Error ("Cannot link bounds with previous clips.");
  1124.            Object->Clip = Object->Bound;
  1125.            EXIT
  1126.          END_CASE
  1127.  
  1128.          OTHERWISE
  1129.            UNGET
  1130.            Temp1_Object = Temp2_Object = Parse_Bound_Clip ();
  1131.            while (Temp2_Object->Sibling != NULL)
  1132.              Temp2_Object = Temp2_Object->Sibling;
  1133.            Temp2_Object->Sibling = Object->Clip;
  1134.            Object->Clip = Temp1_Object;
  1135.  
  1136.            /* Compute quadric bounding box before transformations. [DB 8/94] */
  1137.  
  1138.            if (Object->Methods == &Quadric_Methods)
  1139.            {
  1140.              Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  1141.              Make_Vector(Max,  BOUND_HUGE,  BOUND_HUGE,  BOUND_HUGE);
  1142.  
  1143.              Compute_Quadric_BBox((QUADRIC *)Object, Min, Max);
  1144.            }
  1145.            EXIT
  1146.          END_CASE
  1147.        END_EXPECT
  1148.  
  1149.        Parse_End ();
  1150.      END_CASE
  1151.  
  1152.      CASE (TEXTURE_TOKEN)
  1153.        Object->Type |= TEXTURED_OBJECT;
  1154.        Parse_Begin ();
  1155.        Local_Texture = Parse_Texture ();
  1156.        Parse_End ();
  1157.        Link_Textures(&(Object->Texture), Local_Texture);
  1158.      END_CASE
  1159.  
  1160. #ifdef InteriorTexturePatch
  1161.      CASE (INTERIOR_TEXTURE_TOKEN)/*Chris Huff: Interior Texture patch*/
  1162. #ifdef UnofficialBlocking
  1163.        parseUnofficialFeature(30);
  1164. #endif
  1165.        Object->Type |= TEXTURED_OBJECT;
  1166.        Parse_Begin ();
  1167.        Local_Int_Texture = Parse_Texture ();
  1168.        Parse_End ();
  1169.        Link_Textures(&(Object->Interior_Texture), Local_Int_Texture);
  1170.      END_CASE
  1171. #endif
  1172.      CASE (INTERIOR_TOKEN)
  1173.        Parse_Interior((INTERIOR **)(&Object->Interior));
  1174.      END_CASE
  1175.  
  1176.      CASE (MATERIAL_TOKEN)
  1177.        Local_Material.Texture  = Object->Texture;
  1178. #ifdef InteriorTexturePatch
  1179.        Local_Material.Interior_Texture  = Object->Interior_Texture;/*Chris Huff: Interior Texture patch*/
  1180. #endif
  1181.        Local_Material.Interior = Object->Interior;
  1182.        Parse_Material(&Local_Material);
  1183.        Object->Texture  = Local_Material.Texture;
  1184. #ifdef InteriorTexturePatch
  1185.        Object->Interior_Texture  = Local_Material.Interior_Texture;/*Chris Huff: Interior Texture patch*/
  1186. #endif
  1187.        Object->Interior = Local_Material.Interior;
  1188.      END_CASE
  1189.  
  1190.      CASE3 (PIGMENT_TOKEN, TNORMAL_TOKEN, FINISH_TOKEN)
  1191.        Object->Type |= TEXTURED_OBJECT;
  1192.        if (Object->Texture == NULL)
  1193.          Object->Texture = Copy_Textures(Default_Texture);
  1194.        else
  1195.          if (Object->Texture->Type != PLAIN_PATTERN)
  1196.            Link_Textures(&(Object->Texture), Copy_Textures(Default_Texture));
  1197.        UNGET
  1198.        EXPECT
  1199.          CASE (PIGMENT_TOKEN)
  1200.            Parse_Begin ();
  1201.            Parse_Pigment ( &(Object->Texture->Pigment) );
  1202.            Parse_End ();
  1203.          END_CASE
  1204.  
  1205.          CASE (TNORMAL_TOKEN)
  1206.            Parse_Begin ();
  1207.            Parse_Tnormal ( &(Object->Texture->Tnormal) );
  1208.            Parse_End ();
  1209.          END_CASE
  1210.  
  1211.          CASE (FINISH_TOKEN)
  1212.            Parse_Finish ( &(Object->Texture->Finish) );
  1213.          END_CASE
  1214.  
  1215.          OTHERWISE
  1216.            UNGET
  1217.            EXIT
  1218.          END_CASE
  1219.        END_EXPECT
  1220.      END_CASE
  1221.  
  1222.      CASE (INVERSE_TOKEN)
  1223.        if (Object->Type & PATCH_OBJECT)
  1224.          Warn (0, "Cannot invert a patch object.");
  1225.        Invert_Object (Object);
  1226.      END_CASE
  1227.  
  1228.      CASE (STURM_TOKEN)
  1229.        if (!(Object->Type & STURM_OK_OBJECT))
  1230.          Not_With ("sturm","this object");
  1231.        Bool_Flag (Object, STURM_FLAG, (Allow_Float(1.0) > 0.0));
  1232.      END_CASE
  1233.  
  1234.      CASE (WATER_LEVEL_TOKEN)
  1235.        if (!(Object->Type & WATER_LEVEL_OK_OBJECT))
  1236.          Not_With ("water_level","this object");
  1237.        Temp_Water_Level = Parse_Float();
  1238.        if (opts.Language_Version < 200)
  1239.          Temp_Water_Level /=256.0;
  1240.        ((HFIELD *) Object)->bounding_box->bounds[0][Y] = 65536.0 * Temp_Water_Level;
  1241.      END_CASE
  1242.  
  1243.      CASE (SMOOTH_TOKEN)
  1244.        if (!(Object->Type & SMOOTH_OK_OBJECT))
  1245.          Not_With ("smooth","this object");
  1246.        /* Modification by Lummox JR, June 1999 */
  1247.        /*Set_Flag(Object, SMOOTHED_FLAG);*/
  1248.        ((HFIELD *)Object)->smooth_type = (int)Allow_Float(1.0);
  1249.        if(((HFIELD *)Object)->smooth_type!=0) Set_Flag(Object, SMOOTHED_FLAG);
  1250.        /* NK 1998 double_illuminate */
  1251.        /*Object->Type |= DOUBLE_ILLUMINATE;*/
  1252.        /*Set_Flag(Object, DOUBLE_ILLUMINATE_FLAG);*/
  1253.        /* NK ---- */
  1254.      END_CASE
  1255.  
  1256.      CASE (NO_SHADOW_TOKEN)
  1257.         /* NK phmap 2000-may-10 */
  1258.         Object->Ph_Flags |= PH_FLAG_PASSTHRU;
  1259.         /* NK ---- */
  1260.  
  1261.         Set_Flag(Object, NO_SHADOW_FLAG);
  1262.         Object->No_Shadow_Group = ALL_GROUP;
  1263.         EXPECT
  1264.           CASE (STRING_LITERAL_TOKEN)
  1265.             UNGET
  1266.             {
  1267.             /*YS sept 17 2000 Memory Leak*/
  1268.             char *tempstring=Parse_String();
  1269.             Object->No_Shadow_Group = Get_Light_Group(tempstring,&Tmp_Flag);
  1270.             POV_FREE(tempstring);
  1271.             /*YS*/
  1272.            }
  1273.               if (Tmp_Flag) Set_Flag(Object,INVERT_NO_SHADOW_GROUP);
  1274.           END_CASE
  1275.  
  1276.           OTHERWISE
  1277.             UNGET
  1278.             EXIT
  1279.           END_CASE
  1280.         END_EXPECT
  1281.       END_CASE
  1282.  
  1283. #ifdef NoImageNoReflectionPatch
  1284.    /* Object-Ray Options
  1285.         Do not intersect with camera rays [ENB 9/97] */
  1286.      CASE (NO_IMAGE_TOKEN)
  1287. #ifdef UnofficialBlocking
  1288.        parseUnofficialFeature(30);
  1289. #endif
  1290.        Set_Flag(Object, NO_IMAGE_FLAG);
  1291.        if ((Object->Methods == &CSG_Intersection_Methods) ||
  1292.            (Object->Methods == &CSG_Merge_Methods) ||
  1293.            (Object->Methods == &CSG_Union_Methods))
  1294.        {
  1295.          Set_CSG_Tree_Flag(Object, NO_IMAGE_FLAG);
  1296.        }
  1297.        END_CASE
  1298.  
  1299.      /* Object-Ray Options
  1300.         Do not intersect with reflection rays [ENB 9/97] */
  1301.      CASE (NO_REFLECTION_TOKEN)
  1302. #ifdef UnofficialBlocking
  1303.        parseUnofficialFeature(30);
  1304. #endif
  1305.             Set_Flag(Object, NO_REFLECTION_FLAG);
  1306.  
  1307.        if ((Object->Methods == &CSG_Intersection_Methods) ||
  1308.            (Object->Methods == &CSG_Merge_Methods) ||
  1309.            (Object->Methods == &CSG_Union_Methods))
  1310.        {
  1311.          Set_CSG_Tree_Flag(Object, NO_REFLECTION_FLAG);
  1312.        }
  1313.        END_CASE
  1314. #endif
  1315.  
  1316.      CASE (LIGHT_SOURCE_TOKEN)
  1317.        Error("Light source must be defined using new syntax.");
  1318.      END_CASE
  1319.  
  1320.     CASE (LIGHT_GROUP_TOKEN)
  1321.     {
  1322.         /*YS sept 17 2000 Memory leak */
  1323.         char *tempstring=Parse_String();
  1324.       Object->Light_Group = Get_Light_Group(tempstring,&Tmp_Flag);
  1325.       POV_FREE(tempstring); /*YS sept 17 Memory leak */
  1326.      }
  1327.       if (Object->Light_Group == NONE_GROUP) 
  1328.         Warn(300,"Light_Group of none is a special case, changed to All.\n");
  1329.       if (Tmp_Flag) Set_Flag(Object,INVERT_LIGHT_GROUP);
  1330.     END_CASE
  1331.  
  1332.      CASE(HIERARCHY_TOKEN)
  1333.        if (!(Object->Type & HIERARCHY_OK_OBJECT))
  1334.          Not_With ("hierarchy", "this object");
  1335.        Bool_Flag (Object, HIERARCHY_FLAG, (Allow_Float(1.0) > 0.0));
  1336.      END_CASE
  1337.  
  1338.      CASE(HOLLOW_TOKEN)
  1339.        Bool_Flag (Object, HOLLOW_FLAG, (Allow_Float(1.0) > 0.0));
  1340.        Set_Flag (Object, HOLLOW_SET_FLAG);
  1341.        if ((Object->Methods == &CSG_Intersection_Methods) ||
  1342.            (Object->Methods == &CSG_Merge_Methods) ||
  1343.            (Object->Methods == &CSG_Union_Methods))
  1344.        {
  1345.          Set_CSG_Children_Flag(Object, Test_Flag(Object, HOLLOW_FLAG), HOLLOW_FLAG, HOLLOW_SET_FLAG);
  1346.        }
  1347.      END_CASE
  1348.  
  1349.      /* NK 1998 double_illuminate */
  1350.      CASE(DOUBLE_ILLUMINATE_TOKEN)
  1351. #ifdef UnofficialBlocking
  1352.        parseUnofficialFeature(30);
  1353. #endif
  1354.        Set_Flag(Object, DOUBLE_ILLUMINATE_FLAG);
  1355.      END_CASE
  1356.      /* NK ---- */
  1357.  
  1358.      OTHERWISE
  1359.        UNGET
  1360.        EXIT
  1361.      END_CASE
  1362.    END_EXPECT
  1363.  
  1364.    /*
  1365.     * Assign bounding objects' bounding box to object
  1366.     * if object's bounding box is larger. [DB 9/94]
  1367.     */
  1368.  
  1369.    if (Object->Bound != NULL)
  1370.    {
  1371.      /* Get bounding objects bounding box. */
  1372.  
  1373.      Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  1374.      Make_Vector(Max,  BOUND_HUGE,  BOUND_HUGE,  BOUND_HUGE);
  1375.  
  1376.      for (Sib = Object->Bound; Sib != NULL; Sib = Sib->Sibling)
  1377.      {
  1378.        if (!Test_Flag(Sib, INVERTED_FLAG))
  1379.        {
  1380.          Min[X] = max(Min[X], Sib->BBox.Lower_Left[X]);
  1381.          Min[Y] = max(Min[Y], Sib->BBox.Lower_Left[Y]);
  1382.          Min[Z] = max(Min[Z], Sib->BBox.Lower_Left[Z]);
  1383.          Max[X] = min(Max[X], Sib->BBox.Lower_Left[X] + Sib->BBox.Lengths[X]);
  1384.          Max[Y] = min(Max[Y], Sib->BBox.Lower_Left[Y] + Sib->BBox.Lengths[Y]);
  1385.          Max[Z] = min(Max[Z], Sib->BBox.Lower_Left[Z] + Sib->BBox.Lengths[Z]);
  1386.        }
  1387.      }
  1388.  
  1389.      Make_BBox_from_min_max(BBox, Min, Max);
  1390.  
  1391.      /* Get bounding boxes' volumes. */
  1392.  
  1393.      BOUNDS_VOLUME(V1, BBox);
  1394.      BOUNDS_VOLUME(V2, Object->BBox);
  1395.  
  1396.      if (V1 < V2)
  1397.      {
  1398.        Object->BBox = BBox;
  1399.      }
  1400.    }
  1401.  
  1402.    /*
  1403.     * Assign clipping objects' bounding box to object
  1404.     * if object's bounding box is larger. [DB 9/94]
  1405.     */
  1406.  
  1407.    if (Object->Clip != NULL)
  1408.    {
  1409.      /* Get clipping objects bounding box. */
  1410.  
  1411.      Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  1412.      Make_Vector(Max,  BOUND_HUGE,  BOUND_HUGE,  BOUND_HUGE);
  1413.  
  1414.      for (Sib = Object->Clip; Sib != NULL; Sib = Sib->Sibling)
  1415.      {
  1416.        if (!Test_Flag(Sib, INVERTED_FLAG))
  1417.        {
  1418.          Min[X] = max(Min[X], Sib->BBox.Lower_Left[X]);
  1419.          Min[Y] = max(Min[Y], Sib->BBox.Lower_Left[Y]);
  1420.          Min[Z] = max(Min[Z], Sib->BBox.Lower_Left[Z]);
  1421.          Max[X] = min(Max[X], Sib->BBox.Lower_Left[X] + Sib->BBox.Lengths[X]);
  1422.          Max[Y] = min(Max[Y], Sib->BBox.Lower_Left[Y] + Sib->BBox.Lengths[Y]);
  1423.          Max[Z] = min(Max[Z], Sib->BBox.Lower_Left[Z] + Sib->BBox.Lengths[Z]);
  1424.        }
  1425.      }
  1426.  
  1427.      Make_BBox_from_min_max(BBox, Min, Max);
  1428.  
  1429.      /* Get bounding boxes' volumes. */
  1430.  
  1431.      BOUNDS_VOLUME(V1, BBox);
  1432.      BOUNDS_VOLUME(V2, Object->BBox);
  1433.  
  1434.      if (V1 < V2)
  1435.      {
  1436.        Object->BBox = BBox;
  1437.      }
  1438.    }
  1439. #ifdef InteriorTexturePatch
  1440.    if((Object->Texture ==NULL)&&(Object->Interior_Texture != NULL))
  1441.        Error("Interior texture given but no exterior texture. You must add an exterior texture for interior_texture to be used.");
  1442. #endif
  1443.    Parse_End ();
  1444.   }
  1445.  
  1446.  
  1447. #ifdef NoImageNoReflectionPatch
  1448. /* JG start */
  1449. static void Set_CSG_Tree_Flag(OBJECT *Object, unsigned long f)
  1450. {
  1451.   OBJECT *Sib;
  1452.  
  1453.   for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  1454.   {
  1455.     if ((Sib->Methods == &CSG_Intersection_Methods) ||
  1456.         (Sib->Methods == &CSG_Merge_Methods) ||
  1457.         (Sib->Methods == &CSG_Union_Methods))
  1458.     {
  1459.       Set_CSG_Tree_Flag(Sib, f);
  1460.     }
  1461.     Set_Flag(Sib,f);
  1462.   }
  1463. }
  1464. /* JG end */
  1465. #endif
  1466.  
  1467.  
  1468. /*****************************************************************************
  1469. *
  1470. * FUNCTION
  1471. *
  1472. * INPUT
  1473. *
  1474. * OUTPUT
  1475. *
  1476. * RETURNS
  1477. *
  1478. * AUTHOR
  1479. *
  1480. * DESCRIPTION
  1481. *
  1482. * CHANGES
  1483. *
  1484. ******************************************************************************/
  1485.  
  1486. static OBJECT *Parse_Sphere()
  1487. {
  1488.   SPHERE *Object;
  1489.  
  1490.   Parse_Begin();
  1491.  
  1492.   if ((Object = (SPHERE *)Parse_Object_Id()) != NULL)
  1493.   {
  1494.     return ((OBJECT *) Object);
  1495.   }
  1496.  
  1497.   Object = Create_Sphere();
  1498.  
  1499.   Parse_Vector(Object->Center);
  1500.  
  1501.   Parse_Comma();
  1502.  
  1503.   Object->Radius = Parse_Float();
  1504.  
  1505.   Compute_Sphere_BBox(Object);  
  1506.  
  1507.   Parse_Object_Mods((OBJECT *)Object);
  1508.  
  1509.   return((OBJECT *)Object);
  1510. }
  1511.  
  1512.  
  1513. /** poviso: O. & R.S. **/
  1514. #ifdef POVISO
  1515. /*****************************************************************************
  1516. *
  1517. * FUNCTION
  1518. *   Parse_Parametric
  1519. *
  1520. * INPUT
  1521. *
  1522. * OUTPUT
  1523. *
  1524. * RETURNS
  1525. *
  1526. * AUTHOR
  1527. *
  1528. * DESCRIPTION
  1529. *
  1530. * CHANGES
  1531. *
  1532. ******************************************************************************/
  1533. static OBJECT *Parse_Parametric( void )
  1534.   {
  1535.    PARAMETRIC *Object;
  1536.    char        flags;
  1537.    DBL         temp;
  1538.    char        PrecompFlag=0;
  1539.    int         PrecompDepth;
  1540.    
  1541.    Parse_Begin ();
  1542.  
  1543.    if ( (Object = (PARAMETRIC *)Parse_Object_Id()) != NULL)
  1544.       return ((OBJECT *) Object);
  1545.  
  1546.    Object = Create_Parametric();
  1547.  
  1548.    GET(FUNCTION_TOKEN);
  1549.  
  1550.    Object->Func[0]= Parse_Function();      Parse_Comma();
  1551.    flags= Object->Func[0]->Flags;
  1552.    
  1553.    Object->Func[1]= Parse_Function();      Parse_Comma();
  1554.    flags|= Object->Func[0]->Flags;
  1555.  
  1556.    Object->Func[2]= Parse_Function();                    
  1557.    flags|= Object->Func[0]->Flags;
  1558.  
  1559.    if (((flags) & (255- (OK_U|OK_V))) != 0)
  1560.      Error("Parametric: other variables used than u,v");
  1561.  
  1562.    GET (LEFT_ANGLE_TOKEN);
  1563.    Object->umin=Parse_Float();  Parse_Comma();
  1564.    Object->vmin=Parse_Float();
  1565.    GET (RIGHT_ANGLE_TOKEN);     Parse_Comma();
  1566.  
  1567.    GET (LEFT_ANGLE_TOKEN);
  1568.    Object->umax=Parse_Float();  Parse_Comma();
  1569.    Object->vmax=Parse_Float();
  1570.    GET (RIGHT_ANGLE_TOKEN);
  1571.  
  1572.    if (Object->umin>Object->umax) { temp= Object->umin; Object->umin= Object->umax; Object->umax=temp; }
  1573.    if (Object->vmin>Object->vmax) { temp= Object->vmin; Object->vmin= Object->vmax; Object->vmax=temp; }
  1574.  
  1575.    EXPECT
  1576.      CASE(ACCURACY_TOKEN)
  1577.        Object->accuracy= Parse_Float();
  1578.      END_CASE
  1579.      
  1580.      CASE(PRECOMPUTE_TOKEN)
  1581.         PrecompDepth= Parse_Float();
  1582.         Parse_Comma();
  1583.         GET(LEFT_SQUARE_TOKEN)
  1584.  
  1585.         while (1)
  1586.         {
  1587.           Get_Token();
  1588.           switch (Token.Function_Id)
  1589.           {
  1590.             case X_TOKEN: PrecompFlag|= OK_X; break;
  1591.             case Y_TOKEN: PrecompFlag|= OK_Y; break;
  1592.             case Z_TOKEN: PrecompFlag|= OK_Z; break;
  1593.             default:
  1594.              Error("Precompute: x, y or z expected");
  1595.            }
  1596.  
  1597.           Get_Token();
  1598.           if (Token.Token_Id == RIGHT_SQUARE_TOKEN) break;
  1599.           if (Token.Token_Id != COMMA_TOKEN) Parse_Error (COMMA_TOKEN);
  1600.          }
  1601.  
  1602.      END_CASE
  1603.  
  1604.  
  1605.      CASE_VECTOR
  1606.        Parse_Vector((Object->bounds[0]));     Parse_Comma();
  1607.        Parse_Vector((Object->bounds[1]));
  1608.     
  1609.         if (Object->bounds[0][X] > Object->bounds[1][X]) {
  1610.            temp = Object->bounds[0][X];
  1611.            Object->bounds[0][X] = Object->bounds[1][X];
  1612.            Object->bounds[1][X] = temp;
  1613.            }
  1614.         if (Object->bounds[0][Z] > Object->bounds[1][Z]) {
  1615.            temp = Object->bounds[0][Z];
  1616.            Object->bounds[0][Z] = Object->bounds[1][Z];
  1617.            Object->bounds[1][Z] = temp;
  1618.            }
  1619.         if (Object->bounds[0][Z] > Object->bounds[1][Z]) {
  1620.            temp = Object->bounds[0][Z];
  1621.            Object->bounds[0][Z] = Object->bounds[1][Z];
  1622.            Object->bounds[1][Z] = temp;
  1623.            }
  1624.      END_CASE
  1625.  
  1626. #ifdef IsoBlobPatch
  1627.      /* Lummox JR, July 1999 */
  1628.      CASE (TNORMAL_TOKEN)
  1629.        Object->normal_type = (char)(int)Allow_Float(1.0);
  1630.      END_CASE
  1631.      /* End Lummox JR's modifications */
  1632. #endif
  1633.      OTHERWISE
  1634.        UNGET
  1635.        EXIT
  1636.      END_CASE
  1637.  
  1638.    END_EXPECT
  1639.  
  1640.    Parse_Object_Mods ((OBJECT *)Object);
  1641.  
  1642.    if (PrecompFlag != 0) Object->PData= 
  1643.        Precompute_Parametric_Values(Object, PrecompFlag, PrecompDepth);
  1644.    return ((OBJECT *) Object);
  1645.   }
  1646.  
  1647. #endif
  1648. /** --- **/
  1649.  
  1650.  
  1651.  
  1652. /*****************************************************************************
  1653. *
  1654. * FUNCTION
  1655. *
  1656. * INPUT
  1657. *   
  1658. * OUTPUT
  1659. *   
  1660. * RETURNS
  1661. *   
  1662. * AUTHOR
  1663. *   
  1664. * DESCRIPTION
  1665. *
  1666. * CHANGES
  1667. *
  1668. ******************************************************************************/
  1669.  
  1670. static
  1671. OBJECT *Parse_Plane ()
  1672. {
  1673.    DBL len;
  1674.    PLANE *Object;
  1675.  
  1676.    Parse_Begin ();
  1677.  
  1678.    if ( (Object = (PLANE *)Parse_Object_Id()) != NULL)
  1679.       return ((OBJECT *) Object);
  1680.  
  1681.    Object = Create_Plane();
  1682.  
  1683.    Parse_Vector(Object->Normal_Vector);   Parse_Comma();
  1684.    VLength(len, Object->Normal_Vector);
  1685.    if (len < EPSILON)
  1686.    {
  1687.      Error("Degenerate plane normal.");
  1688.    }
  1689.    VInverseScaleEq(Object->Normal_Vector, len);
  1690.    Object->Distance = -Parse_Float();
  1691.  
  1692.    Compute_Plane_BBox(Object);
  1693.  
  1694.    Parse_Object_Mods ((OBJECT *)Object);
  1695.  
  1696.    return ((OBJECT *) Object);
  1697.   }
  1698.  
  1699.  
  1700.  
  1701. /*****************************************************************************
  1702. *
  1703. * FUNCTION
  1704. *
  1705. * INPUT
  1706. *   
  1707. * OUTPUT
  1708. *   
  1709. * RETURNS
  1710. *   
  1711. * AUTHOR
  1712. *   
  1713. * DESCRIPTION
  1714. *
  1715. * CHANGES
  1716. *
  1717. ******************************************************************************/
  1718.  
  1719. static
  1720. OBJECT *Parse_HField ()
  1721. {
  1722.   HFIELD *Object;
  1723.   VECTOR Local_Vector;
  1724.   IMAGE *Image;
  1725.  
  1726.   Parse_Begin ();
  1727.  
  1728.   if ( (Object = (HFIELD *)Parse_Object_Id()) != NULL)
  1729.       return ((OBJECT *) Object);
  1730.  
  1731.    Object = Create_HField();
  1732.  
  1733.    Image = Parse_Image (HF_FILE);
  1734.    Image->Use_Colour_Flag = FALSE;
  1735.  
  1736.    Make_Vector(Object->bounding_box->bounds[0], 0.0, 0.0, 0.0);
  1737.  
  1738.    if (Image->File_Type == POT_FILE)
  1739.    {
  1740.      Object->bounding_box->bounds[1][X] = Image->width/2.0 - 1.0;
  1741.    }
  1742.    else
  1743.    {
  1744.      Object->bounding_box->bounds[1][X] = Image->width - 1.0;
  1745.    }
  1746.  
  1747.    Object->bounding_box->bounds[1][Y] = 65536.0;
  1748.    Object->bounding_box->bounds[1][Z] = Image->height - 1.0;
  1749.  
  1750.    Make_Vector(Local_Vector,
  1751.      1.0 / (Object->bounding_box->bounds[1][X]),
  1752.      1.0 / (Object->bounding_box->bounds[1][Y]),
  1753.      1.0 / (Object->bounding_box->bounds[1][Z]));
  1754.  
  1755.    Compute_Scaling_Transform(Object->Trans, Local_Vector);
  1756.  
  1757.    Parse_Object_Mods ((OBJECT *)Object);
  1758.  
  1759.    Compute_HField(Object, Image);
  1760.  
  1761.    Compute_HField_BBox(Object);
  1762.  
  1763.    Destroy_Image (Image);
  1764.  
  1765.    return ((OBJECT *) Object);
  1766.   }
  1767.  
  1768.  
  1769.  
  1770. /*****************************************************************************
  1771. *
  1772. * FUNCTION
  1773. *
  1774. * INPUT
  1775. *   
  1776. * OUTPUT
  1777. *   
  1778. * RETURNS
  1779. *   
  1780. * AUTHOR
  1781. *   
  1782. * DESCRIPTION
  1783. *
  1784. * CHANGES
  1785. *
  1786. ******************************************************************************/
  1787.  
  1788. static OBJECT *Parse_Triangle()
  1789. {
  1790.   TRIANGLE *Object;
  1791.  
  1792.   Parse_Begin();
  1793.  
  1794.   if ((Object = (TRIANGLE *)Parse_Object_Id()) != NULL)
  1795.   {
  1796.     return((OBJECT *) Object);
  1797.   }
  1798.  
  1799.   Object = Create_Triangle();
  1800.  
  1801.   Parse_Vector(Object->P1);    Parse_Comma();
  1802.   Parse_Vector(Object->P2);    Parse_Comma();
  1803.   Parse_Vector(Object->P3);
  1804.  
  1805.   /* Note that Compute_Triangle also computes the bounding box. */
  1806.  
  1807.   if (!Compute_Triangle(Object, FALSE))
  1808.   {
  1809.     Warn(0, "Degenerate triangle. Please remove.");
  1810.   }
  1811.  
  1812.   Parse_Object_Mods((OBJECT *)Object);
  1813.  
  1814.   return((OBJECT *)Object);
  1815. }
  1816.  
  1817.  
  1818.  
  1819. /*****************************************************************************
  1820. *
  1821. * FUNCTION
  1822. *
  1823. * INPUT
  1824. *   
  1825. * OUTPUT
  1826. *   
  1827. * RETURNS
  1828. *   
  1829. * AUTHOR
  1830. *   
  1831. * DESCRIPTION
  1832. *
  1833. * CHANGES
  1834. *
  1835. ******************************************************************************/
  1836.  
  1837. static
  1838. OBJECT *Parse_Smooth_Triangle ()
  1839. {
  1840.    SMOOTH_TRIANGLE *Object;
  1841.    short degen;
  1842.    DBL vlen;
  1843.  
  1844.    degen=FALSE;
  1845.  
  1846.    Parse_Begin ();
  1847.  
  1848.    if ( (Object = (SMOOTH_TRIANGLE *)Parse_Object_Id()) != NULL)
  1849.       return ((OBJECT *) Object);
  1850.  
  1851.    Object = Create_Smooth_Triangle();
  1852.  
  1853.    Parse_Vector (Object->P1);    Parse_Comma();
  1854.    Parse_Vector (Object->N1);    Parse_Comma();
  1855.  
  1856.    VLength(vlen,Object->N1);
  1857.  
  1858.    if (vlen == 0.0)
  1859.      degen=TRUE;
  1860.    else
  1861.      VNormalize (Object->N1, Object->N1);
  1862.  
  1863.    Parse_Vector (Object->P2);    Parse_Comma();
  1864.    Parse_Vector (Object->N2);    Parse_Comma();
  1865.  
  1866.    VLength(vlen,Object->N2);
  1867.  
  1868.    if (vlen == 0.0)
  1869.      degen=TRUE;
  1870.    else
  1871.      VNormalize (Object->N2, Object->N2);
  1872.  
  1873.    Parse_Vector (Object->P3);    Parse_Comma();
  1874.    Parse_Vector (Object->N3);
  1875.  
  1876.    VLength(vlen,Object->N3);
  1877.  
  1878.    if (vlen == 0.0)
  1879.      degen=TRUE;
  1880.    else
  1881.      VNormalize (Object->N3, Object->N3);
  1882.  
  1883.    if (!degen)
  1884.    {
  1885.      degen=!Compute_Triangle ((TRIANGLE *) Object,TRUE);
  1886.    }
  1887.  
  1888.    if (degen)
  1889.    {
  1890.      Warn(0, "Degenerate triangle. Please remove.");
  1891.    }
  1892.  
  1893.    Compute_Triangle_BBox((TRIANGLE *)Object);
  1894.  
  1895.    Parse_Object_Mods ((OBJECT *)Object);
  1896.  
  1897.    return ((OBJECT *) Object);
  1898.  }
  1899.  
  1900.  
  1901.  
  1902. /*****************************************************************************
  1903. *
  1904. * FUNCTION
  1905. *
  1906. * INPUT
  1907. *   
  1908. * OUTPUT
  1909. *   
  1910. * RETURNS
  1911. *   
  1912. * AUTHOR
  1913. *   
  1914. * DESCRIPTION
  1915. *
  1916. * CHANGES
  1917. *
  1918. ******************************************************************************/
  1919.  
  1920. static
  1921. OBJECT *Parse_Quadric ()
  1922. {
  1923.    VECTOR Min, Max;
  1924.    QUADRIC *Object;
  1925.  
  1926.    Parse_Begin ();
  1927.  
  1928.    if ( (Object = (QUADRIC *)Parse_Object_Id()) != NULL)
  1929.       return ((OBJECT *) Object);
  1930.  
  1931.    Object = Create_Quadric();
  1932.  
  1933.         Parse_Vector(Object->Square_Terms);     Parse_Comma();
  1934.         Parse_Vector(Object->Mixed_Terms);      Parse_Comma();
  1935.         Parse_Vector(Object->Terms);            Parse_Comma();
  1936.    Object->Constant = Parse_Float();
  1937.  
  1938.    Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  1939.    Make_Vector(Max,  BOUND_HUGE,  BOUND_HUGE,  BOUND_HUGE);
  1940.  
  1941.    Compute_Quadric_BBox(Object, Min, Max);  
  1942.  
  1943.    Parse_Object_Mods ((OBJECT *)Object);
  1944.  
  1945.    return ((OBJECT *) Object);
  1946.   }
  1947.  
  1948.  
  1949.  
  1950. /*****************************************************************************
  1951. *
  1952. * FUNCTION
  1953. *
  1954. * INPUT
  1955. *   
  1956. * OUTPUT
  1957. *   
  1958. * RETURNS
  1959. *   
  1960. * AUTHOR
  1961. *   
  1962. * DESCRIPTION
  1963. *
  1964. * CHANGES
  1965. *
  1966. ******************************************************************************/
  1967.  
  1968. static
  1969. OBJECT *Parse_Box ()
  1970. {
  1971.    BOX *Object;
  1972.    DBL temp;
  1973.  
  1974.    Parse_Begin ();
  1975.  
  1976.    if ( (Object = (BOX *)Parse_Object_Id()) != NULL)
  1977.       return ((OBJECT *) Object);
  1978.  
  1979.    Object = Create_Box();
  1980.  
  1981.         Parse_Vector(Object->bounds[0]);     Parse_Comma();
  1982.         Parse_Vector(Object->bounds[1]);
  1983.  
  1984.     if (Object->bounds[0][X] > Object->bounds[1][X]) {
  1985.        temp = Object->bounds[0][X];
  1986.        Object->bounds[0][X] = Object->bounds[1][X];
  1987.        Object->bounds[1][X] = temp;
  1988.        }
  1989.     if (Object->bounds[0][Y] > Object->bounds[1][Y]) {
  1990.        temp = Object->bounds[0][Y];
  1991.        Object->bounds[0][Y] = Object->bounds[1][Y];
  1992.        Object->bounds[1][Y] = temp;
  1993.        }
  1994.     if (Object->bounds[0][Z] > Object->bounds[1][Z]) {
  1995.        temp = Object->bounds[0][Z];
  1996.        Object->bounds[0][Z] = Object->bounds[1][Z];
  1997.        Object->bounds[1][Z] = temp;
  1998.        }
  1999.  
  2000.    Compute_Box_BBox(Object);
  2001.  
  2002.    Parse_Object_Mods ((OBJECT *)Object);
  2003.  
  2004.    return ((OBJECT *) Object);
  2005.   }
  2006.  
  2007.  
  2008. /** poviso: '96 R.S. **/
  2009. #ifdef POVISO
  2010. /*****************************************************************************
  2011. *
  2012. * FUNCTION      OBJECT *Parse_IsoSurface ( int parse_type)
  2013. *
  2014. * INPUT
  2015. *   
  2016. * OUTPUT
  2017. *   
  2018. * RETURNS
  2019. *   
  2020. * AUTHOR                          R. Suzuki
  2021. *   
  2022. * DESCRIPTION
  2023. *
  2024. * CHANGES
  2025. *
  2026. ******************************************************************************/
  2027. void Iso_Parse_Box(ISOSURFACE *Object)
  2028. {
  2029.   DBL temp;
  2030.   int flag=FALSE;
  2031.  
  2032.   Get_Token ();
  2033.   if (Token.Token_Id == LEFT_CURLY_TOKEN) flag=TRUE;
  2034.   else
  2035.     UNGET
  2036.   Parse_Vector(Object->bounds[0]);     Parse_Comma();
  2037.   Parse_Vector(Object->bounds[1]);
  2038.   if (Object->bounds[0][X] > Object->bounds[1][X]) 
  2039.   {
  2040.     temp = Object->bounds[0][X];
  2041.     Object->bounds[0][X] = Object->bounds[1][X];
  2042.     Object->bounds[1][X] = temp;
  2043.   }
  2044.   if (Object->bounds[0][Z] > Object->bounds[1][Z]) 
  2045.   {
  2046.     temp = Object->bounds[0][Z];
  2047.     Object->bounds[0][Z] = Object->bounds[1][Z];
  2048.     Object->bounds[1][Z] = temp;
  2049.   }
  2050.   if (Object->bounds[0][Z] > Object->bounds[1][Z]) 
  2051.   {
  2052.     temp = Object->bounds[0][Z];
  2053.     Object->bounds[0][Z] = Object->bounds[1][Z];
  2054.     Object->bounds[1][Z] = temp;
  2055.   }
  2056.   if (flag==TRUE)
  2057.   {
  2058.     Get_Token ();
  2059.     if (Token.Token_Id != RIGHT_CURLY_TOKEN) 
  2060.     Error("No matching } in isosurface");
  2061.   }
  2062.   Object->container_shape=0;
  2063.   Compute_Box_BBox((BOX *)Object);
  2064. }
  2065.  
  2066. void Iso_Parse_Sphere(ISOSURFACE *Object)
  2067. {
  2068. /*YS   DBL temp;*/
  2069.   int flag=FALSE;
  2070.  
  2071.   Get_Token ();
  2072.   if (Token.Token_Id == LEFT_CURLY_TOKEN) flag=TRUE; else UNGET
  2073.   Parse_Vector(Object->bounds[0]);  Parse_Comma();
  2074.   Object->bounds[1][X]=Parse_Float();
  2075.   Object->container_shape=1; 
  2076.   if (flag==TRUE)
  2077.   {
  2078.     Get_Token ();
  2079.     if (Token.Token_Id != RIGHT_CURLY_TOKEN) 
  2080.     Error("No matching } in isosurface");
  2081.   }
  2082.   Compute_Sphere_BBox((SPHERE *)Object);  
  2083.  
  2084. }
  2085.  
  2086. static OBJECT *Parse_IsoSurface (int parse_type)
  2087. {
  2088.   ISOSURFACE *Object;
  2089.   int imax;
  2090.   char *tstr;
  2091.   char flags= OK_X|OK_Y|OK_Z;
  2092.   int parsed_contained_by;
  2093.  
  2094.   parsed_contained_by = FALSE;
  2095.  
  2096.   Parse_Begin ();
  2097.  
  2098.   if ( (Object = (ISOSURFACE *)Parse_Object_Id()) != NULL)
  2099.     return ((OBJECT *) Object);
  2100.   
  2101.   Object = (ISOSURFACE *)Create_IsoSurface();
  2102.  
  2103.   EXPECT
  2104.     CASE(FUNCTION_TOKEN)
  2105.       Object->Func= Parse_Function();
  2106.       if (Object->Func->Lib==NULL) 
  2107.         Object->Func->Lib=Object->Lib;/* RS May '97 */
  2108.       Object->Func->isosf=Object;
  2109.       Load_Function(Object->Func, Object->Func->func_name);/* RS May '97 */
  2110.     END_CASE
  2111.  
  2112.     /* NK switched to contained_by */
  2113.     CASE (CONTAINED_BY_TOKEN)
  2114.       parsed_contained_by = TRUE;
  2115.       /* use "open" or "close" to change the closed flag */
  2116.       Parse_Begin ();
  2117.       EXPECT
  2118.         CASE(BOX_TOKEN)
  2119.           Iso_Parse_Box(Object);
  2120.         END_CASE
  2121.         CASE(SPHERE_TOKEN)
  2122.           Iso_Parse_Sphere(Object);
  2123.         END_CASE
  2124.         OTHERWISE
  2125.           UNGET
  2126.           EXIT
  2127.         END_CASE
  2128.       END_EXPECT
  2129.       Parse_End ();
  2130.     END_CASE
  2131.  
  2132.  
  2133.  
  2134.     CASE(THRESHOLD_TOKEN)
  2135.       if (Object->Func !=NULL)
  2136.       {
  2137.         Object->Func->threshold = Parse_Float();
  2138.       }
  2139.       else
  2140.       Error("'function' is not defined \n"); 
  2141.     END_CASE
  2142.  
  2143.     CASE(ACCURACY_TOKEN)
  2144.       Object->accuracy = Parse_Float();
  2145.     END_CASE
  2146.  
  2147.     CASE(SIGN_TOKEN)
  2148.       Object->Func->sign = Parse_Float();
  2149.     END_CASE
  2150.  
  2151.     CASE(MAX_GRADIENT_TOKEN)
  2152.       if (Object->Func !=NULL)
  2153.       {
  2154.         Object->Func->Max_gradient = Parse_Float();
  2155.         Object->gradient_flag=0;
  2156.       }
  2157.       else
  2158.         Error("'function' is not defined \n"); 
  2159.     END_CASE
  2160.  
  2161.     CASE(MAX_TRACE_TOKEN)
  2162.       Object->max_trace = (short)Parse_Float();
  2163.     END_CASE
  2164.  
  2165.     CASE(NOEVAL_TOKEN)
  2166.       Object->Eval=0;
  2167.     END_CASE
  2168.  
  2169.     CASE(EVAL_TOKEN)
  2170.       Object->Eval=1;
  2171.  
  2172.      Get_Token();
  2173.       if (Token.Token_Id == LEFT_ANGLE_TOKEN)
  2174.       { 
  2175.         Unget_Token();
  2176.         Parse_Parm(3, &imax);
  2177.  
  2178.         memcpy( Object->grad_parm, iso_p, imax *sizeof(DBL));
  2179.       }
  2180.       else Unget_Token();
  2181.     END_CASE
  2182.  
  2183.     CASE(OPEN_TOKEN)
  2184.       Object->closed=0;
  2185.     END_CASE
  2186.  
  2187.     CASE(CLOSE_TOKEN)
  2188.       Object->closed=1;
  2189.     END_CASE
  2190.  
  2191.     CASE(LIBRARY_TOKEN)
  2192.       GET (STRING_LITERAL_TOKEN);
  2193.       tstr = (char*)POV_MALLOC (strlen(Token.Token_String) + 1, "lib_name");
  2194.       strcpy (tstr, Token.Token_String);
  2195.       Object->Lib= (LIBRARY*)POV_MALLOC (sizeof(LIBRARY), "library struct");
  2196.       Get_Token();
  2197.       Load_Lib(Object->Lib, tstr); /* RS July 18  '96 */
  2198.       if (Token.Token_Id == COMMA_TOKEN)
  2199.       {
  2200.         Get_Token();
  2201.         if(Token.Token_Id==ARRAY_ID_TOKEN)
  2202.         {
  2203.           Object->Lib->pClient=(char*)(*(Token.DataPtr));
  2204.           Object->Lib->pClientDataSource=PCLIENTDATA_ARRAY;
  2205.         }
  2206.         else 
  2207.         {
  2208.           Unget_Token();
  2209.           /* .. if its not an array, it should be a filename*/
  2210.             Object->Lib->pClient =(char*)Parse_String();
  2211.           Object->Lib->pClientDataSource=PCLIENTDATA_FILE;
  2212.         }
  2213.         /*--dfs*/
  2214.         if (Token.Token_Id == COMMA_TOKEN) 
  2215.         {
  2216.           Parse_Parm(0, &Object->Lib->pnum);
  2217.           Object->Lib->parm = (DBL *) POV_MALLOC (Object->Lib->pnum *sizeof(DBL), "isosurface lib_parm");
  2218.           memcpy( Object->Lib->parm, iso_p, Object->Lib->pnum*sizeof(DBL));
  2219.         }
  2220.         else Unget_Token();
  2221.       }
  2222.       /* R.S. Sep 96*/
  2223.       else 
  2224.       {
  2225.         Unget_Token();Object->Lib->pClientData =0;
  2226.       }
  2227.       Init_Lib(Object->Lib);
  2228.       POV_FREE(tstr);
  2229.     END_CASE
  2230.  
  2231.     CASE(METHOD_TOKEN)
  2232.       Object->method = (int)(15.-Parse_Float()*10.);
  2233.     END_CASE
  2234.  
  2235.     CASE(ALL_INTERSECTIONS_TOKEN)
  2236.       Object->max_trace= ISOSURFACE_MAXTRACE;
  2237.     END_CASE
  2238.  
  2239. #ifdef IsoBlobPatch
  2240.      /* Lummox JR, July 1999 */
  2241.      CASE (TNORMAL_TOKEN)
  2242. #ifdef UnofficialBlocking
  2243.        parseUnofficialFeature(30);
  2244. #endif
  2245.        Object->normal_type = (char)(int)Allow_Float(1.0);
  2246.      END_CASE
  2247.      /* End Lummox JR's modifications */
  2248. #endif
  2249.  
  2250.      OTHERWISE
  2251.        UNGET
  2252.        EXIT
  2253.      END_CASE
  2254.    END_EXPECT
  2255.  
  2256.    if (Object->Func == NULL)
  2257.      Error("'function' is not defined");
  2258.    if (Object->accuracy <= 0.)
  2259.      Error("isosurface component ACCURACY");
  2260.    if (Object->Func->Max_gradient <= 0.)
  2261.      Error("isosurface component MAXGRADIENT");
  2262.    if (Object->max_trace > ISOSURFACE_MAXTRACE)
  2263.      Error("isosurface component MAXTRACE>(ISOSURFACE_MAXTRACE)");
  2264.    if (Object->max_trace < 0)
  2265.      Error("isosurface component MAXTRACE should be >1");
  2266.    if (!parsed_contained_by)
  2267.      Error("isosurface requires contained_by");
  2268.  
  2269.    if (!strcmp(Object->Func->func_name,"imp_func")) Object->method +=2;
  2270.    if (Object->Func->m_flag==1) Object->method -=3;
  2271.  
  2272.    Parse_Object_Mods ((OBJECT *)Object);
  2273.    return ((OBJECT *) Object);
  2274. }
  2275. #endif
  2276. /** --- **/
  2277.  
  2278.  
  2279. /*****************************************************************************
  2280. *
  2281. * FUNCTION
  2282. *
  2283. * INPUT
  2284. *   
  2285. * OUTPUT
  2286. *   
  2287. * RETURNS
  2288. *   
  2289. * AUTHOR
  2290. *   
  2291. * DESCRIPTION
  2292. *
  2293. * CHANGES
  2294. *    speed improvements (FastDiscPatch) added April 18 by Dejan Milosavljevic
  2295. *
  2296. ******************************************************************************/
  2297.  
  2298. static OBJECT *Parse_Disc (void)
  2299. {
  2300.    DISC *Object;
  2301. #ifndef FastDiscPatch
  2302.    DBL tmpf;
  2303.    Parse_Begin ();
  2304.  
  2305.    if ( (Object = (DISC *)Parse_Object_Id()) != NULL)
  2306.       return ((OBJECT *) Object);
  2307.  
  2308.    Object = Create_Disc();
  2309.  
  2310.    Parse_Vector(Object->center); Parse_Comma ();
  2311.    Parse_Vector(Object->normal); Parse_Comma ();
  2312.  
  2313.    VNormalize(Object->normal, Object->normal);
  2314.  
  2315.    tmpf = Parse_Float(); Parse_Comma ();
  2316.    Object->oradius2 = tmpf * tmpf;
  2317.  
  2318.    EXPECT
  2319.      CASE_FLOAT
  2320.        tmpf = Parse_Float();
  2321.        Object->iradius2 = tmpf * tmpf;
  2322.      END_CASE
  2323.  
  2324.      OTHERWISE
  2325.        UNGET
  2326.        EXIT
  2327.      END_CASE
  2328.    END_EXPECT
  2329.  
  2330.    /* Calculate info needed for ray-disc intersections */
  2331.    VDot(tmpf, Object->center, Object->normal);
  2332.    Object->d = -tmpf;
  2333.  
  2334.    Compute_Disc(Object);  
  2335.  
  2336.    Parse_Object_Mods ((OBJECT *)Object);
  2337.  
  2338.    return ((OBJECT *) Object);
  2339. #else
  2340.    DBL inner_radius, outer_radius;
  2341.    VECTOR center, normal;
  2342.    Parse_Begin ();
  2343.  
  2344.    if ( (Object = (DISC *)Parse_Object_Id()) != NULL)
  2345.       return ((OBJECT *) Object);
  2346.  
  2347.    Object = Create_Disc();
  2348.  
  2349.    Parse_Vector(center); Parse_Comma ();
  2350.    Parse_Vector(normal); Parse_Comma ();
  2351.  
  2352.    outer_radius = Parse_Float(); Parse_Comma ();
  2353.    inner_radius = 0.0;
  2354.  
  2355.    EXPECT
  2356.      CASE_FLOAT
  2357.        inner_radius = Parse_Float();
  2358.      END_CASE
  2359.  
  2360.      OTHERWISE
  2361.        UNGET
  2362.        EXIT
  2363.      END_CASE
  2364.    END_EXPECT
  2365.  
  2366. #ifndef FastDiscPatch
  2367.    /* Calculate info needed for ray-disc intersections */
  2368.    VDot(Object->d, Object->center, Object->normal);
  2369.    Object->d = -Object->d;
  2370. #endif
  2371.  
  2372.    Compute_Disc( Object, center, normal, inner_radius, outer_radius );
  2373.  
  2374.    Parse_Object_Mods ((OBJECT *)Object);
  2375.  
  2376.    return ((OBJECT *) Object);
  2377. #endif
  2378.  
  2379.  
  2380. }
  2381.  
  2382.  
  2383.  
  2384.  
  2385. /*****************************************************************************
  2386. *
  2387. * FUNCTION
  2388. *
  2389. * INPUT
  2390. *   
  2391. * OUTPUT
  2392. *   
  2393. * RETURNS
  2394. *   
  2395. * AUTHOR
  2396. *   
  2397. * DESCRIPTION
  2398. *
  2399. * CHANGES
  2400. *
  2401. ******************************************************************************/
  2402.  
  2403. static
  2404. OBJECT *Parse_Cylinder ()
  2405. {
  2406.    CONE *Object;
  2407.  
  2408.    Parse_Begin ();
  2409.  
  2410.    if ( (Object = (CONE *)Parse_Object_Id()) != NULL)
  2411.       return ((OBJECT *) Object);
  2412.  
  2413.    Object = Create_Cylinder();
  2414.  
  2415.         Parse_Vector(Object->apex);  Parse_Comma ();
  2416.         Parse_Vector(Object->base);  Parse_Comma ();
  2417.    Object->apex_radius = Parse_Float();
  2418.    Object->base_radius = Object->apex_radius;
  2419.  
  2420.    EXPECT
  2421.      CASE(OPEN_TOKEN)
  2422.        Clear_Flag(Object, CLOSED_FLAG);
  2423.        EXIT
  2424.      END_CASE
  2425.  
  2426.      OTHERWISE
  2427.        UNGET
  2428.        EXIT
  2429.      END_CASE
  2430.    END_EXPECT
  2431.  
  2432.    Compute_Cylinder_Data((OBJECT *)Object);
  2433.  
  2434.    Compute_Cone_BBox(Object);
  2435.  
  2436.    Parse_Object_Mods ((OBJECT *)Object);
  2437.  
  2438.    return ((OBJECT *) Object);
  2439.   }
  2440.  
  2441.  
  2442.  
  2443. /*****************************************************************************
  2444. *
  2445. * FUNCTION
  2446. *
  2447. * INPUT
  2448. *   
  2449. * OUTPUT
  2450. *   
  2451. * RETURNS
  2452. *   
  2453. * AUTHOR
  2454. *   
  2455. * DESCRIPTION
  2456. *
  2457. * CHANGES
  2458. *
  2459. ******************************************************************************/
  2460.  
  2461. static
  2462. OBJECT *Parse_Cone ()
  2463. {
  2464.    CONE *Object;
  2465.  
  2466.    Parse_Begin ();
  2467.  
  2468.    if ( (Object = (CONE *)Parse_Object_Id()) != NULL)
  2469.       return ((OBJECT *) Object);
  2470.  
  2471.    Object = Create_Cone();
  2472.  
  2473.         Parse_Vector(Object->apex);  Parse_Comma ();
  2474.         Object->apex_radius = Parse_Float();  Parse_Comma ();
  2475.  
  2476.         Parse_Vector(Object->base);  Parse_Comma ();
  2477.    Object->base_radius = Parse_Float();
  2478.  
  2479.    EXPECT
  2480.      CASE(OPEN_TOKEN)
  2481.        Clear_Flag(Object, CLOSED_FLAG);
  2482.        EXIT
  2483.      END_CASE
  2484.      
  2485.      OTHERWISE
  2486.        UNGET
  2487.        EXIT
  2488.      END_CASE
  2489.    END_EXPECT
  2490.  
  2491.    /* Compute run-time values for the cone */
  2492.    Compute_Cone_Data((OBJECT *)Object);
  2493.  
  2494.    Compute_Cone_BBox(Object);  
  2495.  
  2496.    Parse_Object_Mods ((OBJECT *)Object);
  2497.  
  2498.    return ((OBJECT *) Object);
  2499.   }
  2500.  
  2501.  
  2502.  
  2503. /*****************************************************************************
  2504. *
  2505. * FUNCTION
  2506. *
  2507. *   Parse_Blob_Element_Mods
  2508. *
  2509. * INPUT
  2510. *   
  2511. * OUTPUT
  2512. *   
  2513. * RETURNS
  2514. *   
  2515. * AUTHOR
  2516. *
  2517. *   Dieter Bayer
  2518. *   
  2519. * DESCRIPTION
  2520. *
  2521. *   -
  2522. *
  2523. * CHANGES
  2524. *
  2525. *   Sep 1994 : Creation.
  2526. *
  2527. ******************************************************************************/
  2528.  
  2529. static void Parse_Blob_Element_Mods(BLOB_ELEMENT *Element)
  2530. {
  2531.   VECTOR Local_Vector;
  2532.   MATRIX Local_Matrix;
  2533.   TRANSFORM Local_Trans;
  2534.   TEXTURE *Local_Texture;
  2535.  
  2536.   EXPECT
  2537.     CASE (TRANSLATE_TOKEN)
  2538.       Parse_Vector (Local_Vector);
  2539.       Translate_Blob_Element (Element, Local_Vector);
  2540.     END_CASE
  2541.  
  2542.     CASE (ROTATE_TOKEN)
  2543.       Parse_Vector (Local_Vector);
  2544.       Rotate_Blob_Element (Element, Local_Vector);
  2545.     END_CASE
  2546.  
  2547.     CASE (SCALE_TOKEN)
  2548.       Parse_Scale_Vector (Local_Vector);
  2549.       Scale_Blob_Element (Element, Local_Vector);
  2550.     END_CASE
  2551.  
  2552.     CASE (TRANSFORM_TOKEN)
  2553. #ifndef TransformPatch /* Chris Huff april 2000 */
  2554.       GET(TRANSFORM_ID_TOKEN)
  2555.       Transform_Blob_Element (Element, (TRANSFORM *)Token.Data);
  2556. #else
  2557.        {
  2558.            TRANSFORM * Trans = Parse_Transform();
  2559.            Transform_Blob_Element (Element, Trans);
  2560.             /*YS sept 17 2000 Memory leak*/
  2561.                 POV_FREE(Trans);
  2562.        }
  2563. #endif
  2564.     END_CASE
  2565.  
  2566.     CASE (MATRIX_TOKEN)
  2567.       Parse_Matrix (Local_Matrix);
  2568.       Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  2569.       Transform_Blob_Element (Element, &Local_Trans);
  2570.     END_CASE
  2571.  
  2572.     CASE (TEXTURE_TOKEN)
  2573.       Parse_Begin ();
  2574.       Local_Texture = Parse_Texture();
  2575.       Parse_End ();
  2576.       Link_Textures(&Element->Texture, Local_Texture);
  2577.     END_CASE
  2578.  
  2579.     CASE3 (PIGMENT_TOKEN, TNORMAL_TOKEN, FINISH_TOKEN)
  2580.       if (Element->Texture == NULL)
  2581.       {
  2582.         Element->Texture = Copy_Textures(Default_Texture);
  2583.       }
  2584.       else
  2585.       {
  2586.         if (Element->Texture->Type != PLAIN_PATTERN)
  2587.         {
  2588.           Link_Textures(&Element->Texture, Copy_Textures(Default_Texture));
  2589.         }
  2590.       }
  2591.       UNGET
  2592.       EXPECT
  2593.         CASE (PIGMENT_TOKEN)
  2594.           Parse_Begin ();
  2595.           Parse_Pigment(&Element->Texture->Pigment);
  2596.           Parse_End ();
  2597.         END_CASE
  2598.  
  2599.         CASE (TNORMAL_TOKEN)
  2600.           Parse_Begin ();
  2601.           Parse_Tnormal(&Element->Texture->Tnormal);
  2602.           Parse_End ();
  2603.         END_CASE
  2604.  
  2605.         CASE (FINISH_TOKEN)
  2606.           Parse_Finish(&Element->Texture->Finish);
  2607.         END_CASE
  2608.  
  2609.         OTHERWISE
  2610.           UNGET
  2611.           EXIT
  2612.         END_CASE
  2613.       END_EXPECT
  2614.     END_CASE
  2615.  
  2616.     OTHERWISE
  2617.       UNGET
  2618.       EXIT
  2619.     END_CASE
  2620.   END_EXPECT
  2621.  
  2622.   Parse_End();
  2623.  
  2624.   /* Postprocess to make sure that HAS_FILTER will be set correctly. */
  2625.  
  2626.   Post_Textures(Element->Texture);
  2627. }
  2628.  
  2629.  
  2630.  
  2631. /*****************************************************************************
  2632. *
  2633. * FUNCTION
  2634. *
  2635. *   Parse_Blob
  2636. *
  2637. * INPUT
  2638. *
  2639. * OUTPUT
  2640. *   
  2641. * RETURNS
  2642. *   
  2643. * AUTHOR
  2644. *
  2645. *   Dieter Bayer
  2646. *   
  2647. * DESCRIPTION
  2648. *
  2649. *   -
  2650. *
  2651. * CHANGES
  2652. *
  2653. *   Jul 1994 : Creation.
  2654. *
  2655. ******************************************************************************/
  2656.  
  2657. #ifdef BlobPatternPatch
  2658. OBJECT *Parse_Blob( void)
  2659. #else
  2660. static OBJECT *Parse_Blob()
  2661. #endif
  2662. {
  2663.   int npoints;
  2664.   DBL threshold;
  2665.   VECTOR Axis, Base, Apex;
  2666.   BLOB *Object;
  2667.   BLOB_LIST *blob_components, *blob_component;
  2668.  
  2669.   Parse_Begin();
  2670.  
  2671.   if ((Object = (BLOB *)Parse_Object_Id()) != NULL)
  2672.   {
  2673.     return ((OBJECT *) Object);
  2674.   }
  2675.  
  2676.   Object = Create_Blob();
  2677.  
  2678.   blob_components = NULL;
  2679.  
  2680.   npoints = 0;
  2681.  
  2682.   threshold = 1.0;
  2683.  
  2684.   EXPECT
  2685.     CASE (THRESHOLD_TOKEN)
  2686.       threshold = Parse_Float();
  2687.     END_CASE
  2688.  
  2689.  
  2690.     /*************************************************************************
  2691.      * Read sperical component (old syntax).
  2692.      *************************************************************************/
  2693.  
  2694.     CASE (COMPONENT_TOKEN)
  2695.       blob_component = Create_Blob_List_Element();
  2696.  
  2697.       blob_component->elem.Type = BLOB_SPHERE;
  2698.  
  2699.       blob_component->elem.c[2] = Parse_Float();
  2700.  
  2701.       Parse_Comma();
  2702.  
  2703.       blob_component->elem.rad2 = Parse_Float();
  2704.  
  2705.       Parse_Comma();
  2706.  
  2707.       blob_component->elem.rad2 = Sqr(blob_component->elem.rad2);
  2708.  
  2709.       Parse_Vector(blob_component->elem.O);
  2710.  
  2711.       /* Next component. */
  2712.  
  2713.       blob_component->next = blob_components;
  2714.  
  2715.       blob_components = blob_component;
  2716.  
  2717.       npoints++;
  2718.     END_CASE
  2719.  
  2720.     /*************************************************************************
  2721.      * Read sperical component (new syntax).
  2722.      *************************************************************************/
  2723.  
  2724.     CASE (SPHERE_TOKEN)
  2725.       blob_component = Create_Blob_List_Element();
  2726.  
  2727.       blob_component->elem.Type = BLOB_SPHERE;
  2728.  
  2729.       Parse_Begin();
  2730.  
  2731.       Parse_Vector(blob_component->elem.O);
  2732.  
  2733.       Parse_Comma();
  2734.  
  2735.       blob_component->elem.rad2 = Parse_Float();
  2736.  
  2737.       blob_component->elem.rad2 = Sqr(blob_component->elem.rad2);
  2738.  
  2739.       Parse_Comma();
  2740.  
  2741.       ALLOW(STRENGTH_TOKEN)
  2742.  
  2743.       blob_component->elem.c[2] = Parse_Float();
  2744.  
  2745.       Parse_Blob_Element_Mods(&blob_component->elem);
  2746.  
  2747.       /* Next component. */
  2748.  
  2749.       blob_component->next = blob_components;
  2750.  
  2751.       blob_components = blob_component;
  2752.  
  2753.       npoints++;
  2754.     END_CASE
  2755.  
  2756.     /*************************************************************************
  2757.      * Read cylindrical component.
  2758.      *************************************************************************/
  2759.  
  2760.     CASE (CYLINDER_TOKEN)
  2761.       blob_component = Create_Blob_List_Element();
  2762.  
  2763.       blob_component->elem.Type = BLOB_CYLINDER;
  2764.  
  2765.       blob_component->elem.Trans = Create_Transform();
  2766.  
  2767.       Parse_Begin();
  2768.  
  2769.       Parse_Vector(Base);
  2770.  
  2771.       Parse_Comma();
  2772.  
  2773.       Parse_Vector(Apex);
  2774.  
  2775.       Parse_Comma();
  2776.  
  2777.       blob_component->elem.rad2 = Parse_Float();
  2778.  
  2779.       blob_component->elem.rad2 = Sqr(blob_component->elem.rad2);
  2780.  
  2781.       Parse_Comma();
  2782.  
  2783.       ALLOW(STRENGTH_TOKEN)
  2784.  
  2785.       blob_component->elem.c[2] = Parse_Float();
  2786.  
  2787.       /* Calculate cylinder's coordinate system. */
  2788.  
  2789.       VSub(Axis, Apex, Base);
  2790.  
  2791.       VLength(blob_component->elem.len, Axis);
  2792.  
  2793.       if (blob_component->elem.len < EPSILON)
  2794.       {
  2795.         Error("Degenerate cylindrical component in blob.\n");
  2796.       }
  2797.  
  2798.       VInverseScaleEq(Axis, blob_component->elem.len);
  2799.  
  2800.       Compute_Coordinate_Transform(blob_component->elem.Trans, Base, Axis, 1.0, 1.0);
  2801.  
  2802.       Parse_Blob_Element_Mods(&blob_component->elem);
  2803.  
  2804.       /* Next component. */
  2805.  
  2806.       blob_component->next = blob_components;
  2807.  
  2808.       blob_components = blob_component;
  2809.  
  2810.       npoints++;
  2811.     END_CASE
  2812.  
  2813.  
  2814.     OTHERWISE
  2815.       UNGET
  2816.       EXIT
  2817.     END_CASE
  2818.   END_EXPECT
  2819.  
  2820.   Create_Blob_Element_Texture_List(Object, blob_components, npoints);
  2821.  
  2822.   Parse_Object_Mods((OBJECT *)Object);
  2823.  
  2824.   /* The blob's texture has to be processed before Make_Blob() is called. */
  2825.  
  2826.   Post_Textures(Object->Texture);
  2827.   
  2828.   /* Finally, process the information */
  2829.  
  2830.   Make_Blob(Object, threshold, blob_components, npoints);
  2831.  
  2832.   return((OBJECT *)Object);
  2833. }
  2834.  
  2835.  
  2836.  
  2837. /*****************************************************************************
  2838. *
  2839. * FUNCTION
  2840. *
  2841. *   Parse_Julia_Fractal
  2842. *
  2843. * INPUT None
  2844. *   
  2845. * OUTPUT Fractal Objecstructure filledt
  2846. *   
  2847. * RETURNS 
  2848. *
  2849. *   OBJECT * -
  2850. *   
  2851. * AUTHOR
  2852. *
  2853. *   Pascal Massimino
  2854. *   
  2855. * DESCRIPTION
  2856. *
  2857. *   -
  2858. *
  2859. * CHANGES
  2860. *
  2861. *   Dec 1994 : Adopted to version 3.0. [DB]
  2862. *   Sept 1995 : Total rewrite for new syntax [TW]
  2863. *
  2864. ******************************************************************************/
  2865.  
  2866. static OBJECT *Parse_Julia_Fractal ()
  2867. {
  2868.   FRACTAL *Object;
  2869.   DBL P;
  2870.  
  2871.   Parse_Begin();
  2872.  
  2873.   if ( (Object = (FRACTAL *)Parse_Object_Id()) != NULL)
  2874.     return((OBJECT *)Object);
  2875.  
  2876.   Object = Create_Fractal();
  2877.  
  2878.   Parse_Vector4D(Object->Julia_Parm); 
  2879.  
  2880.   EXPECT
  2881.  
  2882.     CASE(MAX_ITERATION_TOKEN)
  2883.       Object->n = (int)floor(Parse_Float()); 
  2884.  
  2885.       if (Object->n <= 0)
  2886.       {
  2887.         Object->n = 1;
  2888.       }
  2889.     END_CASE
  2890.  
  2891.     CASE(SLICE_TOKEN)
  2892.       Parse_Vector4D(Object->Slice);
  2893.       Parse_Comma();
  2894.       Object->SliceDist = Parse_Float(); 
  2895.  
  2896.       /* normalize slice vector */
  2897.       V4D_Dot(P,Object->Slice, Object->Slice);
  2898.       if (fabs(P) < EPSILON)
  2899.       {
  2900.         Error("Slice vector is zero.\n");
  2901.       }
  2902.       if (fabs(Object->Slice[T]) < EPSILON)
  2903.       {
  2904.         Error("Slice t component is zero.\n");
  2905.       }
  2906.       P = sqrt(P);
  2907.       V4D_InverseScaleEq(Object->Slice, P);      
  2908.  
  2909.     END_CASE
  2910.  
  2911.     CASE(PRECISION_TOKEN)
  2912.       P = Parse_Float(); 
  2913.       if ( P < 1.0 )
  2914.       {
  2915.         P = 1.0;
  2916.       }
  2917.       Object->Precision = 1.0 / P;
  2918.     END_CASE
  2919.       
  2920.     CASE(FLOAT_FUNCT_TOKEN)
  2921.       switch(Token.Function_Id)
  2922.       {
  2923.         case EXP_TOKEN:
  2924.           Object->Sub_Type = EXP_STYPE;
  2925.           break;
  2926.         case LOG_TOKEN:
  2927.           Object->Sub_Type = LOG_STYPE;
  2928.           break;
  2929.         case SIN_TOKEN:
  2930.           Object->Sub_Type = SIN_STYPE;
  2931.           break;
  2932.         case ASIN_TOKEN:
  2933.           Object->Sub_Type = ASIN_STYPE;
  2934.           break;
  2935.         case COS_TOKEN:
  2936.           Object->Sub_Type = COS_STYPE;
  2937.           break;
  2938.         case ACOS_TOKEN:
  2939.           Object->Sub_Type = ACOS_STYPE;
  2940.           break;
  2941. #ifdef CubeSqrHatPatch
  2942.         case SQR_TOKEN:/*Chris Huff*/
  2943.           Object->Sub_Type = SQR_STYPE;
  2944.           break;
  2945.         case CUBE_TOKEN:/*Chris Huff*/
  2946.           Object->Sub_Type = CUBE_STYPE;
  2947.           break;
  2948. #endif
  2949.         default: Parse_Error_Str ("fractal keyword");
  2950.       }    
  2951.     END_CASE
  2952.  
  2953.     /* if any of the next become supported by the expression parser,
  2954.      * then their handling would need to move above to the FUNC_TOKEN
  2955.      * case above.
  2956.      */
  2957.     CASE(ATAN_TOKEN)
  2958.       Object->Sub_Type = ATAN_STYPE;
  2959.     END_CASE
  2960.  
  2961.     CASE(COSH_TOKEN)
  2962.       Object->Sub_Type = COSH_STYPE;
  2963.     END_CASE
  2964.  
  2965.     CASE(SINH_TOKEN)
  2966.       Object->Sub_Type = SINH_STYPE;
  2967.     END_CASE
  2968.  
  2969.     CASE(TANH_TOKEN)
  2970.       Object->Sub_Type = TANH_STYPE;
  2971.     END_CASE
  2972.  
  2973.     CASE(ATANH_TOKEN)
  2974.       Object->Sub_Type = ATANH_STYPE;
  2975.     END_CASE
  2976.  
  2977.     CASE(ACOSH_TOKEN)
  2978.       Object->Sub_Type = ACOSH_STYPE;
  2979.     END_CASE
  2980.  
  2981.     CASE(ASINH_TOKEN)
  2982.       Object->Sub_Type = ASINH_STYPE;
  2983.     END_CASE
  2984.  
  2985. #ifndef CubeSqrHatPatch
  2986.     CASE(SQR_TOKEN)
  2987.       Object->Sub_Type = SQR_STYPE;
  2988.     END_CASE
  2989. #endif
  2990.     CASE(PWR_TOKEN)
  2991.       Object->Sub_Type = PWR_STYPE;
  2992.       Parse_Float_Param2(&Object->exponent.x,&Object->exponent.y);
  2993.     END_CASE
  2994.  
  2995. #ifndef CubeSqrHatPatch
  2996.     CASE(CUBE_TOKEN)
  2997.       Object->Sub_Type = CUBE_STYPE;
  2998.     END_CASE
  2999. #endif
  3000.     CASE(RECIPROCAL_TOKEN)
  3001.       Object->Sub_Type = RECIPROCAL_STYPE;
  3002.     END_CASE
  3003.  
  3004.     CASE(HYPERCOMPLEX_TOKEN)
  3005.       Object->Algebra = HYPERCOMPLEX_TYPE;
  3006.     END_CASE
  3007.  
  3008.     CASE(QUATERNION_TOKEN)
  3009.       Object->Algebra = QUATERNION_TYPE;
  3010.     END_CASE
  3011.  
  3012.     OTHERWISE
  3013.       UNGET
  3014.       EXIT
  3015.     END_CASE
  3016.  
  3017.   END_EXPECT
  3018.  
  3019.   Parse_Object_Mods((OBJECT *)Object);
  3020.  
  3021.   SetUp_Fractal(Object);
  3022.  
  3023.   return((OBJECT *)Object);
  3024. }
  3025.  
  3026.  
  3027.  
  3028.  
  3029. /*****************************************************************************
  3030. *
  3031. * FUNCTION
  3032. *
  3033. *   Parse_Polygon
  3034. *
  3035. * INPUT
  3036. *
  3037. * OUTPUT
  3038. *
  3039. * RETURNS
  3040. *
  3041. *   OBJECT * -
  3042. *
  3043. * AUTHOR
  3044. *
  3045. *   Dieter Bayer
  3046. *   
  3047. * DESCRIPTION
  3048. *
  3049. *   -
  3050. *
  3051. * CHANGES
  3052. *
  3053. *   May 1994 : Creation.
  3054. *
  3055. *   Oct 1994 : Modified to use new polygon data structure. [DB]
  3056. *
  3057. ******************************************************************************/
  3058.  
  3059. static OBJECT *Parse_Polygon()
  3060. {
  3061.   int i, closed = FALSE;
  3062.   int Number;
  3063.   POLYGON *Object;
  3064.   VECTOR *Points, P;
  3065.  
  3066.   Parse_Begin();
  3067.  
  3068.   if ((Object = (POLYGON *)Parse_Object_Id()) != NULL)
  3069.   {
  3070.     return((OBJECT *) Object);
  3071.   }
  3072.  
  3073.   Object = Create_Polygon();
  3074.  
  3075.   Number = (int)Parse_Float();
  3076.  
  3077.   if (Number < 3)
  3078.   {
  3079.     Error("Polygon needs at least three points.");
  3080.   }
  3081.  
  3082.   Points = (VECTOR *)POV_MALLOC((Number+1)*sizeof(VECTOR), "temporary polygon points");
  3083.  
  3084.   for (i = 0; i < Number; i++)
  3085.   {
  3086.     Parse_Comma();
  3087.  
  3088.     Parse_Vector(Points[i]);
  3089.   }
  3090.  
  3091.   /* Check for closed polygons. */
  3092.  
  3093.   Assign_Vector(P, Points[0]);
  3094.  
  3095.   for (i = 1; i < Number; i++)
  3096.   {
  3097.     closed = FALSE;
  3098.  
  3099.     if ((fabs(P[X] - Points[i][X]) < EPSILON) &&
  3100.         (fabs(P[Y] - Points[i][Y]) < EPSILON) &&
  3101.         (fabs(P[Z] - Points[i][Z]) < EPSILON))
  3102.     {
  3103.       i++;
  3104.  
  3105.       if (i < Number)
  3106.       {
  3107.         Assign_Vector(P, Points[i]);
  3108.       }
  3109.  
  3110.       closed = TRUE;
  3111.     }
  3112.   }
  3113.  
  3114.   if (!closed)
  3115.   {
  3116.     Warn(0, "Polygon not closed. Closing it.");
  3117.  
  3118.     Assign_Vector(Points[Number], P);
  3119.  
  3120.     Number++;
  3121.   }
  3122.  
  3123.   Compute_Polygon(Object, Number, Points);
  3124.  
  3125.   POV_FREE (Points);
  3126.  
  3127.   Parse_Object_Mods ((OBJECT *)Object);
  3128.  
  3129.   return((OBJECT *) Object);
  3130. }
  3131.  
  3132.  
  3133.  
  3134. /*****************************************************************************
  3135. *
  3136. * FUNCTION
  3137. *
  3138. *   Parse_Prism
  3139. *
  3140. * INPUT
  3141. *
  3142. * OUTPUT
  3143. *
  3144. * RETURNS
  3145. *
  3146. *   OBJECT * -
  3147. *
  3148. * AUTHOR
  3149. *
  3150. *   Dieter Bayer
  3151. *
  3152. * DESCRIPTION
  3153. *
  3154. *   -
  3155. *
  3156. * CHANGES
  3157. *
  3158. *   May 1994 : Creation.
  3159. *
  3160. ******************************************************************************/
  3161.  
  3162. static OBJECT *Parse_Prism()
  3163. {
  3164.   int i, closed = FALSE;
  3165.   DBL h;
  3166.  
  3167.   PRISM *Object;
  3168.   UV_VECT *Points, P;
  3169.  
  3170.   Parse_Begin();
  3171.  
  3172.   if ((Object = (PRISM *)Parse_Object_Id()) != NULL)
  3173.   {
  3174.     return((OBJECT *) Object);
  3175.   }
  3176.  
  3177.   Object = Create_Prism();
  3178.  
  3179.   /* 
  3180.    * Determine kind of spline used (linear, quadratic, cubic) 
  3181.    * and type of sweeping (linear, conic).
  3182.    */
  3183.  
  3184.   EXPECT
  3185.     CASE(LINEAR_SPLINE_TOKEN)
  3186.       Object->Spline_Type = LINEAR_SPLINE;
  3187.     END_CASE
  3188.  
  3189.     CASE(QUADRATIC_SPLINE_TOKEN)
  3190.       Object->Spline_Type = QUADRATIC_SPLINE;
  3191.     END_CASE
  3192.  
  3193.     CASE(CUBIC_SPLINE_TOKEN)
  3194.       Object->Spline_Type = CUBIC_SPLINE;
  3195.     END_CASE
  3196.  
  3197.     CASE(BEZIER_SPLINE_TOKEN)
  3198.       Object->Spline_Type = BEZIER_SPLINE;
  3199.     END_CASE
  3200.  
  3201.     CASE(LINEAR_SWEEP_TOKEN)
  3202.       Object->Sweep_Type = LINEAR_SWEEP;
  3203.     END_CASE
  3204.  
  3205.     CASE(CONIC_SWEEP_TOKEN)
  3206.       Object->Sweep_Type = CONIC_SWEEP;
  3207.     END_CASE
  3208.  
  3209.     OTHERWISE
  3210.       UNGET
  3211.       EXIT
  3212.     END_CASE
  3213.   END_EXPECT
  3214.  
  3215.   /* Read prism heights. */
  3216.  
  3217.   Object->Height1 = Parse_Float(); Parse_Comma();
  3218.   Object->Height2 = Parse_Float(); Parse_Comma();
  3219.  
  3220.   if (Object->Height1 > Object->Height2)
  3221.   {
  3222.     h = Object->Height1;
  3223.     Object->Height1 = Object->Height2;
  3224.     Object->Height2 = h;
  3225.   }
  3226.  
  3227.   /* Get number of points = number of segments. */
  3228.  
  3229.   Object->Number = (int)Parse_Float();
  3230.  
  3231.   switch (Object->Spline_Type)
  3232.   {
  3233.     case LINEAR_SPLINE :
  3234.  
  3235.       if (Object->Number < 3)
  3236.       {
  3237.         Error("Prism with linear splines must have at least three points.");
  3238.       }
  3239.  
  3240.       break;
  3241.  
  3242.     case QUADRATIC_SPLINE :
  3243.  
  3244.       if (Object->Number < 5)
  3245.       {
  3246.         Error("Prism with quadratic splines must have at least five points.");
  3247.       }
  3248.  
  3249.       break;
  3250.  
  3251.     case CUBIC_SPLINE :
  3252.  
  3253.       if (Object->Number < 6)
  3254.       {
  3255.         Error("Prism with cubic splines must have at least six points.");
  3256.       }
  3257.  
  3258.       break;
  3259.  
  3260.     case BEZIER_SPLINE :
  3261.  
  3262.       if ((Object->Number & 3) != 0)
  3263.       {
  3264.         Error("Prism with Bezier splines must have four points per segment.");
  3265.       }
  3266.  
  3267.       break;
  3268.   }
  3269.  
  3270.   /* Allocate Object->Number points for the prism. */
  3271.  
  3272.   Points = (UV_VECT *)POV_MALLOC((Object->Number+1) * sizeof(UV_VECT), "temporary prism points");
  3273.  
  3274.   /* Read points (x, y : coordinate of 2d point; z : not used). */
  3275.  
  3276.   for (i = 0; i < Object->Number; i++)
  3277.   {
  3278.     Parse_Comma();
  3279.  
  3280.     Parse_UV_Vect(Points[i]);
  3281.   }
  3282.  
  3283.   /* Closed or not closed that's the question. */
  3284.  
  3285.   EXPECT
  3286.     CASE(OPEN_TOKEN)
  3287.       Clear_Flag(Object, CLOSED_FLAG);
  3288.       EXIT
  3289.     END_CASE
  3290.  
  3291.     OTHERWISE
  3292.       UNGET
  3293.       EXIT
  3294.     END_CASE
  3295.   END_EXPECT
  3296.  
  3297.   /* Check for closed prism. */
  3298.  
  3299.   if ((Object->Spline_Type == LINEAR_SPLINE) ||
  3300.       (Object->Spline_Type == QUADRATIC_SPLINE) ||
  3301.       (Object->Spline_Type == CUBIC_SPLINE))
  3302.   {
  3303.     switch (Object->Spline_Type)
  3304.     {
  3305.       case LINEAR_SPLINE :
  3306.  
  3307.         i = 1;
  3308.  
  3309.         Assign_UV_Vect(P, Points[0]);
  3310.  
  3311.         break;
  3312.  
  3313.       case QUADRATIC_SPLINE :
  3314.       case CUBIC_SPLINE :
  3315.  
  3316.         i = 2;
  3317.  
  3318.         Assign_UV_Vect(P, Points[1]);
  3319.  
  3320.         break;
  3321.     }
  3322.  
  3323.     for ( ; i < Object->Number; i++)
  3324.     {
  3325.       closed = FALSE;
  3326.  
  3327.       if ((fabs(P[X] - Points[i][X]) < EPSILON) &&
  3328.           (fabs(P[Y] - Points[i][Y]) < EPSILON))
  3329.       {
  3330.         switch (Object->Spline_Type)
  3331.         {
  3332.           case LINEAR_SPLINE :
  3333.  
  3334.             i++;
  3335.  
  3336.             if (i < Object->Number)
  3337.             {
  3338.               Assign_UV_Vect(P, Points[i]);
  3339.             }
  3340.  
  3341.             break;
  3342.  
  3343.           case QUADRATIC_SPLINE :
  3344.  
  3345.             i += 2;
  3346.  
  3347.             if (i < Object->Number)
  3348.             {
  3349.               Assign_UV_Vect(P, Points[i]);
  3350.             }
  3351.  
  3352.             break;
  3353.  
  3354.           case CUBIC_SPLINE :
  3355.  
  3356.             i += 3;
  3357.  
  3358.             if (i < Object->Number)
  3359.             {
  3360.               Assign_UV_Vect(P, Points[i]);
  3361.             }
  3362.  
  3363.             break;
  3364.         }
  3365.  
  3366.         closed = TRUE;
  3367.       }
  3368.     }
  3369.   }
  3370.   else
  3371.   {
  3372.     closed = TRUE;
  3373.  
  3374.     for (i = 0; i < Object->Number; i += 4)
  3375.     {
  3376.       if ((fabs(Points[i][X] - Points[(i-1+Object->Number) % Object->Number][X]) > EPSILON) ||
  3377.           (fabs(Points[i][Y] - Points[(i-1+Object->Number) % Object->Number][Y]) > EPSILON))
  3378.       {
  3379.         closed = FALSE;
  3380.  
  3381.         break;
  3382.       }
  3383.     }
  3384.   }
  3385.  
  3386.   if (!closed)
  3387.   {
  3388.     if (Object->Spline_Type == LINEAR_SPLINE)
  3389.     {
  3390.       Assign_UV_Vect(Points[Object->Number], P);
  3391.  
  3392.       Object->Number++;
  3393.  
  3394.       Warn(0, "Linear prism not closed. Closing it.");
  3395.     }
  3396.     else
  3397.     {
  3398.       Set_Flag(Object, DEGENERATE_FLAG);
  3399.  
  3400.       Warn(0, "Prism not closed. Ignoring it.");
  3401.     }
  3402.   }
  3403.  
  3404.   /* Compute spline segments. */
  3405.  
  3406.   Compute_Prism(Object, Points);
  3407.  
  3408.   /* Compute bounding box. */
  3409.  
  3410.   Compute_Prism_BBox(Object);
  3411.  
  3412.   /* Parse object's modifiers. */
  3413.  
  3414.   Parse_Object_Mods((OBJECT *)Object);
  3415.  
  3416.   /* Destroy temporary points. */
  3417.  
  3418.   POV_FREE (Points);
  3419.  
  3420.   return((OBJECT *) Object);
  3421. }
  3422.  
  3423.  
  3424.  
  3425. /*****************************************************************************
  3426. *
  3427. * FUNCTION
  3428. *
  3429. *   Parse_Sor
  3430. *
  3431. * INPUT
  3432. *   
  3433. * OUTPUT
  3434. *   
  3435. * RETURNS
  3436. *
  3437. *   OBJECT * -
  3438. *
  3439. * AUTHOR
  3440. *
  3441. *   Dieter Bayer
  3442. *   
  3443. * DESCRIPTION
  3444. *
  3445. *   Read a surface of revolution primitive.
  3446. *
  3447. * CHANGES
  3448. *
  3449. *   May 1994 : Creation.
  3450. *
  3451. ******************************************************************************/
  3452.  
  3453. static OBJECT *Parse_Sor()
  3454. {
  3455.   int i;
  3456.   SOR *Object;
  3457.   UV_VECT *Points;
  3458.  
  3459.   Parse_Begin();
  3460.  
  3461.   if ((Object = (SOR *)Parse_Object_Id()) != NULL)
  3462.   {
  3463.     return((OBJECT *)Object);
  3464.   }
  3465.  
  3466.   Object = Create_Sor();
  3467.  
  3468.   /* Get number of points. */
  3469.  
  3470.   Object->Number = (int)Parse_Float();
  3471.  
  3472.   if (Object->Number <4)
  3473.   {
  3474.     Error("Surface of revolution must have at least four points.");
  3475.   }
  3476.  
  3477.   /* Get temporary points describing the rotated curve. */
  3478.  
  3479.   Points = (UV_VECT *)POV_MALLOC(Object->Number*sizeof(UV_VECT), "temporary surface of revolution points");
  3480.  
  3481.   /* Read points (x : radius; y : height; z : not used). */
  3482.  
  3483.   for (i = 0; i < Object->Number; i++)
  3484.   {
  3485.     Parse_Comma();
  3486.  
  3487.     Parse_UV_Vect(Points[i]);
  3488.  
  3489.     if ((Points[i][X] < 0.0) ||
  3490.         ((i > 1 ) && (i < Object->Number - 1) && (Points[i][Y] <= Points[i-1][Y])))
  3491.     {
  3492.       Error("Incorrect point in surface of revolution.");
  3493.     }
  3494.   }
  3495.  
  3496.   /* Closed or not closed that's the question. */
  3497.  
  3498.   EXPECT
  3499.     CASE(OPEN_TOKEN)
  3500.       Clear_Flag(Object, CLOSED_FLAG);
  3501.       EXIT
  3502.     END_CASE
  3503.  
  3504.     OTHERWISE
  3505.       UNGET
  3506.       EXIT
  3507.     END_CASE
  3508.   END_EXPECT
  3509.  
  3510.   /* There are Number-3 segments! */
  3511.  
  3512.   Object->Number -= 3;
  3513.  
  3514.   /* Compute spline segments. */
  3515.  
  3516.   Compute_Sor(Object, Points);
  3517.  
  3518.   /* Compute bounding box. */
  3519.  
  3520.   Compute_Sor_BBox(Object);
  3521.  
  3522.   /* Parse object's modifiers. */
  3523.  
  3524.   Parse_Object_Mods((OBJECT *)Object);
  3525.  
  3526.   /* Destroy temporary points. */
  3527.  
  3528.   POV_FREE (Points);
  3529.  
  3530.   return ((OBJECT *) Object);
  3531. }
  3532.  
  3533.  
  3534.  
  3535. /*****************************************************************************
  3536. *
  3537. * FUNCTION
  3538. *
  3539. *   Parse_Lathe
  3540. *
  3541. * INPUT
  3542. *   
  3543. * OUTPUT
  3544. *   
  3545. * RETURNS
  3546. *
  3547. *   OBJECT * -
  3548. *   
  3549. * AUTHOR
  3550. *
  3551. *   Dieter Bayer
  3552. *   
  3553. * DESCRIPTION
  3554. *
  3555. *   Read a lathe primitive.
  3556. *
  3557. * CHANGES
  3558. *
  3559. *   Jun 1994 : Creation.
  3560. *
  3561. ******************************************************************************/
  3562.  
  3563. static OBJECT *Parse_Lathe()
  3564. {
  3565.   int i;
  3566.   LATHE *Object;
  3567.   UV_VECT *Points;
  3568.  
  3569.   Parse_Begin();
  3570.  
  3571.   if ((Object = (LATHE *)Parse_Object_Id()) != NULL)
  3572.   {
  3573.     return((OBJECT *)Object);
  3574.   }
  3575.  
  3576.   Object = Create_Lathe();
  3577.  
  3578.   /* Determine kind of spline used and aspect ratio. */
  3579.  
  3580.   EXPECT
  3581.     CASE(LINEAR_SPLINE_TOKEN)
  3582.       Object->Spline_Type = LINEAR_SPLINE;
  3583.     END_CASE
  3584.  
  3585.     CASE(QUADRATIC_SPLINE_TOKEN)
  3586.       Object->Spline_Type = QUADRATIC_SPLINE;
  3587.     END_CASE
  3588.  
  3589.     CASE(CUBIC_SPLINE_TOKEN)
  3590.       Object->Spline_Type = CUBIC_SPLINE;
  3591.     END_CASE
  3592.  
  3593.     CASE(BEZIER_SPLINE_TOKEN)
  3594.       Object->Spline_Type = BEZIER_SPLINE;
  3595.     END_CASE
  3596.  
  3597.     OTHERWISE
  3598.       UNGET
  3599.       EXIT
  3600.     END_CASE
  3601.   END_EXPECT
  3602.  
  3603.   /* Get number of points. */
  3604.  
  3605.   Object->Number = (int)Parse_Float();
  3606.  
  3607.   switch (Object->Spline_Type)
  3608.   {
  3609.     case LINEAR_SPLINE :
  3610.  
  3611.       if (Object->Number < 2)
  3612.       {
  3613.         Error("Lathe with linear splines must have at least two points.");
  3614.       }
  3615.  
  3616.       break;
  3617.  
  3618.     case QUADRATIC_SPLINE :
  3619.  
  3620.       if (Object->Number < 3)
  3621.       {
  3622.         Error("Lathe with quadratic splines must have at least three points.");
  3623.       }
  3624.  
  3625.       break;
  3626.  
  3627.     case CUBIC_SPLINE :
  3628.  
  3629.       if (Object->Number < 4)
  3630.       {
  3631.         Error("Prism with cubic splines must have at least four points.");
  3632.       }
  3633.  
  3634.       break;
  3635.  
  3636.     case BEZIER_SPLINE :
  3637.  
  3638.       if ((Object->Number & 3) != 0)
  3639.       {
  3640.         Error("Lathe with Bezier splines must have four points per segment.");
  3641.       }
  3642.  
  3643.       break;
  3644.   }
  3645.  
  3646.   /* Get temporary points describing the rotated curve. */
  3647.  
  3648.   Points = (UV_VECT *)POV_MALLOC(Object->Number*sizeof(UV_VECT), "temporary lathe points");
  3649.  
  3650.   /* Read points (x : radius; y : height; z : not used). */
  3651.  
  3652.   for (i = 0; i < Object->Number; i++)
  3653.   {
  3654.     Parse_Comma();
  3655.  
  3656.     Parse_UV_Vect(Points[i]);
  3657.  
  3658.     if ((i > 0) && (i < Object->Number - 1) && (Points[i][X] < 0.0))
  3659.     {
  3660.       Error("Incorrect point in lathe.");
  3661.     }
  3662.   }
  3663.  
  3664.   /* Compute spline segments. */
  3665.  
  3666.   Compute_Lathe(Object, Points);
  3667.  
  3668.   /* Compute bounding box. */
  3669.  
  3670.   Compute_Lathe_BBox(Object);
  3671.  
  3672.   /* Parse object's modifiers. */
  3673.  
  3674.   Parse_Object_Mods((OBJECT *)Object);
  3675.  
  3676.   /* Destroy temporary points. */
  3677.  
  3678.   POV_FREE (Points);
  3679.  
  3680.   return((OBJECT *) Object);
  3681. }
  3682.  
  3683.  
  3684.  
  3685. /*****************************************************************************
  3686. *
  3687. * FUNCTION
  3688. *
  3689. *   Parse_Superellipsoid
  3690. *
  3691. * INPUT
  3692. *   
  3693. * OUTPUT
  3694. *   
  3695. * RETURNS
  3696. *
  3697. *   OBJECT * -
  3698. *   
  3699. * AUTHOR
  3700. *
  3701. *   Dieter Bayer
  3702. *   
  3703. * DESCRIPTION
  3704. *
  3705. *   Read a superellipsoid primitive.
  3706. *
  3707. * CHANGES
  3708. *
  3709. *   Oct 1994 : Creation.
  3710. *
  3711. ******************************************************************************/
  3712.  
  3713. static OBJECT *Parse_Superellipsoid()
  3714. {
  3715.   UV_VECT V1;
  3716.   SUPERELLIPSOID *Object;
  3717.  
  3718.   Parse_Begin();
  3719.  
  3720.   if ((Object = (SUPERELLIPSOID *)Parse_Object_Id()) != NULL)
  3721.   {
  3722.     return((OBJECT *)Object);
  3723.   }
  3724.  
  3725.   Object = Create_Superellipsoid();
  3726.  
  3727.   Parse_UV_Vect(V1);
  3728.  
  3729.   /* The x component is e, the y component is n. */
  3730.  
  3731.   Object->Power[X] = 2.0  / V1[X];
  3732.   Object->Power[Y] = V1[X] / V1[Y];
  3733.   Object->Power[Z] = 2.0  / V1[Y];
  3734.  
  3735.   /* Compute bounding box. */
  3736.  
  3737.   Compute_Superellipsoid_BBox(Object);
  3738.  
  3739.   /* Parse object's modifiers. */
  3740.  
  3741.   Parse_Object_Mods((OBJECT *)Object);
  3742.  
  3743.   return((OBJECT *) Object);
  3744. }
  3745.  
  3746.  
  3747. /*****************************************************************************
  3748. *
  3749. * FUNCTION
  3750. *
  3751. *   Parse_Torus
  3752. *
  3753. * INPUT
  3754. *   
  3755. * OUTPUT
  3756. *   
  3757. * RETURNS
  3758. *
  3759. *   OBJECT
  3760. *
  3761. * AUTHOR
  3762. *
  3763. *   Dieter Bayer
  3764. *   
  3765. * DESCRIPTION
  3766. *
  3767. *   -
  3768. *
  3769. * CHANGES
  3770. *
  3771. *   Jul 1994 : Creation.
  3772. *
  3773. ******************************************************************************/
  3774.  
  3775. static OBJECT *Parse_Torus()
  3776. {
  3777.   TORUS *Object;
  3778.  
  3779.   Parse_Begin();
  3780.  
  3781.   if ((Object = (TORUS *)Parse_Object_Id()) != NULL)
  3782.   {
  3783.     return((OBJECT *)Object);
  3784.   }
  3785.  
  3786.   Object = Create_Torus();
  3787.  
  3788.   /* Read in the two radii. */
  3789.  
  3790.   Object->R = Parse_Float(); /* Big radius */
  3791.  
  3792.   Parse_Comma();
  3793.  
  3794.   Object->r = Parse_Float(); /* Little radius */
  3795.  
  3796.   Compute_Torus_BBox(Object);
  3797.  
  3798.   Parse_Object_Mods ((OBJECT *)Object);
  3799.  
  3800.   return ((OBJECT *) Object);
  3801. }
  3802.  
  3803.  
  3804.  
  3805. /*****************************************************************************
  3806. *
  3807. * FUNCTION
  3808. *
  3809. *   Parse_Mesh_Texture
  3810. *
  3811. * INPUT
  3812. *   
  3813. * OUTPUT
  3814. *   
  3815. * RETURNS
  3816. *
  3817. *   OBJECT
  3818. *   
  3819. * AUTHOR
  3820. *
  3821. *   Dieter Bayer
  3822. *   
  3823. * DESCRIPTION
  3824. *
  3825. *   Read an individual triangle mesh texture.
  3826. *
  3827. * CHANGES
  3828. *
  3829. *   Feb 1995 : Creation.
  3830. *
  3831. ******************************************************************************/
  3832.  
  3833. #ifdef ColorTrianglePatch
  3834. static TEXTURE *Parse_Mesh_Texture (TEXTURE **t2, TEXTURE **t3)
  3835. #else
  3836. static TEXTURE *Parse_Mesh_Texture ()
  3837. #endif
  3838. {
  3839.   TEXTURE *Texture;
  3840.  
  3841.   Texture = NULL;
  3842.  
  3843.   EXPECT
  3844.     CASE(TEXTURE_TOKEN)
  3845.       Parse_Begin();
  3846.  
  3847.       GET(TEXTURE_ID_TOKEN);
  3848.  
  3849.       Texture = (TEXTURE *)Token.Data;
  3850.  
  3851.       Parse_End();
  3852.     END_CASE
  3853.  
  3854. #ifdef ColorTrianglePatch
  3855.     /* NK */
  3856.     CASE(TEXTURE_LIST_TOKEN)
  3857. #ifdef UnofficialBlocking
  3858.       parseUnofficialFeature(40);
  3859. #endif
  3860.       Parse_Begin();
  3861.       GET(TEXTURE_ID_TOKEN);
  3862.       Texture = (TEXTURE *)Token.Data;
  3863.       GET(TEXTURE_ID_TOKEN);
  3864.       *t2 = (TEXTURE *)Token.Data;
  3865.       GET(TEXTURE_ID_TOKEN);
  3866.       *t3 = (TEXTURE *)Token.Data;
  3867.       Parse_End();
  3868.       EXIT
  3869.     END_CASE
  3870. #endif
  3871.  
  3872.     OTHERWISE
  3873.       UNGET
  3874.       EXIT
  3875.     END_CASE
  3876.   END_EXPECT
  3877.  
  3878.   return(Texture);
  3879. }
  3880.  
  3881.  
  3882.  
  3883. /*****************************************************************************
  3884. *
  3885. * FUNCTION
  3886. *
  3887. *   Parse_Three_UVCoords
  3888. *
  3889. * INPUT
  3890. *
  3891. * OUTPUT
  3892. *
  3893. *   UV1..UV3 are the uv
  3894. *
  3895. * RETURNS
  3896. *
  3897. *   1 for successful read, 0 if UV_VECTORS_TOKEN not found
  3898. *
  3899. * AUTHOR
  3900. *
  3901. *   Nathan Kopp
  3902. *
  3903. * DESCRIPTION
  3904. *
  3905. *   Look for UV_VECTORS_TOKEN and then read in three UV coordinates
  3906. *
  3907. ******************************************************************************/
  3908. int Parse_Three_UVCoords(UV_VECT UV1, UV_VECT UV2, UV_VECT UV3)
  3909. {
  3910.   int Return_Value;
  3911.  
  3912.   EXPECT
  3913.     CASE(UV_VECTORS_TOKEN)
  3914. #ifdef UnofficialBlocking
  3915.       parseUnofficialFeature(30);
  3916. #endif
  3917.       Parse_UV_Vect(UV1);  Parse_Comma();
  3918.       Parse_UV_Vect(UV2);  Parse_Comma();
  3919.       Parse_UV_Vect(UV3);
  3920.  
  3921.       Return_Value = 1;
  3922.       EXIT
  3923.     END_CASE
  3924.  
  3925.     OTHERWISE
  3926.       Return_Value = 0;
  3927.       UNGET
  3928.       EXIT
  3929.     END_CASE
  3930.  
  3931.   END_EXPECT
  3932.  
  3933.   return(Return_Value);
  3934. }
  3935.  
  3936. /*****************************************************************************
  3937. *
  3938. * FUNCTION
  3939. *
  3940. *   Parse_Mesh
  3941. *
  3942. * INPUT
  3943. *   
  3944. * OUTPUT
  3945. *   
  3946. * RETURNS
  3947. *
  3948. *   OBJECT
  3949. *   
  3950. * AUTHOR
  3951. *
  3952. *   Dieter Bayer
  3953. *   
  3954. * DESCRIPTION
  3955. *
  3956. *   Read a triangle mesh.
  3957. *
  3958. * CHANGES
  3959. *
  3960. *   Feb 1995 : Creation.
  3961. *
  3962. ******************************************************************************/
  3963.  
  3964. static OBJECT *Parse_Mesh()
  3965. {
  3966.   /* NK 1998 - added all sorts of uv variables*/
  3967.   int i;
  3968.   int number_of_normals, number_of_textures, number_of_triangles, number_of_vertices, number_of_uvcoords;
  3969.   int max_normals, max_textures, max_triangles, max_vertices, max_uvcoords;
  3970.   DBL l1, l2, l3;
  3971.   VECTOR D1, D2, P1, P2, P3, N1, N2, N3, N;
  3972.   UV_VECT UV1, UV2, UV3;
  3973.   SNGL_VECT *Normals, *Vertices;
  3974.   TEXTURE **Textures;
  3975.   UV_VECT *UVCoords;
  3976.   MESH *Object;
  3977.   MESH_TRIANGLE *Triangles;
  3978.   int fully_textured=TRUE;
  3979.   /* NK 1998 */
  3980.   VECTOR Inside_Vect;
  3981. #ifdef ColorTrianglePatch
  3982.   TEXTURE *t2, *t3;
  3983. #endif
  3984.  
  3985.   Make_Vector(Inside_Vect, 0, 0, 0);
  3986.   /* NK ---- */
  3987.  
  3988.   Parse_Begin();
  3989.  
  3990.   if ((Object = (MESH *)Parse_Object_Id()) != NULL)
  3991.   {
  3992.     return((OBJECT *)Object);
  3993.   }
  3994.  
  3995.   /* Create object. */
  3996.  
  3997.   Object = Create_Mesh();
  3998.  
  3999.   /* Allocate temporary normals, textures, triangles and vertices. */
  4000.  
  4001.   max_normals = 256;
  4002.  
  4003.   max_vertices = 256;
  4004.  
  4005.   max_textures = 16;
  4006.  
  4007.   max_triangles = 256;
  4008.  
  4009.   Normals = (SNGL_VECT *)POV_MALLOC(max_normals*sizeof(SNGL_VECT), "temporary triangle mesh data");
  4010.  
  4011.   Textures = (TEXTURE **)POV_MALLOC(max_textures*sizeof(TEXTURE *), "temporary triangle mesh data");
  4012.  
  4013.   Triangles = (MESH_TRIANGLE *)POV_MALLOC(max_triangles*sizeof(MESH_TRIANGLE), "temporary triangle mesh data");
  4014.  
  4015.   Vertices = (SNGL_VECT *)POV_MALLOC(max_vertices*sizeof(SNGL_VECT), "temporary triangle mesh data");
  4016.  
  4017.   /* Read raw triangle file. */
  4018.  
  4019.   number_of_normals = 0;
  4020.  
  4021.   number_of_textures = 0;
  4022.  
  4023.   number_of_triangles = 0;
  4024.  
  4025.   number_of_vertices = 0;
  4026.  
  4027.   /* NK 1998 */
  4028.   max_uvcoords = 256;
  4029.   UVCoords = (UV_VECT *)POV_MALLOC(max_uvcoords*sizeof(UV_VECT), "temporary triangle mesh data");
  4030.   number_of_uvcoords = 0;
  4031.   /* NK ---- */
  4032.  
  4033.   /* Create hash tables. */
  4034.  
  4035.   Create_Mesh_Hash_Tables();
  4036.  
  4037.   EXPECT
  4038.     CASE(TRIANGLE_TOKEN)
  4039.       Parse_Begin();
  4040.  
  4041.       Parse_Vector(P1);  Parse_Comma();
  4042.       Parse_Vector(P2);  Parse_Comma();
  4043.       Parse_Vector(P3);
  4044.  
  4045.       if (!Mesh_Degenerate(P1, P2, P3))
  4046.       {
  4047.         if (number_of_triangles >= max_triangles)
  4048.         {
  4049.           if (max_triangles >= INT_MAX/2)
  4050.           {
  4051.             Error("Too many triangles in triangle mesh.\n");
  4052.           }
  4053.  
  4054.           max_triangles *= 2;
  4055.  
  4056.           Triangles = (MESH_TRIANGLE *)POV_REALLOC(Triangles, max_triangles*sizeof(MESH_TRIANGLE), "triangle triangle mesh data");
  4057.         }
  4058.  
  4059.         /* Init triangle. */
  4060.  
  4061.         Init_Mesh_Triangle(&Triangles[number_of_triangles]);
  4062.  
  4063.         Triangles[number_of_triangles].P1 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P1);
  4064.         Triangles[number_of_triangles].P2 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P2);
  4065.         Triangles[number_of_triangles].P3 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P3);
  4066.  
  4067.         /* NK 1998 */
  4068.         Parse_Three_UVCoords(UV1,UV2,UV3);
  4069.         Triangles[number_of_triangles].UV1 = Mesh_Hash_UV(&number_of_uvcoords, &max_uvcoords, &UVCoords,UV1);
  4070.         Triangles[number_of_triangles].UV2 = Mesh_Hash_UV(&number_of_uvcoords, &max_uvcoords, &UVCoords,UV2);
  4071.         Triangles[number_of_triangles].UV3 = Mesh_Hash_UV(&number_of_uvcoords, &max_uvcoords, &UVCoords,UV3);
  4072.         /* NK ---- */
  4073.  
  4074. #ifdef ColorTrianglePatch
  4075.         /* NK */
  4076.         /* read possibly three instead of only one texture */
  4077.         /* read these before compute!!! */
  4078.         t2 = t3 = NULL;
  4079.         Triangles[number_of_triangles].Texture = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, Parse_Mesh_Texture(&t2,&t3));
  4080.         if (t2) Triangles[number_of_triangles].Texture2 = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, t2);
  4081.         if (t3) Triangles[number_of_triangles].Texture3 = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, t3);
  4082.         if (t2 || t3) Triangles[number_of_triangles].ThreeTex = TRUE;
  4083. #endif
  4084.  
  4085.         Compute_Mesh_Triangle(&Triangles[number_of_triangles], FALSE, P1, P2, P3, N);
  4086.  
  4087.         Triangles[number_of_triangles].Normal_Ind = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N);
  4088.  
  4089. #ifndef ColorTrianglePatch
  4090.         Triangles[number_of_triangles].Texture = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, Parse_Mesh_Texture());
  4091. #endif
  4092.  
  4093.         if (Triangles[number_of_triangles].Texture < 0)
  4094.         {
  4095.           fully_textured = FALSE;
  4096.         }
  4097.  
  4098.         number_of_triangles++;
  4099.       }
  4100.       /* NK degenerate fix */
  4101.       else
  4102.       {
  4103.         /* parse the uv and texture info - even though we'll just throw it
  4104.            away.  why?  if not we get a parse error - we should just ignore the
  4105.            degenerate triangle */
  4106.         t2=t3=NULL;
  4107.         Parse_Three_UVCoords(UV1,UV2,UV3);
  4108. #ifdef ColorTrianglePatch
  4109.         Parse_Mesh_Texture(&t2,&t3);
  4110. #else
  4111.         Parse_Mesh_Texture();
  4112. #endif
  4113.       }
  4114.  
  4115.       Parse_End();
  4116.     END_CASE
  4117.  
  4118. #ifdef ColorTrianglePatch
  4119.       /* [AP and NK] next CASE */
  4120.  
  4121.     CASE(SMOOTH_COLOR_TRIANGLE_TOKEN)
  4122.       Error("smooth_color_triangle discontinued.  Use texture_list with three textures instead.\n");
  4123.     END_CASE
  4124.  
  4125.     /* [AP and NK] end CASE */
  4126. #endif
  4127.  
  4128.     CASE(SMOOTH_TRIANGLE_TOKEN)
  4129.       Parse_Begin();
  4130.  
  4131.       Parse_Vector(P1);  Parse_Comma();
  4132.       Parse_Vector(N1);  Parse_Comma();
  4133.  
  4134.       Parse_Vector(P2);  Parse_Comma();
  4135.       Parse_Vector(N2);  Parse_Comma();
  4136.  
  4137.       Parse_Vector(P3);  Parse_Comma();
  4138.       Parse_Vector(N3);
  4139.  
  4140.       VLength(l1, N1);
  4141.       VLength(l2, N2);
  4142.       VLength(l3, N3);
  4143.  
  4144.       if ((l1 != 0.0) && (l2 != 0.0) && (l3 != 0.0) && (!Mesh_Degenerate(P1, P2, P3)))
  4145.       {
  4146.         if (number_of_triangles >= max_triangles)
  4147.         {
  4148.           if (max_triangles >= INT_MAX/2)
  4149.           {
  4150.             Error("Too many triangles in triangle mesh.\n");
  4151.           }
  4152.  
  4153.           max_triangles *= 2;
  4154.  
  4155.           Triangles = (MESH_TRIANGLE *)POV_REALLOC(Triangles, max_triangles*sizeof(MESH_TRIANGLE), "triangle triangle mesh data");
  4156.         }
  4157.  
  4158.         VInverseScaleEq(N1, l1);
  4159.         VInverseScaleEq(N2, l2);
  4160.         VInverseScaleEq(N3, l3);
  4161.  
  4162.         /* Init triangle. */
  4163.  
  4164.         Init_Mesh_Triangle(&Triangles[number_of_triangles]);
  4165.  
  4166.         Triangles[number_of_triangles].P1 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P1);
  4167.         Triangles[number_of_triangles].P2 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P2);
  4168.         Triangles[number_of_triangles].P3 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P3);
  4169.  
  4170.         /* Check for equal normals. */
  4171.  
  4172.         VSub(D1, N1, N2);
  4173.         VSub(D2, N1, N3);
  4174.  
  4175.         VDot(l1, D1, D1);
  4176.         VDot(l2, D2, D2);
  4177.  
  4178.         /* NK 1998 */
  4179.         Parse_Three_UVCoords(UV1,UV2,UV3);
  4180.         Triangles[number_of_triangles].UV1 = Mesh_Hash_UV(&number_of_uvcoords, &max_uvcoords, &UVCoords,UV1);
  4181.         Triangles[number_of_triangles].UV2 = Mesh_Hash_UV(&number_of_uvcoords, &max_uvcoords, &UVCoords,UV2);
  4182.         Triangles[number_of_triangles].UV3 = Mesh_Hash_UV(&number_of_uvcoords, &max_uvcoords, &UVCoords,UV3);
  4183.         /* NK ---- */
  4184.  
  4185. #ifdef ColorTrianglePatch
  4186.         /* NK */
  4187.         /* read possibly three instead of only one texture */
  4188.         /* read these before compute!!! */
  4189.         t2 = t3 = NULL;
  4190.         Triangles[number_of_triangles].Texture = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, Parse_Mesh_Texture(&t2,&t3));
  4191.         if (t2) Triangles[number_of_triangles].Texture2 = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, t2);
  4192.         if (t3) Triangles[number_of_triangles].Texture3 = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, t3);
  4193.         if (t2 || t3) Triangles[number_of_triangles].ThreeTex = TRUE;
  4194. #endif
  4195.  
  4196.         if ((fabs(l1) > EPSILON) || (fabs(l2) > EPSILON))
  4197.         {
  4198.           /* Smooth triangle. */
  4199.  
  4200.           Triangles[number_of_triangles].N1 = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N1);
  4201.           Triangles[number_of_triangles].N2 = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N2);
  4202.           Triangles[number_of_triangles].N3 = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N3);
  4203.  
  4204.           Compute_Mesh_Triangle(&Triangles[number_of_triangles], TRUE, P1, P2, P3, N);
  4205.         }
  4206.         else
  4207.         {
  4208.           /* Flat triangle. */
  4209.  
  4210.           Compute_Mesh_Triangle(&Triangles[number_of_triangles], FALSE, P1, P2, P3, N);
  4211.         }
  4212.  
  4213.         Triangles[number_of_triangles].Normal_Ind = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N);
  4214.  
  4215. #ifndef ColorTrianglePatch
  4216.         Triangles[number_of_triangles].Texture = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, Parse_Mesh_Texture());
  4217. #endif
  4218.  
  4219.         if (Triangles[number_of_triangles].Texture < 0)
  4220.         {
  4221.           fully_textured = FALSE;
  4222.         }
  4223.  
  4224.         number_of_triangles++;
  4225.       }
  4226.       /* NK degenerate fix */
  4227.       else
  4228.       {
  4229.         /* parse the uv and texture info - even though we'll just throw it
  4230.            away.  why?  if not we get a parse error - we should just ignore the
  4231.            degenerate triangle */
  4232.         t2=t3=NULL;
  4233.         Parse_Three_UVCoords(UV1,UV2,UV3);
  4234. #ifdef ColorTrianglePatch
  4235.         Parse_Mesh_Texture(&t2,&t3);
  4236. #else
  4237.         Parse_Mesh_Texture();
  4238. #endif
  4239.       }
  4240.  
  4241.       Parse_End();
  4242.     END_CASE
  4243.  
  4244.     /* NK 1998 */
  4245.     CASE(INSIDE_VECTOR_TOKEN)
  4246. #ifdef UnofficialBlocking
  4247.       parseUnofficialFeature(30);
  4248. #endif
  4249.       Parse_Vector(Inside_Vect);
  4250.  
  4251.     END_CASE
  4252.     /* NK ---- */
  4253.  
  4254.     OTHERWISE
  4255.       UNGET
  4256.       EXIT
  4257.     END_CASE
  4258.   END_EXPECT
  4259.  
  4260.   /* Destroy hash tables. */
  4261.  
  4262.   Destroy_Mesh_Hash_Tables();
  4263.  
  4264.   /* If there are no triangles something went wrong. */
  4265.  
  4266.   if (number_of_triangles == 0)
  4267.   {
  4268.     Error("No triangles in triangle mesh.\n");
  4269.   }
  4270.  
  4271.   /* Init triangle mesh data. */
  4272.  
  4273.   Object->Data = (MESH_DATA *)POV_MALLOC(sizeof(MESH_DATA), "triangle mesh data");
  4274.  
  4275.  
  4276.   Object->Data->References = 1;
  4277.  
  4278.   Object->Data->Tree = NULL;
  4279.   /* NK 1998 */
  4280.   /*YS* 31/12/1999 */
  4281.  
  4282.   if( (fabs(Inside_Vect[X]) < EPSILON) &&  (fabs(Inside_Vect[Y]) < EPSILON) &&  (fabs(Inside_Vect[Z]) < EPSILON))
  4283.     Object->has_inside_vector=FALSE;
  4284.   else
  4285.   {
  4286.     VNormalize(Object->Data->Inside_Vect, Inside_Vect);
  4287.     Object->has_inside_vector=TRUE;
  4288.   }
  4289.   /*YS*/
  4290.   
  4291.   Object->Data->Normals   = NULL;
  4292.   Object->Textures  = NULL;
  4293.   Object->Data->Triangles = NULL;
  4294.   Object->Data->Vertices  = NULL;
  4295.  
  4296.   /* Allocate memory for normals, textures, triangles and vertices. */
  4297.  
  4298.   Object->Data->Number_Of_Normals = number_of_normals;
  4299.  
  4300.   Object->Number_Of_Textures = number_of_textures;
  4301.  
  4302.   Object->Data->Number_Of_Triangles = number_of_triangles;
  4303.  
  4304.   Object->Data->Number_Of_Vertices = number_of_vertices;
  4305.  
  4306.   Object->Data->Normals = (SNGL_VECT *)POV_MALLOC(number_of_normals*sizeof(SNGL_VECT), "triangle mesh data");
  4307.  
  4308.   if (number_of_textures)
  4309.   {
  4310.     Set_Flag(Object, MULTITEXTURE_FLAG);
  4311.  
  4312.     Object->Textures = (TEXTURE **)POV_MALLOC(number_of_textures*sizeof(TEXTURE *), "triangle mesh data");
  4313.   }
  4314.  
  4315.   Object->Data->Triangles = (MESH_TRIANGLE *)POV_MALLOC(number_of_triangles*sizeof(MESH_TRIANGLE), "triangle mesh data");
  4316.  
  4317.   Object->Data->Vertices = (SNGL_VECT *)POV_MALLOC(number_of_vertices*sizeof(SNGL_VECT), "triangle mesh data");
  4318.  
  4319.   /* Copy normals, textures, triangles and vertices into mesh. */
  4320.  
  4321.   for (i = 0; i < number_of_normals; i++)
  4322.   {
  4323.     Assign_SNGL_Vect(Object->Data->Normals[i], Normals[i]);
  4324.   }
  4325.  
  4326.   for (i = 0; i < number_of_textures; i++)
  4327.   {
  4328.     Object->Textures[i] = Copy_Textures(Textures[i]);
  4329.  
  4330.     /* now free the texture, in order to decrement the reference count */
  4331.     Destroy_Textures(Textures[i]);
  4332.   }
  4333.   
  4334.   if (fully_textured)
  4335.   {
  4336.     Object->Type |= TEXTURED_OBJECT;
  4337.   }
  4338.  
  4339.   for (i = 0; i < number_of_triangles; i++)
  4340.   {
  4341.     Object->Data->Triangles[i] = Triangles[i];
  4342.   }
  4343.  
  4344.   for (i = 0; i < number_of_vertices; i++)
  4345.   {
  4346.     Assign_SNGL_Vect(Object->Data->Vertices[i], Vertices[i]);
  4347.   }
  4348.  
  4349.   /* NK 1998 */
  4350.   /* do the four steps above, but for UV coordinates*/
  4351.   Object->Data->UVCoords  = NULL;
  4352.   Object->Data->Number_Of_UVCoords = number_of_uvcoords;
  4353.   Object->Data->UVCoords = (UV_VECT *)POV_MALLOC(number_of_uvcoords*sizeof(UV_VECT), "triangle mesh data");
  4354.   for (i = 0; i < number_of_uvcoords; i++)
  4355.   {
  4356.     Assign_UV_Vect(Object->Data->UVCoords[i], UVCoords[i]);
  4357.   }
  4358.   POV_FREE(UVCoords);
  4359.   /* NK ---- */
  4360.  
  4361.   /* Free temporary memory. */
  4362.  
  4363.   POV_FREE(Normals);
  4364.   POV_FREE(Textures);
  4365.   POV_FREE(Triangles);
  4366.   POV_FREE(Vertices);
  4367.  
  4368. /*
  4369.   Render_Info("Mesh: %ld bytes: %ld vertices, %ld normals, %ld textures, %ld triangles\n",
  4370.     Object->Data->Number_Of_Normals*sizeof(SNGL_VECT)+
  4371.     Object->Data->Number_Of_Textures*sizeof(TEXTURE *)+
  4372.     Object->Data->Number_Of_Triangles*sizeof(MESH_TRIANGLE)+
  4373.     Object->Data->Number_Of_Vertices*sizeof(SNGL_VECT),
  4374.     Object->Data->Number_Of_Vertices,
  4375.     Object->Data->Number_Of_Normals,
  4376.     Object->Data->Number_Of_Textures,
  4377.     Object->Data->Number_Of_Triangles);
  4378. */
  4379.  
  4380.   /* Create bounding box. */
  4381.  
  4382.   Compute_Mesh_BBox(Object);
  4383.  
  4384.   /* Parse object modifiers. */
  4385.  
  4386.   Parse_Object_Mods((OBJECT *)Object);
  4387.  
  4388.   /* Create bounding box tree. */
  4389.  
  4390.   Build_Mesh_BBox_Tree(Object);
  4391.  
  4392.   return((OBJECT *)Object);
  4393. }
  4394.  
  4395. /*****************************************************************************
  4396. *
  4397. * FUNCTION
  4398. *
  4399. *   Parse_Mesh2
  4400. *
  4401. * INPUT
  4402. *
  4403. * OUTPUT
  4404. *
  4405. * RETURNS
  4406. *
  4407. *   OBJECT
  4408. *
  4409. * AUTHOR
  4410. *
  4411. *   Nathan Kopp
  4412. *
  4413. * DESCRIPTION
  4414. *
  4415. *   Read a triangle mesh - syntax version 2.
  4416. *
  4417. * CHANGES
  4418. *
  4419. *   Feb 1998 : Creation.
  4420. *
  4421. ******************************************************************************/
  4422. static OBJECT *Parse_Mesh2()
  4423. {
  4424.   int i;
  4425.   int number_of_normals, number_of_textures, number_of_triangles, number_of_vertices, number_of_uvcoords;
  4426.   int number_of_normal_indices;
  4427.   int a,b,c;
  4428.   int n1, n2, n3;
  4429.   int found_normal_indices = 0;
  4430.   int found_uv_indices = 0;
  4431.  
  4432.   DBL l1, l2;
  4433.   VECTOR D1, D2, P1, P2, P3, N1, N;
  4434.   VECTOR Inside_Vect;
  4435.  
  4436.   UV_VECT UV1;
  4437.   SNGL_VECT *Normals = NULL;
  4438.   SNGL_VECT *Vertices = NULL;
  4439.   TEXTURE **Textures = NULL;
  4440.   UV_VECT *UVCoords = NULL;
  4441.   MESH *Object;
  4442.   MESH_TRIANGLE *Triangles;
  4443.  
  4444.   Make_Vector(Inside_Vect, 0, 0, 0);
  4445.  
  4446.   Parse_Begin();
  4447.  
  4448.   if ((Object = (MESH *)Parse_Object_Id()) != NULL)
  4449.     return((OBJECT *)Object);
  4450.  
  4451.   /* Create object. */
  4452.   Object = Create_Mesh();
  4453.  
  4454.   /* normals, uvcoords, and textures are optional */
  4455.   number_of_vertices = 0;
  4456.   number_of_uvcoords = 0;
  4457.   number_of_textures = 0;
  4458.   number_of_normals = 0;
  4459.   number_of_normal_indices = 0;
  4460.  
  4461.  
  4462.   /* -----------------  Get the Normals & UV Vectors & Textures ------------ */
  4463.   EXPECT
  4464.     /* -------------------  Get the Vertices ------------------- */
  4465.     CASE(VERTEX_VECTORS_TOKEN)
  4466.       Parse_Begin();
  4467.  
  4468.       number_of_vertices = (int)Parse_Float(); Parse_Comma();
  4469.  
  4470.       if (number_of_vertices<=0)
  4471.         Error("No vertices in triangle mesh.\n");
  4472.  
  4473.       /* allocate memory for vertices */
  4474.       Vertices = (SNGL_VECT *)POV_MALLOC(number_of_vertices*sizeof(SNGL_VECT), "triangle mesh data");
  4475.  
  4476.       for(i=0; i<number_of_vertices; i++)
  4477.       {
  4478.         Parse_Vector(P1); Parse_Comma();
  4479.         Assign_SNGL_Vect(Vertices[i], P1);
  4480.       }
  4481.       Parse_End();
  4482.     END_CASE
  4483.  
  4484.     CASE(NORMAL_VECTORS_TOKEN)
  4485.       Parse_Begin();
  4486.       number_of_normals = (int)Parse_Float(); Parse_Comma();
  4487.  
  4488.       if (number_of_normals>0)
  4489.       {
  4490.         Normals = (SNGL_VECT *)POV_MALLOC(number_of_normals*sizeof(SNGL_VECT), "triangle mesh data");
  4491.  
  4492.         /* leave space in the array for the raw triangle normals */
  4493.         for(i=0; i<number_of_normals; i++)
  4494.         {
  4495.           Parse_Vector(N1); Parse_Comma();
  4496.           VNormalizeEq(N1);
  4497.           Assign_SNGL_Vect(Normals[i], N1);
  4498.         }
  4499.       }
  4500.  
  4501.       Parse_End();
  4502.     END_CASE
  4503.  
  4504.     CASE(UV_VECTORS_TOKEN)
  4505.       Parse_Begin();
  4506.       number_of_uvcoords = (int)Parse_Float(); Parse_Comma();
  4507.  
  4508.       if (number_of_uvcoords>0)
  4509.       {
  4510.         UVCoords = (UV_VECT *)POV_MALLOC(number_of_uvcoords*sizeof(UV_VECT), "triangle mesh data");
  4511.  
  4512.         for(i=0; i<number_of_uvcoords; i++)
  4513.         {
  4514.           Parse_UV_Vect(UV1); Parse_Comma();
  4515.           Assign_UV_Vect(UVCoords[i], UV1);
  4516.         }
  4517.       }
  4518.  
  4519.       Parse_End();
  4520.     END_CASE
  4521.  
  4522.     /*OTHERWISE
  4523.       UNGET
  4524.       EXIT
  4525.     END_CASE
  4526.   END_EXPECT
  4527.  
  4528.   EXPECT*/
  4529.     CASE(TEXTURE_LIST_TOKEN)
  4530.       Parse_Begin();
  4531.  
  4532.       number_of_textures = (int)Parse_Float();  Parse_Comma();
  4533.  
  4534.       if (number_of_textures>0)
  4535.       {
  4536.         Textures = (TEXTURE **)POV_MALLOC(number_of_textures*sizeof(TEXTURE *), "triangle mesh data");
  4537.  
  4538.         for(i=0; i<number_of_textures; i++)
  4539.         {
  4540.             /*
  4541.              GET(TEXTURE_ID_TOKEN)
  4542.              Textures[i] = Copy_Texture_Pointer((TEXTURE *)Token.Data);
  4543.             */
  4544.             GET(TEXTURE_TOKEN);
  4545.             Parse_Begin();
  4546.             Textures[i] = Parse_Texture();
  4547.             Parse_End();
  4548.             Parse_Comma();
  4549.         }
  4550.       }
  4551.  
  4552.       Parse_End();
  4553.       EXIT
  4554.     END_CASE
  4555.  
  4556.     OTHERWISE
  4557.       UNGET
  4558.       EXIT
  4559.     END_CASE
  4560.  
  4561.   END_EXPECT
  4562.  
  4563.   if (number_of_vertices == 0)
  4564.     Error("Vertex vectors not found in mesh2\n");
  4565.  
  4566.   /* first make sure we at least have one UV coordinate */
  4567.   if (number_of_uvcoords == 0)
  4568.   {
  4569.     number_of_uvcoords = 1;
  4570.     UVCoords = (UV_VECT *)POV_MALLOC(number_of_uvcoords*sizeof(UV_VECT), "triangle mesh data");
  4571.     UVCoords[0][U] = 0;
  4572.     UVCoords[0][V] = 0;
  4573.   }
  4574.  
  4575.   /* -------------------  Get the Faces ------------------- */
  4576.   GET(FACE_INDICES_TOKEN)
  4577.       Parse_Begin();
  4578.  
  4579.   /* number faces is mandatory, so we ask how many there are */
  4580.   number_of_triangles = (int)Parse_Float(); Parse_Comma();
  4581.  
  4582.   if (number_of_triangles == 0)
  4583.   {
  4584.     Error("No triangles in triangle mesh.");
  4585.   }
  4586.  
  4587.   /* allocate memory for triangles */
  4588.   Triangles = (MESH_TRIANGLE *)POV_MALLOC(number_of_triangles*sizeof(MESH_TRIANGLE), "triangle mesh data");
  4589.  
  4590.   /* start reading triangles */
  4591.  
  4592.       for(i=0; i<number_of_triangles; i++)
  4593.       {
  4594.         /* read in the indices vector */
  4595.         Parse_Vector(P1); Parse_Comma();
  4596.  
  4597.         /* convert the vector to integers */
  4598.         a = (int)P1[X];
  4599.         b = (int)P1[Y];
  4600.         c = (int)P1[Z];
  4601.  
  4602.         /* a--;b--;c--; use this to start external stuff at 1 */
  4603.         if ( a<0 || b<0 || c<0 ||
  4604.              a>=number_of_vertices || b>=number_of_vertices ||
  4605.              c>=number_of_vertices)
  4606.         {
  4607.           Error("Mesh face index out of range.");
  4608.         }
  4609.  
  4610.         /* Init triangle. */
  4611.         Init_Mesh_Triangle(&Triangles[i]);
  4612.  
  4613.         /* assign the vertices */
  4614.         Triangles[i].P1 = a;
  4615.         Triangles[i].P2 = b;
  4616.         Triangles[i].P3 = c;
  4617.  
  4618.         /* look for a texture index */
  4619.         EXPECT
  4620.           CASE_FLOAT
  4621.             Triangles[i].Texture = (int)Parse_Float(); Parse_Comma();
  4622.             if (Triangles[i].Texture >= number_of_textures ||
  4623.                 Triangles[i].Texture < 0)
  4624.               Error("Texture index out of range in mesh2.");
  4625.             EXIT
  4626.           END_CASE
  4627.           OTHERWISE
  4628.             Triangles[i].Texture = -1;
  4629.             EXIT
  4630.             UNGET
  4631.           END_CASE
  4632.         END_EXPECT
  4633.         /* look for a texture index */
  4634.         EXPECT
  4635.           CASE_FLOAT
  4636.             Triangles[i].Texture2 = (int)Parse_Float(); Parse_Comma();
  4637.             if (Triangles[i].Texture2 >= number_of_textures ||
  4638.                 Triangles[i].Texture2 < 0)
  4639.               Error("Texture index out of range in mesh2.");
  4640.             Triangles[i].ThreeTex = TRUE;
  4641.             EXIT
  4642.           END_CASE
  4643.           OTHERWISE
  4644.             Triangles[i].Texture2 = -1;
  4645.             EXIT
  4646.             UNGET
  4647.           END_CASE
  4648.         END_EXPECT
  4649.         /* look for a texture index */
  4650.         EXPECT
  4651.           CASE_FLOAT
  4652.             Triangles[i].Texture3 = (int)Parse_Float(); Parse_Comma();
  4653.             if (Triangles[i].Texture3 >= number_of_textures ||
  4654.                 Triangles[i].Texture3 < 0)
  4655.               Error("Texture index out of range in mesh2.");
  4656.             Triangles[i].ThreeTex = TRUE;
  4657.             EXIT
  4658.           END_CASE
  4659.           OTHERWISE
  4660.             Triangles[i].Texture3 = -1;
  4661.             EXIT
  4662.             UNGET
  4663.           END_CASE
  4664.         END_EXPECT
  4665.  
  4666.       }
  4667.  
  4668.       Parse_End();
  4669.  
  4670.   /* now we get the uv_indices & normal_indices in either order */
  4671.  
  4672.   EXPECT
  4673.     CASE(UV_INDICES_TOKEN)
  4674.       if (found_uv_indices)
  4675.       {
  4676.         Error("Only one uv_indices section is allowed in mesh2\n");
  4677.       }
  4678.       found_uv_indices = 1;
  4679.       Parse_Begin();
  4680.  
  4681.       if (Parse_Float() != number_of_triangles)
  4682.         Error("Number of uv indices must equal number of faces.");
  4683.       Parse_Comma();
  4684.  
  4685.       for (i=0; i<number_of_triangles; i++)
  4686.       {
  4687.         /* read in the indices vector */
  4688.         Parse_Vector(P1); Parse_Comma();
  4689.  
  4690.         /* convert the vector to integers */
  4691.         a = (int)P1[X];
  4692.         b = (int)P1[Y];
  4693.         c = (int)P1[Z];
  4694.  
  4695.         /* a--;b--;c--; use this to start external stuff at 1 */
  4696.         if ( a<0 || b<0 || c<0 ||
  4697.              a>=number_of_uvcoords || b>=number_of_uvcoords ||
  4698.              c>=number_of_uvcoords)
  4699.         {
  4700.           Error("Mesh UV index out of range.");
  4701.         }
  4702.  
  4703.         /* assign the uv coordinate */
  4704.         Triangles[i].UV1 = a;
  4705.         Triangles[i].UV2 = b;
  4706.         Triangles[i].UV3 = c;
  4707.       }
  4708.       Parse_End();
  4709.       /*EXIT*/
  4710.     END_CASE
  4711.  
  4712.   /*
  4713.     OTHERWISE
  4714.       UNGET
  4715.       EXIT
  4716.     END_CASE
  4717.   END_EXPECT
  4718.  
  4719.   EXPECT
  4720.   */
  4721.     CASE(NORMAL_INDICES_TOKEN)
  4722.       if (found_normal_indices)
  4723.       {
  4724.         Error("Only one normal_indices section is allowed in mesh2\n");
  4725.       }
  4726.       found_normal_indices = 1;
  4727.       Parse_Begin();
  4728.  
  4729.       /*
  4730.       Change - if fewer normals than triangles, then no problem - the
  4731.       rest will be flat triangles.
  4732.  
  4733.       if (Parse_Float() != number_of_triangles)
  4734.         Error("Number of normal indices must equal number of faces.");
  4735.       */
  4736.       number_of_normal_indices = (int)Parse_Float();
  4737.       if (number_of_normal_indices > number_of_triangles)
  4738.         Error("Number of normal indices cannot be more than the number of faces.");
  4739.  
  4740.       Parse_Comma();
  4741.  
  4742.       for (i=0; i<number_of_normal_indices; i++)
  4743.       {
  4744.         /* read in the indices vector */
  4745.         Parse_Vector(P1); Parse_Comma();
  4746.  
  4747.         /* convert the vector to integers */
  4748.         a = (int)P1[X];
  4749.         b = (int)P1[Y];
  4750.         c = (int)P1[Z];
  4751.  
  4752.         /* a--;b--;c--; use this to start external stuff at 1 */
  4753.         if ( a<0 || b<0 ||
  4754.              c<0 ||
  4755.              a>=number_of_normals || b>=number_of_normals ||
  4756.              c>=number_of_normals)
  4757.         {
  4758.           Error("Mesh normal index out of range.");
  4759.         }
  4760.  
  4761.         /* assign the uv coordinate */
  4762.         Triangles[i].N1 = a;
  4763.         Triangles[i].N2 = b;
  4764.         Triangles[i].N3 = c;
  4765.       }
  4766.       Parse_End();
  4767.       /*EXIT*/
  4768.     END_CASE
  4769.  
  4770.     OTHERWISE
  4771.       UNGET
  4772.       EXIT
  4773.     END_CASE
  4774.   END_EXPECT
  4775.  
  4776.   /* ----------------------------------------------------- */
  4777.   /* ----------------------------------------------------- */
  4778.  
  4779.   EXPECT
  4780.     CASE(INSIDE_VECTOR_TOKEN)
  4781.       Parse_Vector(Inside_Vect);
  4782.     END_CASE
  4783.  
  4784.     OTHERWISE
  4785.       UNGET
  4786.       EXIT
  4787.     END_CASE
  4788.   END_EXPECT
  4789.  
  4790.   if (!found_uv_indices)
  4791.   {
  4792.     if (number_of_uvcoords==number_of_vertices)
  4793.     {
  4794.       for (i=0; i<number_of_triangles; i++)
  4795.       {
  4796.         Triangles[i].UV1 = Triangles[i].P1;
  4797.         Triangles[i].UV2 = Triangles[i].P2;
  4798.         Triangles[i].UV3 = Triangles[i].P3;
  4799.       }
  4800.     }
  4801.     else if (number_of_uvcoords==1)
  4802.     {
  4803.       for (i=0; i<number_of_triangles; i++)
  4804.       {
  4805.         Triangles[i].UV1 = 0;
  4806.         Triangles[i].UV2 = 0;
  4807.         Triangles[i].UV3 = 0;
  4808.       }
  4809.     }
  4810.     else
  4811.     {
  4812.       Error("Missing uv_indicies section in mesh2.");
  4813.     }
  4814.   }
  4815.  
  4816.   if (!found_normal_indices)
  4817.   {
  4818.     if (number_of_normals==number_of_vertices)
  4819.     {
  4820.       /* If number of normals matches number of vertices, then assume
  4821.          that the normal_indices are the same as the triangle indices
  4822.          (left out for file size reasons).
  4823.          So, we pretend that we read in some normal_indices
  4824.       */
  4825.       number_of_normal_indices = number_of_triangles;
  4826.  
  4827.       for (i=0; i<number_of_triangles; i++)
  4828.       {
  4829.         Triangles[i].N1 = Triangles[i].P1;
  4830.         Triangles[i].N2 = Triangles[i].P2;
  4831.         Triangles[i].N3 = Triangles[i].P3;
  4832.       }
  4833.     }
  4834.     else if (number_of_normals)
  4835.     {
  4836.       Error("Missing normal_indicies section in mesh2.");
  4837.     }
  4838.   }
  4839.  
  4840.   /* ---------------- Compute Triangle Normals ---------------- */
  4841.  
  4842.   /* reallocate the normals stuff */
  4843.   if (!number_of_normals)
  4844.     Normals = (SNGL_VECT *)POV_MALLOC(number_of_triangles*sizeof(SNGL_VECT), "triangle mesh data");
  4845.   else
  4846.     Normals = (SNGL_VECT *)POV_REALLOC(Normals, (number_of_normals+number_of_triangles)*sizeof(SNGL_VECT), "triangle mesh data");
  4847.  
  4848.   for (i=0; i<number_of_triangles; i++)
  4849.   {
  4850.     a = Triangles[i].P1;
  4851.     b = Triangles[i].P2;
  4852.     c = Triangles[i].P3;
  4853.     n1 = Triangles[i].N1;
  4854.     n2 = Triangles[i].N2;
  4855.     n3 = Triangles[i].N3;
  4856.  
  4857.     Assign_SNGL_Vect(P1, Vertices[a]);
  4858.     Assign_SNGL_Vect(P2, Vertices[b]);
  4859.     Assign_SNGL_Vect(P3, Vertices[c]);
  4860.  
  4861.     Triangles[i].Smooth = FALSE;
  4862.  
  4863.     /* compute the normal (check for smoothness) */
  4864.     /* if number_of_normal_indices > 0, then the first triangles
  4865.        are smooth and the rest are flat */
  4866.     if (i<number_of_normal_indices)
  4867.     {
  4868.       /* Check for equal normals. */
  4869.       VSub(D1, Normals[n1], Normals[n2]);
  4870.       VSub(D2, Normals[n1], Normals[n3]);
  4871.  
  4872.       VDot(l1, D1, D1);
  4873.       VDot(l2, D2, D2);
  4874.  
  4875.       if ((fabs(l1) > EPSILON) || (fabs(l2) > EPSILON))
  4876.       {
  4877.         /* Smooth triangle. */
  4878.         Compute_Mesh_Triangle(&Triangles[i], TRUE, P1, P2, P3, N);
  4879.         Triangles[i].Smooth = TRUE;
  4880.       }
  4881.       else
  4882.       {
  4883.         /* Flat triangle. */
  4884.         Compute_Mesh_Triangle(&Triangles[i], FALSE, P1, P2, P3, N);
  4885.       }
  4886.     }
  4887.     else
  4888.     {
  4889.       /* Flat triangle. */
  4890.       Compute_Mesh_Triangle(&Triangles[i], FALSE, P1, P2, P3, N);
  4891.     }
  4892.  
  4893.     /* assign the triangle normal that we just computed */
  4894.     Triangles[i].Normal_Ind = i+number_of_normals;
  4895.     Assign_SNGL_Vect(Normals[i+number_of_normals], N);
  4896.   }
  4897.  
  4898.   /* now remember how many normals we really have */
  4899.   number_of_normals += number_of_triangles;
  4900.  
  4901.   /* ----------------------------------------------------- */
  4902.  
  4903.   /* Init triangle mesh data. */
  4904.   Object->Data = (MESH_DATA*)POV_MALLOC(sizeof(MESH_DATA), "triangle mesh data");
  4905.   Object->Data->References = 1;
  4906.   Object->Data->Tree = NULL;
  4907.   /* NK 1998 */
  4908.   /*YS* 31/12/1999 */
  4909.  
  4910.   if( (fabs(Inside_Vect[X]) < EPSILON) &&  (fabs(Inside_Vect[Y]) < EPSILON) &&  (fabs(Inside_Vect[Z]) < EPSILON))
  4911.     Object->has_inside_vector=FALSE;
  4912.   else
  4913.   {
  4914.     VNormalize(Object->Data->Inside_Vect, Inside_Vect);
  4915.     Object->has_inside_vector=TRUE;
  4916.   }
  4917.   /*YS*/
  4918.  
  4919.   /* copy pointers to normals, triangles, textures, and vertices. */
  4920.   Object->Data->Normals   = Normals;
  4921.   Object->Data->Triangles = Triangles;
  4922.   Object->Data->Vertices  = Vertices;
  4923.   Object->Data->UVCoords  = UVCoords;
  4924.   Object->Textures  = Textures;
  4925.  
  4926.   /* copy number of for normals, textures, triangles and vertices. */
  4927.   Object->Data->Number_Of_Normals = number_of_normals;
  4928.   Object->Data->Number_Of_Triangles = number_of_triangles;
  4929.   Object->Data->Number_Of_Vertices = number_of_vertices;
  4930.   Object->Data->Number_Of_UVCoords  = number_of_uvcoords;
  4931.   Object->Number_Of_Textures = number_of_textures;
  4932.  
  4933.   if (number_of_textures)
  4934.   {
  4935.     Set_Flag(Object, MULTITEXTURE_FLAG);
  4936.   }
  4937.  
  4938.   /* Create bounding box. */
  4939.   Compute_Mesh_BBox(Object);
  4940.  
  4941.   /* Parse object modifiers. */
  4942.   Parse_Object_Mods((OBJECT *)Object);
  4943.  
  4944.   /* Create bounding box tree. */
  4945.   Build_Mesh_BBox_Tree(Object);
  4946.  
  4947. /*
  4948.   Render_Info("Mesh2: %ld bytes: %ld vertices, %ld normals, %ld textures, %ld triangles\n",
  4949.     Object->Data->Number_Of_Normals*sizeof(SNGL_VECT)+
  4950.     Object->Data->Number_Of_Textures*sizeof(TEXTURE *)+
  4951.     Object->Data->Number_Of_Triangles*sizeof(MESH_TRIANGLE)+
  4952.     Object->Data->Number_Of_Vertices*sizeof(SNGL_VECT),
  4953.     Object->Data->Number_Of_Vertices,
  4954.     Object->Data->Number_Of_Normals,
  4955.     Object->Data->Number_Of_Textures,
  4956.     Object->Data->Number_Of_Triangles);
  4957. */
  4958.  
  4959.   return((OBJECT *)Object);
  4960. }
  4961.  
  4962.  
  4963. /*****************************************************************************
  4964. *
  4965. * FUNCTION
  4966. *
  4967. * INPUT
  4968. *   
  4969. * OUTPUT
  4970. *   
  4971. * RETURNS
  4972. *   
  4973. * AUTHOR
  4974. *   
  4975. * DESCRIPTION
  4976. *
  4977. * CHANGES
  4978. *
  4979. ******************************************************************************/
  4980.  
  4981. static
  4982. OBJECT *Parse_Poly (int order)
  4983. {
  4984.    POLY *Object;
  4985.  
  4986.    Parse_Begin ();
  4987.  
  4988.    if ( (Object = (POLY *)Parse_Object_Id()) != NULL)
  4989.       return ((OBJECT *) Object);
  4990.  
  4991.    if (order == 0)
  4992.      {
  4993.       order = (int)Parse_Float();      Parse_Comma();
  4994.       if (order < 2 || order > MAX_ORDER)
  4995.         Error("Order of poly is out of range.");
  4996.      }
  4997.  
  4998.    Object = Create_Poly(order);
  4999.  
  5000.    Parse_Coeffs(Object->Order, &(Object->Coeffs[0]));
  5001.  
  5002.    Compute_Poly_BBox(Object);
  5003.  
  5004.    Parse_Object_Mods ((OBJECT *)Object);
  5005.  
  5006.    return ((OBJECT *) Object);
  5007.   }
  5008.  
  5009.  
  5010.  
  5011. /*****************************************************************************
  5012. *
  5013. * FUNCTION
  5014. *
  5015. * INPUT
  5016. *   
  5017. * OUTPUT
  5018. *   
  5019. * RETURNS
  5020. *   
  5021. * AUTHOR
  5022. *   
  5023. * DESCRIPTION
  5024. *
  5025. * CHANGES
  5026. *
  5027. ******************************************************************************/
  5028.  
  5029. #ifdef RBezierPatch
  5030. static void bicubic_patch_warning(BICUBIC_PATCH *Object, char flag)
  5031. {
  5032.   if ( flag ^ ((Object->Patch_Type == BEZIER_NSK) || (Object->Patch_Type == RATIONAL_BEZIER_NSK)))
  5033.     Warn(150, "This parameter is useless with current bicubic type");  
  5034. }
  5035.  
  5036. #endif
  5037. static
  5038. OBJECT *Parse_Bicubic_Patch ()
  5039. {
  5040.    BICUBIC_PATCH *Object;
  5041. #ifdef RBezierPatch
  5042.    DBL           hvector[4];
  5043. #endif
  5044.    int i, j;
  5045.  
  5046.    Parse_Begin ();
  5047.  
  5048.    if ( (Object = (BICUBIC_PATCH *)Parse_Object_Id()) != NULL)
  5049.       return ((OBJECT *) Object);
  5050.  
  5051.    Object = Create_Bicubic_Patch();
  5052.  
  5053.    EXPECT
  5054.      CASE_FLOAT
  5055.        Warn(150, "Should use keywords for bicubic parameters.");
  5056.        Object->Patch_Type = (int)Parse_Float();
  5057.        if (Object->Patch_Type == 2 ||
  5058.            Object->Patch_Type == 3)
  5059.            Object->Flatness_Value = Parse_Float();
  5060.          else
  5061.            Object->Flatness_Value = 0.1;
  5062.        Object->U_Steps = (int)Parse_Float();
  5063.        Object->V_Steps = (int)Parse_Float();
  5064.        EXIT
  5065.      END_CASE
  5066.        
  5067.      CASE (TYPE_TOKEN)
  5068.        Object->Patch_Type = (int)Parse_Float();
  5069.      END_CASE
  5070.  
  5071.      CASE (FLATNESS_TOKEN)
  5072. #ifdef RBezierPatch
  5073.        bicubic_patch_warning( Object, 0 );
  5074. #endif
  5075.        Object->Flatness_Value = Parse_Float();
  5076.      END_CASE
  5077.  
  5078.      CASE (V_STEPS_TOKEN)
  5079. #ifdef RBezierPatch
  5080.        bicubic_patch_warning( Object, 0 );
  5081. #endif
  5082.        Object->V_Steps = (int)Parse_Float();
  5083.      END_CASE
  5084.  
  5085.      CASE (U_STEPS_TOKEN)
  5086. #ifdef RBezierPatch
  5087.        bicubic_patch_warning( Object, 0 );
  5088. #endif
  5089.        Object->U_Steps = (int)Parse_Float();
  5090.      END_CASE
  5091.  
  5092. #ifdef RBezierPatch
  5093.      CASE (ACCURACY_TOKEN)
  5094. #ifdef UnofficialBlocking
  5095.        parseUnofficialFeature(30);
  5096. #endif
  5097.        bicubic_patch_warning( Object, 1 );
  5098.        Object->accuracy = Parse_Float();
  5099.      END_CASE
  5100. #endif
  5101. /*YS Moved parsing of the uv_vectors after parsing of the control points
  5102.     to be consistent with triangle mesh */
  5103.     
  5104.      OTHERWISE
  5105.        UNGET
  5106.        EXIT
  5107.      END_CASE
  5108.    END_EXPECT
  5109.  
  5110. #ifdef RBezierPatch
  5111.    if (Object->Patch_Type >= MAX_PATCH_TYPE)
  5112. #else
  5113.    if (Object->Patch_Type > 1)
  5114. #endif
  5115.      {
  5116.       Object->Patch_Type = 1;
  5117.       Warn(0, "Patch type no longer supported. Using type 1.");
  5118.      }
  5119.  
  5120.    if ((Object->Patch_Type < 0) || (Object->Patch_Type > MAX_PATCH_TYPE))
  5121.      Error("Undefined bicubic patch type.");
  5122.  
  5123.    Parse_Comma();
  5124.  
  5125. #ifdef RBezierPatch
  5126.    if (Object->Patch_Type == RATIONAL_BEZIER_NSK)
  5127.    {
  5128.       Object->Weights= (WEIGHTS*)POV_MALLOC( sizeof(WEIGHTS), "bicubic patch");
  5129.    }
  5130. #endif
  5131.  
  5132.   for (i=0;i<4;i++)
  5133.      for (j=0;j<4;j++)
  5134.        {
  5135. #ifdef RBezierPatch
  5136.          if (Object->Patch_Type != RATIONAL_BEZIER_NSK)
  5137. #endif
  5138.            Parse_Vector(Object->Control_Points[i][j]);
  5139. #ifdef RBezierPatch
  5140.            else
  5141.            {
  5142.              Parse_RBezierPatchVector4D(hvector);
  5143.              Object->Control_Points[i][j][X]= hvector[X];
  5144.              Object->Control_Points[i][j][Y]= hvector[Y];
  5145.              Object->Control_Points[i][j][Z]= hvector[Z];
  5146.              (*(Object->Weights))[i][j]= hvector[3];                   
  5147.            }
  5148. #endif
  5149.  
  5150.          if (!((i==3)&&(j==3)))
  5151.            Parse_Comma();
  5152.        }
  5153.  
  5154. /*YS Moved parsing of the uv_vectors to here
  5155.     to be consistent with triangle mesh */
  5156.    EXPECT
  5157.      CASE_FLOAT
  5158.      /* NK 1998 */
  5159.      CASE(UV_VECTORS_TOKEN)
  5160. #ifdef UnofficialBlocking
  5161.        parseUnofficialFeature(30);
  5162. #endif
  5163.   #ifndef UpdatedUVMappingPatch
  5164.      /* syntax is Start, End   but we want to store it as  */
  5165.        /*   Start & (End-Start) for speed reasons            */
  5166.        Parse_UV_Vect(Object->UV_Start);  Parse_Comma();
  5167.        Parse_UV_Vect(Object->UV_Diff);
  5168.  
  5169.        /* right now UV_Diff is holding UV_End, so we need to change that */
  5170.        Object->UV_Diff[U] = Object->UV_Diff[U] - Object->UV_Start[U];
  5171.        Object->UV_Diff[V] = Object->UV_Diff[V] - Object->UV_Start[V];
  5172. #else
  5173.        /* altered by MH 2000.  Store 4 ST coords for quadrilateral  */
  5174.        Parse_UV_Vect(Object->ST[0]);  Parse_Comma();
  5175.        Parse_UV_Vect(Object->ST[1]);  Parse_Comma();
  5176.        Parse_UV_Vect(Object->ST[2]);  Parse_Comma();
  5177.        Parse_UV_Vect(Object->ST[3]); 
  5178.         /*YS sept 17 2000 Moved MSquareQuad() to here for better error handling
  5179.             see function MSquareQuad() for more info 
  5180.         /*YS*/
  5181. #endif
  5182.        EXIT
  5183.      END_CASE
  5184.      /* NK ---- */
  5185.  
  5186.      OTHERWISE
  5187.        UNGET
  5188.        EXIT
  5189.      END_CASE
  5190.    END_EXPECT
  5191.  
  5192. /* MH 
  5193.     Might want to skip the following if not using uv mapping 
  5194.     for speed reasons - I put it here to make sure it gets done for now*/
  5195.     MSquareQuad(Object->ST, Object->Mapping); /* mapping matrix */
  5196. /*    MH */
  5197.  
  5198.    Precompute_Patch_Values(Object); /* interpolated mesh coords */
  5199.  
  5200.    Compute_Bicubic_Patch_BBox(Object);  
  5201.  
  5202.    Parse_Object_Mods ((OBJECT *)Object);
  5203.  
  5204.    return ((OBJECT *) Object);
  5205.   }
  5206.  
  5207. #ifdef RBezierPatch
  5208. /***************************************************
  5209.  
  5210.    RBezier  & Parse_Trims
  5211.  
  5212.  **************************************************/
  5213.  
  5214. static TRIM_SHAPE *Parse_Trim(void)
  5215. {
  5216.   TRIM_SHAPE    *trim;
  5217.  
  5218.   DBL           u[TRIM_MAX_CONST], v[TRIM_MAX_CONST], w[TRIM_MAX_CONST];
  5219.   
  5220.   char          ttypes[TRIM_MAX_CONST];
  5221.   int           uvnum=0,
  5222.         wnum=0, 
  5223.         tnum=0,
  5224.         tmp, rat, ord;
  5225.   VECTOR        vec;
  5226.   char          skip, copy, ctmp;
  5227.   
  5228.   Parse_Begin();
  5229.   Get_Token();
  5230.   if (Token.Token_Id == TRIMMED_BY_ID_TOKEN)
  5231.     {
  5232.       trim= (TRIM_SHAPE *) Token.Data;
  5233.       copy=0;
  5234.       EXPECT
  5235.     CASE (TYPE_TOKEN)
  5236.        if (copy==0) { copy=1; trim= trim_deep_copy(trim); }
  5237.        trim-> ttype= ctmp= Parse_Float();
  5238.        if ((ctmp!=0)&&(ctmp!=1)) Error("Wrong trim type");
  5239.     END_CASE
  5240.  
  5241.       CASE (SCALE_TOKEN)
  5242.      if (copy==0) { copy=1; trim= trim_deep_copy(trim); }
  5243.      Parse_UV_Vect( vec );
  5244.      trim_scale_cp( vec, trim->u, trim->v, trim->num_of_cp );
  5245.       END_CASE
  5246.  
  5247.       CASE (ROTATE_TOKEN)
  5248.       if (copy==0) { copy=1; trim= trim_deep_copy(trim); }
  5249.       vec[0]= Parse_Float();
  5250.       trim_rotate_cp( vec[0], trim->u, trim->v, trim->num_of_cp );
  5251.        END_CASE
  5252.  
  5253.        CASE (TRANSLATE_TOKEN)
  5254.      if (copy==0) { copy=1; trim= trim_deep_copy(trim); }
  5255.      Parse_UV_Vect( vec );
  5256.      trim_translate_cp( vec, trim->u, trim->v, trim->num_of_cp );
  5257.     END_CASE
  5258.  
  5259.     OTHERWISE
  5260.         UNGET
  5261.         EXIT
  5262.     END_CASE
  5263.       END_EXPECT            
  5264.  
  5265.       if (copy==0) 
  5266.     trim= Copy_Trim(trim);
  5267.       else
  5268.     trim_compute_bounds( trim );
  5269.     
  5270.         Parse_End();
  5271.         return trim;
  5272.     }
  5273.         
  5274.     trim=(TRIM_SHAPE*) POV_MALLOC( sizeof(TRIM_SHAPE), "trimmig shape");
  5275.   trim->refs= 1;
  5276.   trim->ttype= 0;
  5277.   
  5278.   if (Token.Token_Id == TYPE_TOKEN)
  5279.     {
  5280.       trim->ttype=tmp= Parse_Float();
  5281.       if ((tmp != 0) && (tmp!=1)) 
  5282.     Error("Wrong trim type");
  5283.     }
  5284.   else
  5285.     Unget_Token();
  5286.   
  5287.   EXPECT
  5288.     CASE_FLOAT
  5289.       ord= Parse_Float();
  5290.       if ((ord < 2)||(ord>4)) 
  5291.     Error("Trimming shape: wrong number of control points");
  5292.       
  5293.       rat= 0;
  5294.       if (ord != 2)
  5295.     {
  5296.       Get_Token();
  5297.       if (Token.Token_Id == RATIONAL_TOKEN) rat= 1;
  5298.       else Unget_Token();
  5299.     }
  5300.  
  5301.       for (tmp = 0; tmp < ord; tmp ++)
  5302.     {
  5303.       skip= 0;
  5304.  
  5305.       Get_Token();
  5306.  
  5307.       if ((Token.Token_Id==FIRST_TOKEN) && (uvnum != 0))
  5308.         {
  5309.           skip=1;   vec[0]= u[0];   vec[1]= v[0];
  5310.         }
  5311.  
  5312.       if ((Token.Token_Id==PREVIOUS_TOKEN) && (tmp==0) && (uvnum !=0))
  5313.         {
  5314.           skip=1;  vec[0]= u[uvnum-1];  vec[1]= v[uvnum-1];
  5315.         }
  5316.  
  5317.       if ((skip != 0) && (rat!=0))
  5318.         {   
  5319.           Parse_Comma();
  5320.           w[wnum++]= Parse_Float();
  5321.         }
  5322.  
  5323.       if (skip==0)
  5324.         {
  5325.           Unget_Token();
  5326.           if (rat)
  5327.         {
  5328.           Parse_Vector(vec);
  5329.           w[wnum++]= vec[2];
  5330.         }
  5331.           else
  5332.         Parse_UV_Vect(vec);
  5333.         }
  5334.  
  5335.       if ((tmp != 0) || (uvnum==0))
  5336.         {
  5337.           u[uvnum]= vec[0];
  5338.           v[uvnum]= vec[1];
  5339.           uvnum++;
  5340.         }
  5341.       else
  5342.         if ((vec[0]!=u[uvnum-1])||(vec[1]!=v[uvnum-1])) /* connect with last point by line */
  5343.           {
  5344.         u[uvnum]= vec[0];
  5345.         v[uvnum]= vec[1];
  5346.         uvnum++;
  5347.         ttypes[tnum++]= 2;
  5348.           }
  5349.  
  5350.       if (tmp!= ord -1) Parse_Comma();
  5351.     }
  5352.  
  5353.       ttypes[tnum++]= ord | ( rat << 4);
  5354.     END_CASE
  5355.  
  5356.     CASE (SCALE_TOKEN)
  5357.        Parse_UV_Vect( vec );
  5358.        trim_scale_cp( vec, u,v, uvnum );
  5359.     END_CASE
  5360.  
  5361.     CASE (ROTATE_TOKEN)
  5362.     vec[0]= Parse_Float();
  5363.     trim_rotate_cp( vec[0], u,v,uvnum);
  5364.     END_CASE
  5365.  
  5366.     CASE (TRANSLATE_TOKEN)
  5367.        Parse_UV_Vect( vec );
  5368.        trim_translate_cp( vec, u,v, uvnum );
  5369.     END_CASE
  5370.  
  5371.     OTHERWISE
  5372.       UNGET
  5373.       EXIT
  5374.     END_CASE
  5375.   END_EXPECT
  5376.  
  5377.   if ((u[uvnum-1] != u[0])||(v[uvnum-1] != v[0]))
  5378.     { /* connect last & first poit */
  5379.       u[uvnum]= u[0];
  5380.       v[uvnum]= v[0];
  5381.       uvnum++;
  5382.       ttypes[tnum++]= 2;
  5383.     }
  5384.   tmp= sizeof(DBL)*(uvnum*2 + wnum) + sizeof(char)*tnum;
  5385.  
  5386.   trim->v= trim->u= (DBL *) POV_MALLOC( tmp, "trimming shape");
  5387.   trim->w= trim->v+= uvnum;
  5388.   trim->w+=uvnum;
  5389.   trim->ctypes= (char *) (trim->w + wnum);
  5390.  
  5391.   trim-> num_of_parts= tnum;
  5392.   trim-> num_of_cp= uvnum;
  5393.       
  5394.   memcpy (trim->u, u, sizeof(DBL) * uvnum);
  5395.   memcpy (trim->v, v, sizeof(DBL) * uvnum);
  5396.   if (wnum)
  5397.     memcpy(trim->w, w, sizeof(DBL) * wnum);
  5398.   memcpy(trim->ctypes, ttypes, sizeof(char)*tnum);
  5399.   
  5400.   trim_compute_bounds( trim );
  5401.  
  5402.   Parse_End();
  5403.   return trim;
  5404. }
  5405.  
  5406. static
  5407. OBJECT *Parse_RBezier_Patch(void)
  5408. {
  5409.   RBEZIER_PATCH *Object;
  5410.   int           i, j, rat=0;
  5411.   DBL           hvector[4];
  5412.  
  5413.   TRIM_SHAPE    *(trims[TRIM_MAX_CONST]);
  5414.   int           noft=0;
  5415.  
  5416.   Parse_Begin();
  5417.  
  5418.   if ( (Object = (RBEZIER_PATCH *) Parse_Object_Id ()) != NULL)
  5419.     return ((OBJECT *) Object);
  5420.  
  5421.   Object = Create_RBezier_Patch();
  5422.  
  5423.   Object-> u_order= (int) Parse_Float(); Parse_Comma();
  5424.   Object-> v_order= (int) Parse_Float();
  5425.  
  5426.   if ((Object-> u_order < 2 ) || (Object-> u_order > 4) ||
  5427.       (Object-> v_order < 2 ) || (Object-> v_order > 4))
  5428.     Error("Wrong number of control points");
  5429.  
  5430.   EXPECT
  5431.  
  5432. #ifdef DEBUG_RBEZIER
  5433.     CASE (DEBUG_TOKEN)
  5434.      Object->debug=1;
  5435.     END_CASE
  5436. #endif
  5437.  
  5438.     CASE (RATIONAL_TOKEN)
  5439.       rat=1;
  5440.     END_CASE
  5441.  
  5442.     CASE (ACCURACY_TOKEN)
  5443.       Object-> accuracy = Parse_Float();
  5444.     END_CASE
  5445.  
  5446.     OTHERWISE
  5447.       UNGET
  5448.       EXIT
  5449.     END_CASE
  5450.  
  5451.   END_EXPECT
  5452.  
  5453.   Object-> Points= (DBL *) POV_MALLOC( sizeof(DBL) * 3 * 4 * (Object->v_order), "bezier patch");
  5454.  
  5455.   for (i=0; i < 4 * 3 * (Object->v_order); Object->Points[i]=0.0, i++);
  5456.  
  5457.   Object->pts[X]= Object->Points;
  5458.   Object->pts[Y]= &(Object->Points[4*Object->v_order]);
  5459.   Object->pts[Z]= &(Object->Points[2*4*Object->v_order]);
  5460.  
  5461.   if (rat)
  5462.     Object-> Weights= (DBL *) POV_MALLOC( sizeof(DBL) * 4 * (Object->v_order), "bezier patch");
  5463.  
  5464.   for (i=0; i < Object->v_order ; i++)
  5465.     for (j=0; j < Object->u_order; j++)
  5466.       {
  5467.     if (!rat)
  5468.       {
  5469.         Parse_Vector( hvector );
  5470.     
  5471.         Object->Points[ 4*X*(Object->v_order) + 4*i + j]  = hvector[X];
  5472.         Object->Points[ 4*Y*(Object->v_order) + 4*i + j]  = hvector[Y];
  5473.         Object->Points[ 4*Z*(Object->v_order) + 4*i + j]  = hvector[Z];
  5474.     
  5475.       }
  5476.     else
  5477.       {
  5478.         Parse_Vector4D(hvector);        
  5479.     
  5480.         Object->Points[ 4*X*(Object->v_order) + 4*i + j]  = hvector[X];
  5481.         Object->Points[ 4*Y*(Object->v_order) + 4*i + j]  = hvector[Y];
  5482.         Object->Points[ 4*Z*(Object->v_order) + 4*i + j]  = hvector[Z];
  5483.         Object->Weights[4*i+j]= hvector[3];
  5484.     
  5485.       }
  5486.     if ((i!= Object->v_order-1) || (j!=Object->u_order))
  5487.       Parse_Comma();
  5488.       }
  5489.  
  5490.   EXPECT
  5491.      CASE (TRIMMED_BY_TOKEN)
  5492.      trims[noft]= Parse_Trim();
  5493.      noft++;
  5494.      if (noft == TRIM_MAX_CONST)
  5495.        Error("To many trims");
  5496.      END_CASE
  5497.  
  5498.      OTHERWISE
  5499.       UNGET
  5500.       EXIT
  5501.      END_CASE
  5502.   END_EXPECT
  5503.  
  5504.   if (noft != 0)
  5505.     {
  5506.       Object->trims= (TRIM_SHAPE **) POV_MALLOC( noft * sizeof(TRIM_SHAPE *), "trimming curves");
  5507.       memcpy( Object->trims, trims, noft * sizeof(TRIM_SHAPE *));
  5508.       Object-> num_of_trims= noft;
  5509.     }
  5510.    
  5511.   Compute_RBezier_Patch_BBox(Object);
  5512.  
  5513.   Parse_Object_Mods ((OBJECT *) Object);
  5514.  
  5515. #ifdef DEBUG_RBEZIER
  5516.   if (Object->debug)
  5517.     Warn(0,"You enabled debugging code in RBezier patch. Intersection will be performed only if dirrection of ray is Z");
  5518. #endif
  5519.  
  5520.   return ((OBJECT *) Object);
  5521. }
  5522.  
  5523.  
  5524. #endif
  5525.  
  5526.  
  5527.  
  5528. /*****************************************************************************
  5529. *
  5530. * FUNCTION
  5531. *
  5532. * INPUT
  5533. *   
  5534. * OUTPUT
  5535. *   
  5536. * RETURNS
  5537. *   
  5538. * AUTHOR
  5539. *   
  5540. * DESCRIPTION
  5541. *
  5542. * CHANGES
  5543. *
  5544. ******************************************************************************/
  5545.  
  5546. static
  5547. OBJECT *Parse_TrueType ()
  5548. {
  5549.    OBJECT *Object;
  5550.    char *filename, *text_string;
  5551.    DBL depth;
  5552.    VECTOR offset;
  5553.    TRANSFORM Local_Trans;
  5554.  
  5555. #ifdef FontAnlignmentPatch
  5556.     int position=0;
  5557. #endif
  5558.  
  5559.    Parse_Begin ();
  5560.    
  5561.    GET(TTF_TOKEN);
  5562.  
  5563.    if ( (Object = (OBJECT *)Parse_Object_Id()) != NULL)
  5564.       return ((OBJECT *) Object);
  5565.       
  5566.    Object = (OBJECT *)Create_CSG_Union ();
  5567.    /*** Object = Create_TTF(); */
  5568.  
  5569.    /* Parse the TrueType font file name */
  5570.    filename = Parse_String();
  5571.    Parse_Comma();
  5572.  
  5573.    /* Parse the text string to be rendered */
  5574.    text_string = Parse_String();
  5575.    Parse_Comma();
  5576.  
  5577.    /* Get the extrusion depth */
  5578.    depth = Parse_Float(); Parse_Comma ();
  5579.  
  5580.    /* Get the offset vector */
  5581.    Parse_Vector(offset);
  5582.  
  5583.  
  5584. #ifdef FontAnlignmentPatch
  5585.    position = 0; /* default to left-justified */
  5586.     EXPECT
  5587.         CASE (ALIGN_LEFT_TOKEN)
  5588. #ifdef UnofficialBlocking
  5589.        parseUnofficialFeature(30);
  5590. #endif
  5591.             position =0;
  5592.         END_CASE
  5593.         CASE(ALIGN_RIGHT_TOKEN)
  5594. #ifdef UnofficialBlocking
  5595.        parseUnofficialFeature(30);
  5596. #endif
  5597.             position = 2;
  5598.         END_CASE
  5599.         CASE(ALIGN_CENTER_TOKEN)
  5600. #ifdef UnofficialBlocking
  5601.        parseUnofficialFeature(30);
  5602. #endif
  5603.             position = 1;
  5604.         END_CASE
  5605.         CASE (POSITION_TOKEN)
  5606. #ifdef UnofficialBlocking
  5607.        parseUnofficialFeature(30);
  5608. #endif
  5609.             position = Parse_Float();
  5610.         END_CASE
  5611.          OTHERWISE
  5612.            UNGET
  5613.        EXIT
  5614.      END_CASE
  5615.    END_EXPECT
  5616.  
  5617.    /* Process all this good info */
  5618.    ProcessNewTTF((OBJECT *)Object, filename, text_string, depth, offset, position );
  5619. #else
  5620.    /* Process all this good info */
  5621.    ProcessNewTTF((OBJECT *)Object, filename, text_string, depth, offset);
  5622. #endif
  5623.  
  5624.    /* Free up the filename and text string memory */
  5625.    POV_FREE (filename);
  5626.    POV_FREE (text_string);
  5627.  
  5628.    /**** Compute_TTF_BBox(Object); */
  5629.    Compute_CSG_BBox((OBJECT *)Object);
  5630.  
  5631. /* This tiny rotation should fix cracks in text that lies along an axis */
  5632.    Make_Vector(offset, 0.001, 0.001, 0.001);
  5633.    Compute_Rotation_Transform(&Local_Trans, offset);
  5634.    Rotate_Object ((OBJECT *)Object, offset, &Local_Trans);
  5635.  
  5636.    /* Get any rotate/translate or texturing stuff */
  5637.    Parse_Object_Mods ((OBJECT *)Object);
  5638.  
  5639.    return ((OBJECT *) Object);
  5640.   }
  5641.  
  5642.  
  5643. /*****************************************************************************
  5644. *
  5645. * FUNCTION
  5646. *
  5647. *       Parse_Sphere_Sweep
  5648. *
  5649. * INPUT
  5650. *
  5651. *   -
  5652. *
  5653. * OUTPUT
  5654. *
  5655. *   -
  5656. *
  5657. * RETURNS
  5658. *
  5659. *   Object
  5660. *
  5661. * AUTHOR
  5662. *
  5663. *       Jochen Lippert
  5664. *
  5665. * DESCRIPTION
  5666. *
  5667. * CHANGES
  5668. *
  5669. ******************************************************************************/
  5670.  
  5671. static OBJECT *Parse_Sphere_Sweep()
  5672. {
  5673.     SPHERE_SWEEP    *Object;
  5674.     int                             i;
  5675.     
  5676.     Parse_Begin();
  5677.     
  5678.     if ((Object = (SPHERE_SWEEP *)Parse_Object_Id()) != NULL)
  5679.     {
  5680.         return ((OBJECT *) Object);
  5681.     }
  5682.     
  5683.     Object = Create_Sphere_Sweep();
  5684.     
  5685.     /* Get type of interpolation */
  5686.     EXPECT
  5687.         CASE(LINEAR_SPHERE_SWEEP_TOKEN)
  5688.             Object->Interpolation = LINEAR_SPHERE_SWEEP;
  5689.             EXIT
  5690.         END_CASE
  5691.         CASE(CATMULL_ROM_SPLINE_SPHERE_SWEEP_TOKEN)
  5692.             Object->Interpolation = CATMULL_ROM_SPLINE_SPHERE_SWEEP;
  5693.             EXIT
  5694.         END_CASE
  5695.         CASE(B_SPLINE_SPHERE_SWEEP_TOKEN)
  5696.             Object->Interpolation = B_SPLINE_SPHERE_SWEEP;
  5697.             EXIT
  5698.         END_CASE
  5699.         OTHERWISE
  5700.             UNGET
  5701.             EXIT
  5702.         END_CASE
  5703.     END_EXPECT
  5704.     
  5705.     if (Object->Interpolation == -1)
  5706.     {
  5707.         Error("Invalid type of interpolation.");
  5708.     }
  5709.     
  5710.     Parse_Comma();
  5711.     
  5712.     /* Get number of modeling spheres */
  5713.     Object->Num_Modeling_Spheres = (int)Parse_Float();
  5714.     
  5715.     Object->Modeling_Sphere =
  5716.         (SPHSWEEP_SPH *)POV_MALLOC(Object->Num_Modeling_Spheres * sizeof(SPHSWEEP_SPH),
  5717.         "sphere sweep modeling spheres");
  5718.     
  5719.     for (i = 0; i < Object->Num_Modeling_Spheres; i++)
  5720.     {
  5721.         Parse_Comma();
  5722.         Parse_Vector(Object->Modeling_Sphere[i].Center);
  5723.         Parse_Comma();
  5724.         Object->Modeling_Sphere[i].Radius = Parse_Float();
  5725.     }
  5726.     
  5727.     EXPECT
  5728.         CASE(SPHERE_SWEEP_DEPTH_TOLERANCE_TOKEN)
  5729.             Object->Depth_Tolerance = Parse_Float();
  5730.             EXIT
  5731.         END_CASE
  5732.         OTHERWISE
  5733.             UNGET
  5734.             EXIT
  5735.         END_CASE
  5736.     END_EXPECT
  5737.     
  5738.     Compute_Sphere_Sweep(Object);
  5739.     
  5740.     Compute_Sphere_Sweep_BBox(Object);
  5741.     
  5742.     Parse_Object_Mods((OBJECT *)Object);
  5743.     
  5744.     return ((OBJECT *)Object);
  5745. }
  5746.  
  5747.  
  5748. /*****************************************************************************
  5749. *
  5750. * FUNCTION
  5751. *
  5752. * INPUT
  5753. *   
  5754. * OUTPUT
  5755. *   
  5756. * RETURNS
  5757. *   
  5758. * AUTHOR
  5759. *   
  5760. * DESCRIPTION
  5761. *
  5762. * CHANGES
  5763. *
  5764. ******************************************************************************/
  5765.  
  5766. static
  5767. OBJECT *Parse_CSG (int CSG_Type)
  5768. {
  5769.    CSG *Object;
  5770.    OBJECT *Local;
  5771.    int Object_Count = 0;
  5772.    int Light_Source_Union = TRUE;
  5773.  
  5774.    Parse_Begin ();
  5775.    if ( (Object = (CSG *)Parse_Object_Id()) != NULL)
  5776.       return ((OBJECT *) Object);
  5777.    if (CSG_Type & CSG_UNION_TYPE)
  5778.      Object = Create_CSG_Union ();
  5779.    else
  5780.      if (CSG_Type & CSG_MERGE_TYPE)
  5781.        Object = Create_CSG_Merge ();
  5782.      else
  5783.        Object = Create_CSG_Intersection ();
  5784.  
  5785.    Object->Children = NULL;
  5786.  
  5787.    while ((Local = Parse_Object ()) != NULL)
  5788.      {
  5789.  
  5790.       if ((CSG_Type & CSG_INTERSECTION_TYPE) && (Local->Type & PATCH_OBJECT))
  5791.         Warn(0, "Patch objects not allowed in intersection.");
  5792.       Object_Count++;
  5793.       if ((CSG_Type & CSG_DIFFERENCE_TYPE) && (Object_Count > 1))
  5794.         Invert_Object (Local);
  5795.       Object->Type |=  (Local->Type & CHILDREN_FLAGS);
  5796.       if (!(Local->Type & LIGHT_SOURCE_OBJECT))
  5797.       {
  5798.          Light_Source_Union = FALSE;
  5799.       }
  5800.       Local->Type |= IS_CHILD_OBJECT;
  5801.       Link(Local, &Local->Sibling, &Object->Children);
  5802.      };
  5803.  
  5804.  
  5805.    if (Light_Source_Union)
  5806.    {
  5807.      Object->Type |= LT_SRC_UNION_OBJECT;
  5808.    }
  5809.    
  5810.    if ((Object_Count < 2) && (opts.Language_Version >= 150))
  5811.      Warn(150, "Should have at least 2 objects in csg.");
  5812.  
  5813.  
  5814.        Compute_CSG_BBox((OBJECT *)Object);
  5815.  
  5816.    Parse_Object_Mods ((OBJECT *)Object);
  5817.  
  5818.    return ((OBJECT *) Object);
  5819.   }
  5820.  
  5821.  
  5822.  
  5823. /*****************************************************************************
  5824. *
  5825. * FUNCTION
  5826. *
  5827. * INPUT
  5828. *
  5829. * OUTPUT
  5830. *
  5831. * RETURNS
  5832. *
  5833. * AUTHOR
  5834. *
  5835. * DESCRIPTION
  5836. *
  5837. * CHANGES
  5838. *
  5839. ******************************************************************************/
  5840.  
  5841. static OBJECT *Parse_Light_Source ()
  5842. {
  5843.    DBL Len;
  5844.    VECTOR Local_Vector;
  5845.    MATRIX Local_Matrix;
  5846.    TRANSFORM Local_Trans;
  5847.    LIGHT_SOURCE *Object;
  5848.    /* NK phmap */
  5849.    BLEND_MAP *Map;
  5850.    SNGL Value;
  5851.    int i;
  5852.    /* NK ---- */
  5853.  
  5854.    Parse_Begin ();
  5855.  
  5856.    if ( (Object = (LIGHT_SOURCE *)Parse_Object_Id()) != NULL)
  5857.       return ((OBJECT *) Object);
  5858.       
  5859.    Object = Create_Light_Source ();
  5860.  
  5861.    Parse_Vector(Object->Center);
  5862.  
  5863.    Parse_Comma();
  5864.  
  5865.    Parse_Colour (Object->Colour);
  5866.  
  5867.    EXPECT
  5868.      /* NK phmap */
  5869.      CASE (COLOUR_MAP_TOKEN)
  5870. #ifdef UnofficialBlocking
  5871.        parseUnofficialFeature(30);
  5872. #endif
  5873.        Destroy_Blend_Map(Object->blend_map);
  5874.        Map = Object->blend_map = Parse_Colour_Map ();
  5875.  
  5876.        Make_Colour(Object->Colour, 0, 0, 0);
  5877.        for (i = 0; i < Map->Number_Of_Entries; i++)
  5878.        {
  5879.          Value = Map->Blend_Map_Entries[i].value;
  5880.          VAddScaledEq(Object->Colour,Value,Map->Blend_Map_Entries[i].Vals.Colour);
  5881.        }
  5882.      END_CASE
  5883.  
  5884.      CASE(PHOTONS_TOKEN)
  5885.        Parse_Begin();
  5886.        EXPECT
  5887.          CASE(GLOBAL_TOKEN)
  5888.            Object->Ph_Density = Allow_Float(1.0);
  5889.            if (Object->Ph_Density > 0)
  5890.            {
  5891.              Object->Ph_Flags |= PH_FLAG_TARGET;
  5892.              /*CheckPassThru(Object, PH_FLAG_TARGET);*/
  5893.            }
  5894.            else
  5895.            {
  5896.              Object->Ph_Flags &= ~PH_FLAG_TARGET;
  5897.            }
  5898.          END_CASE
  5899.  
  5900.          CASE(REFRACTION_TOKEN)
  5901.            if((int)Parse_Float())
  5902.            { SET_PH_FLAG(Object, PH_FLAG_RFR_ON, PH_FLAG_RFR_OFF); }
  5903.            else
  5904.            { CLEAR_PH_FLAG(Object, PH_FLAG_RFR_ON, PH_FLAG_RFR_OFF); }
  5905.          END_CASE
  5906.  
  5907.          CASE(REFLECTION_TOKEN)
  5908.            if((int)Parse_Float())
  5909.            { SET_PH_FLAG(Object, PH_FLAG_RFL_ON, PH_FLAG_RFL_OFF); }
  5910.            else
  5911.            { CLEAR_PH_FLAG(Object, PH_FLAG_RFL_ON, PH_FLAG_RFL_OFF); }
  5912.          END_CASE
  5913.  
  5914.          CASE (AREA_LIGHT_TOKEN)
  5915.            Object->Photon_Area_Light = TRUE;
  5916.          END_CASE
  5917.  
  5918.          OTHERWISE
  5919.            UNGET
  5920.            EXIT
  5921.          END_CASE
  5922.        END_EXPECT
  5923.        Parse_End();
  5924.      END_CASE
  5925.  
  5926.      /* NK ---- */
  5927.  
  5928. #ifdef GlowPatch
  5929.     CASE(GLOW_TOKEN)
  5930.     {
  5931.         GLOW * NewGlow = NULL;
  5932.         #ifdef UnofficialBlocking
  5933.            parseUnofficialFeature(60);
  5934.         #endif    
  5935.         NewGlow = Create_Glow();
  5936.         Assign_Colour(NewGlow->Colour, Object->Colour);
  5937.         Assign_Vector(NewGlow->Center, Object->Center);
  5938.         Parse_Glow(NewGlow);
  5939.         Add_Glow(NewGlow);/*Add glow to Frame*/
  5940.         /*Add glow to list of glow pointers in object*/
  5941.     if(Object->glowList == NULL)
  5942.     {   Object->glowList =(GLOW**) POV_MALLOC(sizeof(GLOW_PTR), "glow pointer array");}
  5943.     else
  5944.     {
  5945.         GLOW_PTR * newGlowList =(GLOW**) POV_MALLOC((Object->numOfGlows+2)*sizeof(GLOW_PTR), "glow pointer array");
  5946.         memcpy(newGlowList, Object->glowList, (Object->numOfGlows+1)*sizeof(GLOW_PTR));
  5947.         POV_FREE(Object->glowList);
  5948.         Object->glowList = newGlowList;
  5949.     }
  5950.         Object->glowList[Object->numOfGlows] = NewGlow;
  5951.         Object->numOfGlows++;
  5952.     }
  5953.     END_CASE
  5954. #endif
  5955.  
  5956.      CASE (LOOKS_LIKE_TOKEN)
  5957.        if (Object->Children != NULL)
  5958.          Error("Only one looks_like allowed per light_source.");
  5959.        Parse_Begin ();
  5960.        Object->Type &= ~(int)PATCH_OBJECT;
  5961.        if ((Object->Children = Parse_Object ()) == NULL)
  5962.          Parse_Error_Str ("object");
  5963.        Compute_Translation_Transform(&Local_Trans, Object->Center);
  5964.        Translate_Object (Object->Children, Object->Center, &Local_Trans);
  5965.        Parse_Object_Mods (Object->Children);
  5966.        Set_Flag(Object->Children, NO_SHADOW_FLAG);
  5967.        Set_Flag(Object, NO_SHADOW_FLAG);
  5968.        Object->Children->No_Shadow_Group=ALL_GROUP;
  5969.        Object->Type |= (Object->Children->Type & CHILDREN_FLAGS);
  5970.        /* NK phmap 2000-may-10 */
  5971.        Object->Ph_Flags |= PH_FLAG_PASSTHRU;
  5972.        /* NK ---- */
  5973.      END_CASE
  5974.  
  5975.      CASE (PROJECTED_THROUGH_TOKEN)
  5976.        if (Object->Projected_Through_Object != NULL)
  5977.          Error("Only one projected through allowed per light_source.");
  5978.        Parse_Begin ();
  5979.        Object->Type &= ~(int)PATCH_OBJECT;
  5980.        if ((Object->Projected_Through_Object = Parse_Object ()) == NULL)
  5981.          Parse_Error_Str ("object");
  5982.        Parse_Object_Mods (Object->Projected_Through_Object);
  5983.        Set_Flag(Object, NO_SHADOW_FLAG);
  5984.        /* NK phmap 2000-may-10 */
  5985.        Object->Ph_Flags |= PH_FLAG_PASSTHRU;
  5986.        /* NK ---- */
  5987.      END_CASE
  5988.  
  5989.      CASE (FILL_LIGHT_TOKEN)
  5990.        Object->Light_Type = FILL_LIGHT_SOURCE;
  5991.      END_CASE
  5992.  
  5993.         CASE (GROUPS_TOKEN)
  5994.     {
  5995.         /*YS sept 17 2000 Memory leak */
  5996.         char *tempstring=Parse_String();
  5997.        Assign_Light_Groups(Object,tempstring);
  5998.       POV_FREE(tempstring); /*YS sept 17 Memory leak */
  5999.      }
  6000.      END_CASE
  6001.  
  6002.         CASE (PARALLEL_TOKEN)
  6003.        Object->Parallel= TRUE;
  6004.      END_CASE
  6005.  
  6006.      CASE (SPOTLIGHT_TOKEN)
  6007.        Object->Light_Type = SPOT_SOURCE;
  6008.      END_CASE
  6009.  
  6010.      CASE (CYLINDER_TOKEN)
  6011.        Object->Light_Type = CYLINDER_SOURCE;
  6012.      END_CASE
  6013.  
  6014.      CASE (POINT_AT_TOKEN)
  6015.        if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE)
  6016.             || Object->Parallel)
  6017.          Parse_Vector(Object->Points_At);
  6018.        else
  6019.          Not_With ("point_at","standard light source");
  6020.      END_CASE
  6021.  
  6022.      CASE (TIGHTNESS_TOKEN)
  6023.        if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE))
  6024.          Object->Coeff = Parse_Float();
  6025.        else
  6026.          Not_With ("tightness","standard light source");
  6027.      END_CASE
  6028.  
  6029.      CASE (RADIUS_TOKEN)
  6030.        if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE))
  6031.          Object->Radius = Parse_Float();
  6032.        else
  6033.          Not_With ("radius","standard light source");
  6034.      END_CASE
  6035.  
  6036.      CASE (FALLOFF_TOKEN)
  6037.        if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE))
  6038.          Object->Falloff = Parse_Float();
  6039.        else
  6040.          Not_With ("falloff","standard light source");
  6041.      END_CASE
  6042.  
  6043.      CASE (FADE_DISTANCE_TOKEN)
  6044.        Object->Fade_Distance = Parse_Float();
  6045.      END_CASE
  6046.  
  6047.      CASE (FADE_POWER_TOKEN)
  6048.        Object->Fade_Power = Parse_Float();
  6049.      END_CASE
  6050.  
  6051.      CASE (AREA_LIGHT_TOKEN)
  6052.        Object->Area_Light = TRUE;
  6053.        Parse_Vector (Object->Axis1); Parse_Comma ();
  6054.        Parse_Vector (Object->Axis2); Parse_Comma ();
  6055.        Object->Area_Size1 = (int)Parse_Float(); Parse_Comma ();
  6056.        Object->Area_Size2 = (int)Parse_Float();
  6057.        Object->Light_Grid = Create_Light_Grid (Object->Area_Size1, Object->Area_Size2);
  6058.      END_CASE
  6059.  
  6060. #ifdef CircularOrientAreaLightPatch 
  6061.     /* Orient area lights to the point [ENB 9/97] */
  6062.      CASE (AREA_LIGHT_ORIENT_TOKEN)
  6063. #ifdef UnofficialBlocking
  6064.        parseUnofficialFeature(30);
  6065. #endif
  6066.          Object->Orient =Object->CircularOrient= TRUE;
  6067.      END_CASE
  6068.  
  6069.      /* Circular area lights [ENB 9/97] */
  6070.      CASE (AREA_LIGHT_CIRCULAR_TOKEN)
  6071. #ifdef UnofficialBlocking
  6072.        parseUnofficialFeature(30);
  6073. #endif
  6074.        Object->Circular = Object->CircularOrient=TRUE;
  6075.      END_CASE
  6076. #endif
  6077.  
  6078.      CASE (JITTER_TOKEN)
  6079.        Object->Jitter = TRUE;
  6080.      END_CASE
  6081.  
  6082.      CASE (TRACK_TOKEN)
  6083.        Object->Track = TRUE;
  6084.      END_CASE
  6085.  
  6086.      CASE (ADAPTIVE_TOKEN)
  6087.        Object->Adaptive_Level = (int)Parse_Float();
  6088.      END_CASE
  6089.  
  6090.      CASE (MEDIA_ATTENUATION_TOKEN)
  6091.        Object->Media_Attenuation = Allow_Float(1.0) > 0.0;
  6092.      END_CASE
  6093.  
  6094.      CASE (MEDIA_INTERACTION_TOKEN)
  6095.        Object->Media_Interaction = Allow_Float(1.0) > 0.0;
  6096.      END_CASE
  6097.  
  6098.      CASE (TRANSLATE_TOKEN)
  6099.        Parse_Vector (Local_Vector);
  6100.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  6101.        Translate_Object ((OBJECT *)Object, Local_Vector, &Local_Trans);
  6102.      END_CASE
  6103.  
  6104.      CASE (ROTATE_TOKEN)
  6105.        Parse_Vector (Local_Vector);
  6106.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  6107.        Rotate_Object ((OBJECT *)Object, Local_Vector, &Local_Trans);
  6108.      END_CASE
  6109.  
  6110.      CASE (SCALE_TOKEN)
  6111.        Parse_Scale_Vector (Local_Vector);
  6112.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  6113.        Scale_Object ((OBJECT *)Object, Local_Vector, &Local_Trans);
  6114.      END_CASE
  6115.  
  6116.      CASE (TRANSFORM_TOKEN)
  6117. #ifndef TransformPatch /* Chris Huff april 2000 */
  6118.      GET(TRANSFORM_ID_TOKEN)
  6119.        Transform_Object ((OBJECT *)Object, (TRANSFORM *)Token.Data);
  6120. #else
  6121.        {
  6122.            TRANSFORM * Trans = Parse_Transform();
  6123.            Transform_Object((OBJECT *)Object, Trans);
  6124.             /*YS sept 17 2000 Memory leak*/
  6125.                 POV_FREE(Trans);
  6126.        }
  6127. #endif
  6128.      END_CASE
  6129.  
  6130.      CASE (MATRIX_TOKEN)
  6131.        Parse_Matrix (Local_Matrix);
  6132.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  6133.        Transform_Object ((OBJECT *)Object, &Local_Trans);
  6134.      END_CASE
  6135.  
  6136.      OTHERWISE
  6137.        UNGET
  6138.        EXIT
  6139.      END_CASE
  6140.    END_EXPECT
  6141.  
  6142.    Parse_End ();
  6143.  
  6144.    if (Object->Light_Type == SPOT_SOURCE)
  6145.    {
  6146.      Object->Radius  = cos(Object->Radius * M_PI_180);
  6147.      Object->Falloff = cos(Object->Falloff * M_PI_180);
  6148.    }
  6149.  
  6150.    VSub(Object->Direction, Object->Points_At, Object->Center);
  6151.  
  6152.    VLength(Len, Object->Direction);
  6153.  
  6154.    if (Len > EPSILON)
  6155.    {
  6156.      VInverseScaleEq(Object->Direction, Len);
  6157.    }
  6158.  
  6159.    return ((OBJECT *)Object);
  6160.   }
  6161.  
  6162.  
  6163.  
  6164. /*****************************************************************************
  6165. *
  6166. * FUNCTION
  6167. *
  6168. * INPUT
  6169. *   
  6170. * OUTPUT
  6171. *   
  6172. * RETURNS
  6173. *   
  6174. * AUTHOR
  6175. *   
  6176. * DESCRIPTION
  6177. *
  6178. * CHANGES
  6179. *
  6180. ******************************************************************************/
  6181.  
  6182. #ifdef CreateLabelPatch
  6183. /* NK persist create */
  6184. char* createObjectName;
  6185. /* NK ---- */
  6186. #endif
  6187.  
  6188. OBJECT *Parse_Object ()
  6189. {
  6190. #ifdef CreateLabelPatch
  6191.    /* NK persist create Nov 1999 */
  6192.    char *localObjectName;
  6193.    /* ---- */
  6194. #endif
  6195.  
  6196.    OBJECT *Object = NULL;
  6197.  
  6198. #ifdef CreateLabelPatch
  6199.    /* NK persist create Nov 1999 */
  6200.    localObjectName = createObjectName;
  6201.    createObjectName = NULL;
  6202.    /* ---- */
  6203. #endif
  6204.  
  6205.    EXPECT
  6206.  
  6207.      CASE (JULIA_FRACTAL_TOKEN)
  6208.        Object = Parse_Julia_Fractal ();
  6209.        EXIT
  6210.      END_CASE
  6211.  
  6212.      CASE (SPHERE_TOKEN)
  6213.        Object = Parse_Sphere ();
  6214.        EXIT
  6215.      END_CASE
  6216.  
  6217. /** poviso: '96 O. & R.S. **/
  6218. #ifdef POVISO
  6219.      CASE (PARAMETRIC_TOKEN)
  6220. #ifdef UnofficialBlocking
  6221.        parseUnofficialFeature(10);
  6222. #endif
  6223.        Object = Parse_Parametric();
  6224.        EXIT
  6225.      END_CASE
  6226.  
  6227.      CASE (ISOSURFACE_TOKEN)
  6228. #ifdef UnofficialBlocking
  6229.        parseUnofficialFeature(10);
  6230. #endif
  6231.       Object = Parse_IsoSurface (PARSE_IMPFUN);
  6232.        EXIT
  6233.      END_CASE
  6234. #endif
  6235. /** --- **/
  6236.  
  6237.      /* Sphere sweep support */
  6238.      CASE (SPHERE_SWEEP_TOKEN)
  6239.        Object = Parse_Sphere_Sweep ();
  6240.        EXIT
  6241.      END_CASE
  6242.  
  6243.      CASE (PLANE_TOKEN)
  6244.        Object = Parse_Plane ();
  6245.        EXIT
  6246.      END_CASE
  6247.  
  6248.      CASE (CONE_TOKEN)
  6249.        Object = Parse_Cone ();
  6250.        EXIT
  6251.      END_CASE
  6252.  
  6253.      CASE (CYLINDER_TOKEN)
  6254.        Object = Parse_Cylinder ();
  6255.        EXIT
  6256.      END_CASE
  6257.  
  6258.      CASE (DISC_TOKEN)
  6259.        Object = Parse_Disc ();
  6260.        EXIT
  6261.      END_CASE
  6262.  
  6263.      CASE (QUADRIC_TOKEN)
  6264.        Object = Parse_Quadric ();
  6265.        EXIT
  6266.      END_CASE
  6267.  
  6268.      CASE (CUBIC_TOKEN)
  6269.        Object = Parse_Poly (3);
  6270.        EXIT
  6271.      END_CASE
  6272.  
  6273.      CASE (QUARTIC_TOKEN)
  6274.        Object = Parse_Poly (4);
  6275.        EXIT
  6276.      END_CASE
  6277.  
  6278.      CASE (POLY_TOKEN)
  6279.        Object = Parse_Poly (0);
  6280.        EXIT
  6281.      END_CASE
  6282.  
  6283.      CASE (TORUS_TOKEN)
  6284.        Object = Parse_Torus ();
  6285.        EXIT
  6286.      END_CASE
  6287.  
  6288.      /* Parse lathe primitive. [DB 8/94] */
  6289.  
  6290.      CASE (LATHE_TOKEN)
  6291.        Object = Parse_Lathe();
  6292.        EXIT
  6293.      END_CASE
  6294.  
  6295.      /* Parse polygon primitive. [DB 8/94] */
  6296.  
  6297.      CASE (POLYGON_TOKEN)
  6298.        Object = Parse_Polygon();
  6299.        EXIT
  6300.      END_CASE
  6301.  
  6302.      /* Parse prism primitive. [DB 8/94] */
  6303.  
  6304.      CASE (PRISM_TOKEN)
  6305.        Object = Parse_Prism();
  6306.        EXIT
  6307.      END_CASE
  6308.  
  6309.      /* Parse surface of revolution primitive. [DB 8/94] */
  6310.  
  6311.      CASE (SOR_TOKEN)
  6312.        Object = Parse_Sor();
  6313.        EXIT
  6314.      END_CASE
  6315.  
  6316.      /* Parse superellipsoid primitive. [DB 11/94] */
  6317.  
  6318.      CASE (SUPERELLIPSOID_TOKEN)
  6319.        Object = Parse_Superellipsoid();
  6320.        EXIT
  6321.      END_CASE
  6322.  
  6323.      /* Parse triangle mesh primitive. [DB 2/95] */
  6324.  
  6325.      CASE (MESH_TOKEN)
  6326.        Object = Parse_Mesh();
  6327.        EXIT
  6328.      END_CASE
  6329.  
  6330.      /* NK 1998 Parse triangle mesh primitive - syntax version 2. */
  6331.      CASE (MESH2_TOKEN)
  6332. #ifdef UnofficialBlocking
  6333.        parseUnofficialFeature(30);
  6334. #endif
  6335.        Object = Parse_Mesh2();
  6336.        EXIT
  6337.      END_CASE
  6338.      /* NK ---- */
  6339.  
  6340.      CASE (TEXT_TOKEN)
  6341.        Object = Parse_TrueType ();
  6342.        EXIT
  6343.      END_CASE
  6344.  
  6345.      CASE (OBJECT_ID_TOKEN)
  6346.        Object = Copy_Object((OBJECT *) Token.Data);
  6347.        EXIT
  6348.      END_CASE
  6349.  
  6350.      CASE (UNION_TOKEN)
  6351.        Object = Parse_CSG (CSG_UNION_TYPE);
  6352.        EXIT
  6353.      END_CASE
  6354.  
  6355.      CASE (COMPOSITE_TOKEN)
  6356.        Warn(150, "Use union instead of composite.");
  6357.        Object = Parse_CSG (CSG_UNION_TYPE);
  6358.        EXIT
  6359.      END_CASE
  6360.  
  6361.      CASE (MERGE_TOKEN)
  6362.        Object = Parse_CSG (CSG_MERGE_TYPE);
  6363.        EXIT
  6364.      END_CASE
  6365.  
  6366.      CASE (INTERSECTION_TOKEN)
  6367.        Object = Parse_CSG (CSG_INTERSECTION_TYPE);
  6368.        EXIT
  6369.      END_CASE
  6370.  
  6371.      CASE (DIFFERENCE_TOKEN)
  6372.        Object = Parse_CSG (CSG_DIFFERENCE_TYPE+CSG_INTERSECTION_TYPE);
  6373.        EXIT
  6374.      END_CASE
  6375.  
  6376.      CASE (BICUBIC_PATCH_TOKEN)
  6377.        Object = Parse_Bicubic_Patch ();
  6378.        EXIT
  6379.      END_CASE
  6380.  
  6381. #ifdef RBezierPatch
  6382.      CASE (BEZIER_PATCH_TOKEN)
  6383. #ifdef UnofficialBlocking
  6384.        parseUnofficialFeature(30);
  6385. #endif
  6386.        Object = Parse_RBezier_Patch ();
  6387.        EXIT
  6388.      END_CASE
  6389. #endif
  6390.  
  6391.      CASE (TRIANGLE_TOKEN)
  6392.        Object = Parse_Triangle ();
  6393.        EXIT
  6394.      END_CASE
  6395.  
  6396.      CASE (SMOOTH_TRIANGLE_TOKEN)
  6397.        Object = Parse_Smooth_Triangle ();
  6398.        EXIT
  6399.      END_CASE
  6400.  
  6401.      CASE (HEIGHT_FIELD_TOKEN)
  6402.        Object = Parse_HField ();
  6403.        EXIT
  6404.      END_CASE
  6405.  
  6406.      CASE (BOX_TOKEN)
  6407.        Object = Parse_Box ();
  6408.        EXIT
  6409.      END_CASE
  6410.  
  6411.      CASE (BLOB_TOKEN)
  6412.      #ifdef BlobPatternPatch
  6413.        Object = Parse_Blob ();
  6414.      #else
  6415.        Object = Parse_Blob ();
  6416.     #endif     
  6417.        EXIT
  6418.      END_CASE
  6419.  
  6420. #ifdef IsoBlobPatch
  6421.     /* Lummox JR, July 1999 */
  6422.      CASE (ISOBLOB_TOKEN)
  6423. #ifdef UnofficialBlocking
  6424.        parseUnofficialFeature(30);
  6425. #endif
  6426.        Object = Parse_Isoblob ();
  6427.        EXIT
  6428.      END_CASE
  6429.     /* end Lummox JR's additions */
  6430. #endif
  6431.  
  6432.      CASE (LIGHT_SOURCE_TOKEN)
  6433.        Object = Parse_Light_Source ();
  6434.        EXIT
  6435.      END_CASE
  6436.  
  6437. #ifdef MotionBlurPatch
  6438.      CASE (MOTION_BLUR_TOKEN)
  6439. #ifdef UnofficialBlocking
  6440.        parseUnofficialFeature(30);
  6441. #endif
  6442.        Object = Parse_Motion_Blur();
  6443.        parsedMotionBlurObject = TRUE;
  6444.        EXIT
  6445.      END_CASE
  6446.  
  6447. #endif
  6448.      CASE (OBJECT_TOKEN)
  6449.        Parse_Begin ();
  6450.        Object = Parse_Object ();
  6451.        if (!Object)
  6452.          Parse_Error_Str ("object");
  6453.        Parse_Object_Mods ((OBJECT *)Object);
  6454.        EXIT
  6455.      END_CASE
  6456.  
  6457.      OTHERWISE
  6458.        UNGET
  6459.        EXIT
  6460.      END_CASE
  6461.    END_EXPECT
  6462.  
  6463. #ifdef CreateLabelPatch
  6464.    /* NK persist create Nov 1999 */
  6465.    if(Object!=NULL && localObjectName!=NULL)
  6466.    {
  6467.      if((OBJECT *)Object->Label!=NULL)
  6468.        POV_FREE(((OBJECT *)Object)->Label);
  6469.    
  6470.      ((OBJECT *)Object)->Label = localObjectName;
  6471.    }
  6472.    /* ---- */
  6473. #endif
  6474.  
  6475.    return ((OBJECT *) Object);
  6476.   }
  6477.   
  6478.  
  6479.  
  6480. /*****************************************************************************
  6481. *
  6482. * FUNCTION
  6483. *
  6484. * INPUT
  6485. *   
  6486. * OUTPUT
  6487. *   
  6488. * RETURNS
  6489. *   
  6490. * AUTHOR
  6491. *   
  6492. * DESCRIPTION
  6493. *
  6494. * CHANGES
  6495. *
  6496. ******************************************************************************/
  6497.  
  6498. void Parse_Default ()
  6499. {
  6500.    TEXTURE *Local_Texture;
  6501.    PIGMENT *Local_Pigment;
  6502.    TNORMAL *Local_Tnormal;
  6503.    FINISH  *Local_Finish;
  6504.  
  6505.    Not_In_Default = FALSE;
  6506.    Parse_Begin();
  6507.  
  6508.    EXPECT
  6509.      CASE (TEXTURE_TOKEN)
  6510.        Local_Texture = Default_Texture;
  6511.        Parse_Begin ();
  6512.        Default_Texture = Parse_Texture();
  6513.        Parse_End ();
  6514.        if (Default_Texture->Type != PLAIN_PATTERN)
  6515.          Error("Default texture cannot be material map or tiles.");
  6516.        if (Default_Texture->Next != NULL)
  6517.          Error("Default texture cannot be layered.");
  6518.        Destroy_Textures(Local_Texture);
  6519.      END_CASE
  6520.  
  6521.      CASE (PIGMENT_TOKEN)
  6522.        Local_Pigment = Copy_Pigment((Default_Texture->Pigment));
  6523.        Parse_Begin ();
  6524.        Parse_Pigment (&Local_Pigment);
  6525.        Parse_End ();
  6526.        Destroy_Pigment(Default_Texture->Pigment);
  6527.        Default_Texture->Pigment = Local_Pigment;
  6528.      END_CASE
  6529.  
  6530.      CASE (TNORMAL_TOKEN)
  6531.        Local_Tnormal = Copy_Tnormal((Default_Texture->Tnormal));
  6532.        Parse_Begin ();
  6533.        Parse_Tnormal (&Local_Tnormal);
  6534.        Parse_End ();
  6535.        Destroy_Tnormal(Default_Texture->Tnormal);
  6536.        Default_Texture->Tnormal = Local_Tnormal;
  6537.      END_CASE
  6538.  
  6539.      CASE (FINISH_TOKEN)
  6540.        Local_Finish = Copy_Finish((Default_Texture->Finish));
  6541.        Parse_Finish (&Local_Finish);
  6542.        Destroy_Finish(Default_Texture->Finish);
  6543.        Default_Texture->Finish = Local_Finish;
  6544.      END_CASE
  6545.  
  6546.      CASE (CAMERA_TOKEN)
  6547.        Parse_Camera (&Default_Camera);
  6548.      END_CASE
  6549.  
  6550.      OTHERWISE
  6551.        UNGET
  6552.        EXIT
  6553.      END_CASE
  6554.    END_EXPECT
  6555.  
  6556.    Parse_End();
  6557.  
  6558.    Not_In_Default = TRUE;
  6559. }
  6560.  
  6561. #ifdef BsplinePatch
  6562. /*****************************************************************************
  6563. *
  6564. * FUNCTION
  6565. *
  6566. *   Parse_Init_Spline
  6567. *
  6568. * INPUT
  6569. *   
  6570. * OUTPUT
  6571. *   
  6572. * RETURNS
  6573. *   
  6574. * AUTHOR
  6575. *
  6576. *   Daniel Fenner
  6577. *
  6578. * DESCRIPTION
  6579. *
  6580. *   Parse a new spline and compute the coefficients
  6581. *
  6582. * CHANGES
  6583. *
  6584. *   3-98 Creation
  6585. *
  6586. ******************************************************************************/
  6587.  
  6588.  
  6589. void Parse_Init_Spline()
  6590. {
  6591.     char   *name;
  6592.     DBL    tv1,tv2;
  6593.     VECTOR tv;
  6594.     int    is_first=TRUE,nr_of_knots=0,type=NATURAL_SPLINE,does_exist=FALSE;
  6595.     DBL    last_knot;
  6596.     
  6597.     SPLINE  *help;
  6598.     SPLINE_STACK_1D *base=NULL,*New=NULL,*New1=NULL;
  6599.  
  6600.     
  6601.     Parse_Begin ();
  6602.  
  6603.     name = Parse_String();
  6604.     
  6605.     /* does already exist ??? */
  6606.     if (The_Splines!=NULL)
  6607.     {
  6608.         help=The_Splines;
  6609.         if (strcmp(help->name,name)==0) does_exist=TRUE;
  6610.         while (help->next!=NULL)
  6611.         {
  6612.             help=(SPLINE*)help->next;
  6613.             if (strcmp(help->name,name)==0) does_exist=TRUE;
  6614.         }
  6615.         if (does_exist) Error("Spline named %s does already exist.",name);
  6616.     }
  6617.  
  6618.     
  6619.     Parse_Comma();
  6620.  
  6621.     EXPECT
  6622.       CASE (SPLINE_CLOSED_TOKEN)
  6623.         type = CLOSED_SPLINE;
  6624.         GET (EQUALS_TOKEN);
  6625.         tv1 = Parse_Float();
  6626.         Parse_Comma();
  6627.       END_CASE
  6628.  
  6629.       CASE (SPLINE_DIRECTION_TOKEN)
  6630.         type = DIRECTION_SPLINE;
  6631.         GET (EQUALS_TOKEN);
  6632.         tv1 = Parse_Float();
  6633.         Parse_Comma();
  6634.         tv2 = Parse_Float();
  6635.         Parse_Comma();
  6636.       END_CASE
  6637.  
  6638.       CASE (SPLINE_NATURAL_TOKEN)
  6639.         type = NATURAL_SPLINE; 
  6640.         Parse_Comma();
  6641.       END_CASE
  6642.  
  6643.       OTHERWISE
  6644.         UNGET
  6645.         EXIT
  6646.       END_CASE
  6647.     END_EXPECT
  6648.  
  6649.     
  6650.     EXPECT
  6651.       CASE_VECTOR
  6652.         Parse_Vector2D(tv);
  6653.         if (is_first)
  6654.             is_first=FALSE;
  6655.         else
  6656.             if (tv[X] <= last_knot) Error("Knot values have to be sorted in ascending way.");
  6657.         last_knot = tv[X];
  6658.         nr_of_knots ++;
  6659.  
  6660.         /* Put the knot in a list */
  6661.  
  6662.         New = (SPLINE_STACK_1D *)POV_MALLOC(sizeof(SPLINE_STACK_1D), NULL);
  6663.         New->t = tv[X];
  6664.         New->y = tv[Y];
  6665.         New->next = NULL;
  6666.         if (base==NULL) base=New;
  6667.         else
  6668.         {
  6669.           New1=base;
  6670.           while (New1->next!=NULL) New1 = (SPLINE_STACK_1D *)New1->next;
  6671.           New1->next = New;
  6672.         }
  6673.           
  6674.         Parse_Comma();        
  6675.       END_CASE
  6676.  
  6677.       OTHERWISE
  6678.         UNGET
  6679.         EXIT
  6680.       END_CASE
  6681.     END_EXPECT
  6682.  
  6683.     if (nr_of_knots<2) Error("At least two knots per spline.");
  6684.     if ((type==CLOSED_SPLINE)&&(tv1<=tv[X]))
  6685.         Error("Last knot of closed spline must be the biggest.");
  6686.       
  6687.     Parse_End();         
  6688.  
  6689.     Create_Spline_1D(base,nr_of_knots,name,type,tv1,tv2);
  6690.             
  6691. }
  6692.  /*****************************************************************************
  6693. *
  6694. * FUNCTION
  6695. *
  6696. *   Parse_Init_3D_Spline
  6697. *
  6698. * INPUT
  6699. *   
  6700. * OUTPUT
  6701. *   
  6702. * RETURNS
  6703. *   
  6704. * AUTHOR
  6705. *
  6706. *   Daniel Fenner
  6707. *
  6708. * DESCRIPTION
  6709. *
  6710. *   Parse a new spline and compute the coefficients
  6711. *
  6712. * CHANGES
  6713. *
  6714. *   3-98 Creation
  6715. *
  6716. ******************************************************************************/
  6717.  
  6718.  
  6719. void Parse_Init_3D_Spline()
  6720. {
  6721.     char   *name;
  6722.     VECTOR  temp1,temp2,tv;
  6723.     int    nr_of_knots=0,type=NATURAL_SPLINE,does_exist=FALSE;
  6724.     
  6725.     SPLINE_3D  *help;
  6726.     SPLINE_STACK_3D *base=NULL,*New=NULL,*New1=NULL;
  6727.  
  6728.     
  6729.     Parse_Begin ();
  6730.  
  6731.     name = Parse_String();
  6732.     
  6733.     /* does already exist ??? */
  6734.     if (The_3D_Splines!=NULL)
  6735.     {
  6736.         help=The_3D_Splines;
  6737.         if (strcmp(help->name,name)==0) does_exist=TRUE;
  6738.         while (help->next!=NULL)
  6739.         {
  6740.             help=(SPLINE_3D*)help->next;
  6741.             if (strcmp(help->name,name)==0) does_exist=TRUE;
  6742.         }
  6743.         if (does_exist) Error("Spline named %s does already exist.",name);
  6744.     }
  6745.  
  6746.     
  6747.     Parse_Comma();
  6748.  
  6749.     EXPECT
  6750.       CASE (SPLINE_CLOSED_TOKEN)
  6751.         type = CLOSED_SPLINE;
  6752.         Parse_Comma();
  6753.       END_CASE
  6754.  
  6755.       CASE (SPLINE_DIRECTION_TOKEN)
  6756.         type = DIRECTION_SPLINE;
  6757.         GET (EQUALS_TOKEN);
  6758.         Parse_Vector(temp1);
  6759.         Parse_Comma();
  6760.         Parse_Vector(temp2);
  6761.         Parse_Comma();
  6762.       END_CASE
  6763.  
  6764.       CASE (SPLINE_NATURAL_TOKEN)
  6765.         type = NATURAL_SPLINE; 
  6766.         Parse_Comma();
  6767.       END_CASE
  6768.  
  6769.       OTHERWISE
  6770.         UNGET
  6771.         EXIT
  6772.       END_CASE
  6773.     END_EXPECT
  6774.  
  6775.     
  6776.     EXPECT
  6777.       CASE_VECTOR
  6778.         Parse_Vector(tv);
  6779.         nr_of_knots ++;
  6780.  
  6781.         /* Put the knot in a list */
  6782.  
  6783.         New = (SPLINE_STACK_3D *)POV_MALLOC(sizeof(SPLINE_STACK_3D), NULL);
  6784.         New->Knot[X]=tv[X];
  6785.         New->Knot[Y]=tv[Y];
  6786.         New->Knot[Z]=tv[Z];
  6787.         New->next = NULL;
  6788.         if (base==NULL) base=New;
  6789.         else
  6790.         {
  6791.           New1=base;
  6792.           while (New1->next!=NULL) New1 =(SPLINE_STACK_3D *) New1->next;
  6793.           New1->next = New;
  6794.         }
  6795.           
  6796.         Parse_Comma();        
  6797.       END_CASE
  6798.  
  6799.       OTHERWISE
  6800.         UNGET
  6801.         EXIT
  6802.       END_CASE
  6803.     END_EXPECT
  6804.  
  6805.     if (nr_of_knots<2) Error("At least two knots per spline.");
  6806.       
  6807.     Parse_End();         
  6808.  
  6809.     Create_Spline_3D(base,nr_of_knots,name,type,temp1,temp2);
  6810.             
  6811. }
  6812. #endif
  6813.  
  6814.  
  6815.  
  6816. /*****************************************************************************
  6817. *
  6818. * FUNCTION
  6819. *
  6820. * INPUT
  6821. *   
  6822. * OUTPUT
  6823. *   
  6824. * RETURNS
  6825. *   
  6826. * AUTHOR
  6827. *   
  6828. * DESCRIPTION
  6829. *
  6830. * CHANGES
  6831. *
  6832. ******************************************************************************/
  6833.  
  6834. static void Parse_Frame ()
  6835. {
  6836.    OBJECT *Object;
  6837.    RAINBOW  *Local_Rainbow;
  6838.    FOG  *Local_Fog;
  6839.    SKYSPHERE  *Local_Skysphere;
  6840.    int i;
  6841.  
  6842.    EXPECT
  6843.      CASE (RAINBOW_TOKEN)
  6844.        Local_Rainbow = Parse_Rainbow();
  6845.        Local_Rainbow->Next = Frame.Rainbow;
  6846.        Frame.Rainbow = Local_Rainbow;
  6847.      END_CASE
  6848.  
  6849.      CASE (SKYSPHERE_TOKEN)
  6850.        Local_Skysphere = Parse_Skysphere();
  6851.        if (Frame.Skysphere != NULL)
  6852.        {
  6853.          Warn(0, "Only one sky-sphere allowed (last one will be used).");
  6854.          Destroy_Skysphere(Frame.Skysphere);
  6855.        }
  6856.        Frame.Skysphere = Local_Skysphere;
  6857.        for (i=0; i<Local_Skysphere->Count; i++)
  6858.        {
  6859.          Post_Pigment(Local_Skysphere->Pigments[i]);
  6860.        }
  6861.      END_CASE
  6862.  
  6863.      CASE (FOG_TOKEN)
  6864.        Local_Fog = Parse_Fog();
  6865.        Local_Fog->Next = Frame.Fog;
  6866.        Frame.Fog = Local_Fog;
  6867.      END_CASE
  6868.  
  6869.      CASE (MEDIA_TOKEN)
  6870.        Parse_Media(&Frame.Atmosphere);
  6871.      END_CASE
  6872.  
  6873.      CASE (BACKGROUND_TOKEN)
  6874.        Parse_Begin();
  6875.        Parse_Colour (Frame.Background_Colour);
  6876.        Parse_End();
  6877.      END_CASE
  6878.  
  6879.      CASE (CAMERA_TOKEN)
  6880.        Parse_Camera (&Frame.Camera);
  6881.      END_CASE
  6882.  
  6883.      CASE (DECLARE_TOKEN)
  6884.        UNGET
  6885.        Warn(299,"Should have '#' before 'declare'.");
  6886.        Parse_Directive (FALSE);
  6887.      END_CASE
  6888.  
  6889.      CASE (INCLUDE_TOKEN)
  6890.        UNGET
  6891.        Warn(299,"Should have '#' before 'include'.");
  6892.        Parse_Directive (FALSE);
  6893.      END_CASE
  6894.  
  6895.      CASE (FLOAT_FUNCT_TOKEN)
  6896.        switch(Token.Function_Id)
  6897.          {
  6898.           case VERSION_TOKEN:
  6899.             UNGET
  6900.             Parse_Directive (FALSE);
  6901.             UNGET
  6902.             break;
  6903.             
  6904.           default:
  6905.             UNGET
  6906.             Parse_Error_Str ("object or directive");
  6907.             break;
  6908.          }
  6909.      END_CASE
  6910.  
  6911.      CASE (MAX_TRACE_LEVEL_TOKEN)
  6912.        Global_Setting_Warn();
  6913.        Max_Trace_Level = (int) Parse_Float ();
  6914.      END_CASE
  6915.  
  6916.      CASE (MAX_INTERSECTIONS)
  6917.        Global_Setting_Warn();
  6918.        Max_Intersections = (int)Parse_Float ();
  6919.      END_CASE
  6920.  
  6921.      CASE (DEFAULT_TOKEN)
  6922.        Parse_Default();
  6923.      END_CASE
  6924.  
  6925.      CASE (END_OF_FILE_TOKEN)
  6926.        EXIT
  6927.      END_CASE
  6928.  
  6929.      CASE (GLOBAL_SETTINGS_TOKEN)
  6930.        Parse_Global_Settings();
  6931.      END_CASE
  6932.  
  6933.      /* NK persist - Nov 1999 */
  6934.      CASE (MODIFY_TOKEN)
  6935. #ifdef UnofficialBlocking
  6936.        parseUnofficialFeature(30);
  6937. #endif
  6938.        Parse_Modify_Object();
  6939.      END_CASE
  6940.  
  6941.      CASE (DESTROY_TOKEN)
  6942. #ifdef UnofficialBlocking
  6943.        parseUnofficialFeature(30);
  6944. #endif
  6945.        Parse_Destroy_Object();
  6946.      END_CASE
  6947.      /* NK ---- */
  6948. #ifdef GlowPatch
  6949.     /*YS sept 18 2000 
  6950.        added this here too to allow 
  6951.         for a scene with only glow */
  6952.     CASE(GLOW_TOKEN)
  6953.         #ifdef UnofficialBlocking
  6954.            parseUnofficialFeature(60);
  6955.         #endif    
  6956.         {
  6957.         GLOW * NewGlow = Create_Glow();
  6958.         Parse_Glow(NewGlow);
  6959.         Add_Glow(NewGlow);
  6960.     }
  6961.     END_CASE
  6962. #endif
  6963.  
  6964.      OTHERWISE
  6965.        UNGET
  6966.        Object = Parse_Object();
  6967.        if (Object == NULL)
  6968.          Parse_Error_Str ("object or directive");
  6969.        Post_Process (Object, NULL);
  6970.        Link_To_Frame (Object);
  6971.      END_CASE
  6972.    END_EXPECT
  6973.   }
  6974.  
  6975. /* NK persist */
  6976. int findObjectsByLabel(OBJECT **objHandle, OBJECT* parent, char **objectNames, int nameCount,
  6977.                    int (*function)(OBJECT **objHandle, OBJECT* parent, void *handle), void *handle,
  6978.                    int (*functionParent)(OBJECT **objHandle, OBJECT* parent, void *handle), void *handle2 )
  6979. {
  6980.   int found=FALSE;
  6981.   int go_next;
  6982.  
  6983.   /* go through objects, but we're always using the pointer to the pointer to
  6984.     the object */
  6985.   while( *objHandle != NULL )
  6986.   {
  6987.     if((*objHandle)->Label)
  6988.     {
  6989.       if(strcmp((*objHandle)->Label,objectNames[0])==0)
  6990.       {
  6991.         /* match */
  6992.         if (nameCount==1)
  6993.         {
  6994.           /* call the function */
  6995.           go_next = function(objHandle, parent, handle);
  6996.           found = TRUE;
  6997.         }
  6998.         else
  6999.         {
  7000.           /* should check this first, make sure it really is a CSG */
  7001.           if (findObjectsByLabel(&(((CSG *)*objHandle)->Children), *objHandle, &objectNames[1],
  7002.                              nameCount-1, function, handle, functionParent, handle2 ))
  7003.           {
  7004.             found = TRUE;
  7005.             go_next = functionParent(objHandle, parent, handle2);
  7006.           }
  7007.         }
  7008.         if(go_next)
  7009.         {
  7010.           objHandle=&((*objHandle)->Sibling);
  7011.         }
  7012.       }
  7013.       else
  7014.       {
  7015.         objHandle=&((*objHandle)->Sibling);
  7016.       }
  7017.     }
  7018.     else
  7019.     {
  7020.       objHandle=&((*objHandle)->Sibling);
  7021.     }
  7022.   }
  7023.  
  7024.   return found;
  7025. }
  7026.  
  7027. extern int CS_Index;
  7028. static int beginCS_Index;
  7029. static int beginBrace_Index;
  7030.  
  7031. int modifyObjectCallback(OBJECT **objHandle, OBJECT* parent, void *handle)
  7032. {
  7033.   restoreFilePos();
  7034.   Brace_Index = beginBrace_Index;
  7035.   Parse_Object_Mods(*objHandle);
  7036.   Post_Process (*objHandle, parent);
  7037.  
  7038.   if (CS_Index != beginCS_Index)
  7039.   {
  7040.     Error("close brace for modify cannot be enclosed in an #if, #case, or #while block.\n");
  7041.   }
  7042.   return TRUE; /* continue to next */
  7043. }
  7044. int modifyObjectParentCallback(OBJECT **objHandle, OBJECT *parent, void *handle)
  7045. {
  7046.   /* if this is a parent then we know it is a compound object */
  7047.   Compute_CSG_BBox(*objHandle);
  7048.   Post_Process (*objHandle, parent);
  7049.   return TRUE; /* continue to next */
  7050. }
  7051.  
  7052. int destroyObjectCallback(OBJECT **objHandle, OBJECT* parent, void *handle)
  7053. {
  7054.   OBJECT *obj = *objHandle;
  7055.   *objHandle = (*objHandle)->Sibling;
  7056.   POV_FREE(obj);
  7057.   return FALSE; /* don't go to next */
  7058. }
  7059. int destroyObjectParentCallback(OBJECT **objHandle, OBJECT *parent, void *handle)
  7060. {
  7061.   /* if this is a parent then we know it is a compound object */
  7062.   Compute_CSG_BBox(*objHandle);
  7063.   Post_Process (*objHandle, parent);
  7064.   return TRUE; /* continue to next */
  7065. }
  7066.  
  7067. /*****************************************************************************
  7068. *
  7069. * FUNCTION
  7070. *  Parse_Modify_Object()
  7071. *
  7072. * INPUT
  7073. *   
  7074. * OUTPUT
  7075. *   
  7076. * RETURNS
  7077. *   
  7078. * AUTHOR
  7079. *   
  7080. * DESCRIPTION
  7081. *
  7082. *  This allows a persistent object (named with #create) to be modified.
  7083. *  It will parse object modifiers and apply them to all objects that
  7084. *  match the name.
  7085. *
  7086. *  The syntax would look like this:
  7087. *  #create mySph=sphere{...}
  7088. *  modify{
  7089. *    mySph
  7090. *    translate 10*x
  7091. *  }
  7092. *
  7093. *
  7094. * CHANGES
  7095. *
  7096. ******************************************************************************/
  7097.  
  7098. static void Parse_Modify_Object(void)
  7099. {
  7100.   /*OBJECT *o;*/
  7101.   char **objectNames;
  7102.   int done;
  7103.   int i;
  7104.   /*int level;*/
  7105.   int numLevels;
  7106.  
  7107.   Parse_Begin();
  7108.  
  7109.   /* first, count levels */
  7110.   saveFilePos();
  7111.   numLevels = 0;
  7112.   done = FALSE;
  7113.   while (!done)
  7114.   {
  7115.     numLevels++;
  7116.     Get_Token();
  7117.     Get_Token();
  7118.     if(Token.Token_Id!=PERIOD_TOKEN)
  7119.       done=TRUE;
  7120.   }
  7121.   restoreFilePos();
  7122.  
  7123.   objectNames =(char**) POV_MALLOC(sizeof(OBJECT*)*numLevels,"object names");
  7124.   for(i=0; i<numLevels; i++)
  7125.   {
  7126.     if (i>0) Get_Token();  /* parse the period */
  7127.     Get_Token();           /* parse the name */
  7128.     objectNames[i] = POV_STRDUP(Token.Token_String);
  7129.   }
  7130.  
  7131.   saveFilePos();
  7132.   beginCS_Index = CS_Index;
  7133.   beginBrace_Index = Brace_Index;
  7134.  
  7135.   if (!findObjectsByLabel(&Frame.Objects, NULL, objectNames, numLevels,
  7136.                      modifyObjectCallback, NULL,
  7137.                      modifyObjectParentCallback, NULL))
  7138.   {
  7139.     Error("No objects match this label.\n");
  7140.   }
  7141.  
  7142.   for(i=0; i<numLevels; i++)
  7143.   {
  7144.     POV_FREE(objectNames[i]);
  7145.   }
  7146.  
  7147.   POV_FREE(objectNames);
  7148. }
  7149.  
  7150. /*****************************************************************************
  7151. *
  7152. * FUNCTION
  7153. *  Parse_Destroy_Object()
  7154. *
  7155. * INPUT
  7156. *   
  7157. * OUTPUT
  7158. *   
  7159. * RETURNS
  7160. *   
  7161. * AUTHOR
  7162. *   
  7163. * DESCRIPTION
  7164. *
  7165. *
  7166. *
  7167. * CHANGES
  7168. *
  7169. ******************************************************************************/
  7170.  
  7171. static void Parse_Destroy_Object(void)
  7172. {
  7173.   char **objectNames;
  7174.   int done;
  7175.   int i;
  7176.   int numLevels;
  7177.  
  7178.   Parse_Begin();
  7179.  
  7180.   /* first, count levels */
  7181.   saveFilePos();
  7182.   numLevels = 0;
  7183.   done = FALSE;
  7184.   while (!done)
  7185.   {
  7186.     numLevels++;
  7187.     Get_Token();
  7188.     Get_Token();
  7189.     if(Token.Token_Id!=PERIOD_TOKEN)
  7190.       done=TRUE;
  7191.   }
  7192.   restoreFilePos();
  7193.  
  7194.   objectNames =(char**) POV_MALLOC(sizeof(OBJECT*)*numLevels,"object names");
  7195.   for(i=0; i<numLevels; i++)
  7196.   {
  7197.     if (i>0) Get_Token();  /* parse the period */
  7198.     Get_Token();           /* parse the name */
  7199.     objectNames[i] = POV_STRDUP(Token.Token_String);
  7200.   }
  7201.  
  7202.   if (!findObjectsByLabel(&Frame.Objects, NULL, objectNames, numLevels,
  7203.                      destroyObjectCallback, NULL,
  7204.                      destroyObjectParentCallback, NULL))
  7205.   {
  7206.     Error("No objects match this label.\n");
  7207.   }
  7208.  
  7209.   Parse_End();
  7210.  
  7211.   for(i=0; i<numLevels; i++)
  7212.   {
  7213.     POV_FREE(objectNames[i]);
  7214.   }
  7215.  
  7216.   POV_FREE(objectNames);
  7217. }
  7218. /* NK ---- */
  7219.  
  7220. /*****************************************************************************
  7221. *
  7222. * FUNCTION
  7223. *
  7224. * INPUT
  7225. *   
  7226. * OUTPUT
  7227. *   
  7228. * RETURNS
  7229. *   
  7230. * AUTHOR
  7231. *   
  7232. * DESCRIPTION
  7233. *
  7234. * CHANGES
  7235. *
  7236. *   Mar 1996 : Add line number info to warning message  [AED]
  7237. *
  7238. ******************************************************************************/
  7239.  
  7240. static void Global_Setting_Warn()
  7241. {
  7242.   if (opts.Language_Version >= 300)
  7243.   {
  7244.     Warning(0, "%s:%d: warning: '%s' should be in 'global_settings{...}' statement.\n",
  7245.             Token.Filename, Token.Token_Line_No+1, Token.Token_String);
  7246.   }
  7247. }
  7248.  
  7249.  
  7250. #ifdef PostProcessPatch
  7251.  
  7252. #define Add_PP(pp) {\
  7253.     PP_TASK *pp_task;\
  7254.     if(!opts.postProcess)\
  7255.     {   opts.postProcess = (void*)pp;}\
  7256.     else\
  7257.     {\
  7258.         for(pp_task = (PP_TASK*)opts.postProcess; pp_task->next != NULL; pp_task = pp_task->next){;}\
  7259.         pp_task->next = (PP_TASK*)pp;\
  7260.     }\
  7261. }
  7262.  
  7263. #ifdef PostProcessCurvesPatch
  7264. SPLINE2 *Process_Spline_Syntax(void);
  7265.  
  7266. SPLINE2 *Process_Spline_Syntax(void)
  7267. {
  7268.     SPLINE2 *Spline=NULL;
  7269.  
  7270.     EXPECT
  7271.         CASE(SPLINE_TOKEN)
  7272.             Parse_Begin();
  7273.            Spline= Parse_Spline();
  7274.             Parse_End();
  7275.             EXIT
  7276.         END_CASE
  7277.         
  7278.      OTHERWISE
  7279.        UNGET
  7280.         Spline= Parse_Spline();
  7281.        EXIT
  7282.      END_CASE
  7283.    END_EXPECT                        
  7284.    
  7285.    return Spline;
  7286.  
  7287. }
  7288. #endif
  7289.  
  7290. void Parse_Post_Process(void)
  7291. {
  7292.   PP_TASK *pp_task;
  7293.  
  7294.   if(!(opts.Options & DISKWRITE))
  7295.   {
  7296.     Error("Post-processing requires an output file.\n");
  7297.   }
  7298.  
  7299.   Parse_Begin();
  7300.   EXPECT
  7301.     CASE(OVERWRITE_FILE_TOKEN)
  7302.       opts.postProcessOverwriteOriginal = TRUE;
  7303.     END_CASE
  7304.  
  7305. #ifdef PostProcessKeepDataPatch
  7306.     CASE(KEEP_DATA_FILE_TOKEN)
  7307.       opts.keep_post_process_data_file = TRUE;
  7308.     END_CASE
  7309. #endif
  7310.  
  7311. #ifdef PostProcessLimitBrightnessPatch
  7312.     CASE(LIMIT_BRIGHTNESS_TOKEN)
  7313.     {
  7314.         PP_LIMIT_BRIGHTNESS * new_pp = createPostLimitBrightness();
  7315. #ifdef UnofficialBlocking
  7316.         parseUnofficialFeature(70);
  7317. #endif
  7318.         new_pp->max_brightness = Allow_Float(1);
  7319.         
  7320.         Add_PP(new_pp)
  7321.         opts.postProcessFlags |= PP_LIMIT_BRIGHTNESS_FLAGS;
  7322.     }
  7323.     END_CASE
  7324. #endif
  7325.  
  7326. #ifdef PostProcessRawImagePatch
  7327.     CASE(RAW_IMAGE_TOKEN)
  7328.     {
  7329.         PP_RAW_IMAGE * new_pp = createPostRawImage();
  7330. #ifdef UnofficialBlocking
  7331.         parseUnofficialFeature(70);
  7332. #endif
  7333.      
  7334.         if(!opts.postProcess)
  7335.         {   opts.postProcess = (void*)new_pp;}
  7336.         else
  7337.         {
  7338.             for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7339.             pp_task->next = (PP_TASK*)new_pp;
  7340.         }
  7341.         opts.postProcessFlags |= PP_RAW_IMAGE_FLAGS;
  7342.     }
  7343.     END_CASE
  7344. #endif
  7345.  
  7346. #ifdef PostProcessCurvesPatch
  7347.     CASE(CURVES_TOKEN)
  7348.     {
  7349.         PP_CURVES * new_pp = createPostCurves();;
  7350. #ifdef UnofficialBlocking
  7351.         parseUnofficialFeature(70);
  7352. #endif
  7353.         Parse_Begin();
  7354.         EXPECT
  7355.         CASE(COLOUR_KEY_TOKEN)
  7356.             switch(Token.Function_Id)
  7357.             {
  7358.                 case RGB_TOKEN:
  7359.                 Parse_Comma();
  7360.                 new_pp->type = 0;/*rgb type*/
  7361.                 new_pp->rCurve = Process_Spline_Syntax();
  7362.                 Parse_Comma();
  7363.                 new_pp->gCurve = Process_Spline_Syntax();
  7364.                 Parse_Comma();
  7365.                 new_pp->bCurve = Process_Spline_Syntax();
  7366.                 EXIT
  7367.             break;
  7368.  
  7369.             case RED_TOKEN:
  7370.                 Parse_Comma();
  7371.                 new_pp->type = 0;/*red channel only*/
  7372.                 new_pp->rCurve = Process_Spline_Syntax();
  7373.                 EXIT
  7374.             break;
  7375.  
  7376.             case GREEN_TOKEN:
  7377.                 Parse_Comma();
  7378.                 new_pp->type = 0;/*green channel only*/
  7379.                 new_pp->gCurve = Process_Spline_Syntax();
  7380.                 EXIT
  7381.             break;
  7382.  
  7383.             case BLUE_TOKEN:
  7384.                 Parse_Comma();
  7385.                 new_pp->type = 0;/*blue channel only*/
  7386.                 new_pp->bCurve = Process_Spline_Syntax();
  7387.                 EXIT
  7388.             break;
  7389.         }
  7390.         END_CASE        
  7391.     
  7392.         CASE (ALL_TOKEN)
  7393.            Parse_Comma();
  7394.              new_pp->type = 1;/*grayscale*/
  7395.                 new_pp->rCurve = Process_Spline_Syntax();
  7396.            EXIT
  7397.         END_CASE
  7398.       
  7399.         OTHERWISE
  7400.            Error("Expected rgb, red, green, blue, or all.");
  7401.           END_CASE
  7402.       END_EXPECT
  7403.      
  7404.       Parse_End();
  7405.  
  7406.         if(!opts.postProcess)
  7407.         {   opts.postProcess = (void*)new_pp;}
  7408.         else
  7409.         {
  7410.             for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7411.             pp_task->next = (PP_TASK*)new_pp;
  7412.         }
  7413.         opts.postProcessFlags |= PP_CURVES_FLAGS;
  7414.     }
  7415.     END_CASE
  7416. #endif
  7417.  
  7418.  
  7419.  
  7420. #ifdef PostProcessPatternBlurPatch
  7421.     CASE(PATTERN_BLUR_TOKEN)
  7422.     {
  7423.       PP_PATTERN_BLUR *new_pattern_blur;
  7424. #ifdef UnofficialBlocking
  7425.       parseUnofficialFeature(50);
  7426. #endif
  7427.       new_pattern_blur = createPostPatternBlur();
  7428.      
  7429.       Parse_Begin();
  7430.         new_pattern_blur->Radius = Parse_Float();
  7431.         Parse_Comma();
  7432.         new_pattern_blur->Div = Parse_Float();
  7433.         Parse_Comma();
  7434.         new_pattern_blur->Levelling = Parse_Float();
  7435.         Parse_Comma();
  7436.         Parse_Pigment(&new_pattern_blur->Pig);
  7437.       Parse_End();
  7438.      
  7439.       if(!opts.postProcess)
  7440.       { opts.postProcess = (void*)new_pattern_blur; }
  7441.       else
  7442.       {
  7443.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7444.         pp_task->next = (PP_TASK*)new_pattern_blur;
  7445.       }
  7446.       opts.postProcessFlags |= PP_PATTERN_BLUR_FLAGS;
  7447.     }
  7448.     END_CASE
  7449. #endif   
  7450.  
  7451. #ifdef PostProcessStarsPatch
  7452.     CASE(STARS_TOKEN)
  7453.     {
  7454.       PP_STARS *new_stars;
  7455. #ifdef UnofficialBlocking
  7456.       parseUnofficialFeature(50);
  7457. #endif
  7458.       new_stars = createPostStars();
  7459.      
  7460.       Parse_Begin();
  7461.       new_stars->Density = Parse_Float();
  7462.       Parse_Comma();
  7463.       Parse_Colour(new_stars->colRangeMin);
  7464.       Parse_Comma();
  7465.       Parse_Colour(new_stars->colRangeMax);
  7466.  
  7467.  
  7468.       Parse_End();
  7469.  
  7470.       if(!opts.postProcess)
  7471.       { opts.postProcess = (void*)new_stars;}
  7472.       else
  7473.       {
  7474.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7475.         pp_task->next = (PP_TASK*)new_stars;
  7476.       }
  7477.       opts.postProcessFlags |= PP_STARS_FLAGS;
  7478.     }
  7479.     END_CASE
  7480. #endif
  7481. #ifdef PostProcessStepsPatch
  7482.     CASE(POSTERIZE_TOKEN)
  7483.     {
  7484.       PP_STEPS *new_steps;
  7485. #ifdef UnofficialBlocking
  7486.       parseUnofficialFeature(50);
  7487. #endif
  7488.       new_steps = createPostSteps();
  7489.      
  7490.       Parse_Begin();
  7491.       Parse_Colour(new_steps->numSteps);
  7492.       Parse_End();
  7493.      
  7494.       if(!opts.postProcess)
  7495.       { opts.postProcess = (void*)new_steps;}
  7496.       else
  7497.       {
  7498.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7499.         pp_task->next = (PP_TASK*)new_steps;
  7500.       }
  7501.       opts.postProcessFlags |= PP_STEPS_FLAGS;
  7502.     }
  7503.     END_CASE
  7504. #endif   
  7505.    
  7506. #ifdef PostProcesNormalPatch
  7507.     CASE(TNORMAL_TOKEN)
  7508.     {
  7509.       PP_NORMAL *new_normal;
  7510. #ifdef UnofficialBlocking
  7511.       parseUnofficialFeature(50);
  7512. #endif
  7513.       new_normal = createPostNormal();
  7514.      
  7515.       if(!opts.postProcess)
  7516.       { opts.postProcess = (void*)new_normal;}
  7517.       else
  7518.       {
  7519.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7520.         pp_task->next = (PP_TASK*)new_normal;
  7521.       }
  7522.       opts.postProcessFlags |= PP_NORMAL_FLAGS;
  7523.     }
  7524.     END_CASE
  7525. #endif   
  7526.    
  7527. #ifdef PostProcessMinPatch
  7528.     CASE(POST_MIN_TOKEN)
  7529.     {
  7530.       PP_MATH *new_proc;
  7531. #ifdef UnofficialBlocking
  7532.       parseUnofficialFeature(60);
  7533. #endif
  7534.       new_proc = createPostMath();
  7535.       new_proc->doPostProcess = doPostMin;
  7536.      
  7537.       Parse_Begin();
  7538.       Parse_Pigment(&new_proc->Pig);
  7539.       Parse_End();
  7540.      
  7541.       if(!opts.postProcess)
  7542.       { opts.postProcess = (void*)new_proc;}
  7543.       else
  7544.       {
  7545.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7546.         pp_task->next = (PP_TASK*)new_proc;
  7547.       }
  7548.       opts.postProcessFlags |= PP_MATH_FLAGS;
  7549.     }
  7550.     END_CASE
  7551. #endif 
  7552.  
  7553. #ifdef PostProcessMaxPatch
  7554.     CASE(POST_MAX_TOKEN)
  7555.     {
  7556.       PP_MATH *new_proc;
  7557. #ifdef UnofficialBlocking
  7558.       parseUnofficialFeature(60);
  7559. #endif
  7560.       new_proc = createPostMath();
  7561.       new_proc->doPostProcess = doPostMax;
  7562.      
  7563.       Parse_Begin();
  7564.       Parse_Pigment(&new_proc->Pig);
  7565.       Parse_End();
  7566.      
  7567.       if(!opts.postProcess)
  7568.       { opts.postProcess = (void*)new_proc;}
  7569.       else
  7570.       {
  7571.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7572.         pp_task->next = (PP_TASK*)new_proc;
  7573.       }
  7574.       opts.postProcessFlags |= PP_MATH_FLAGS;
  7575.     }
  7576.     END_CASE
  7577. #endif   
  7578.    
  7579. #ifdef PostProcessAddPatch
  7580.     CASE(ADD_TOKEN)
  7581.     {
  7582.       PP_MATH *new_proc;
  7583. #ifdef UnofficialBlocking
  7584.       parseUnofficialFeature(50);
  7585. #endif
  7586.       new_proc = createPostMath();
  7587.       new_proc->doPostProcess = doPostAdd;
  7588.      
  7589.       Parse_Begin();
  7590.       Parse_Pigment(&new_proc->Pig);
  7591.       Parse_End();
  7592.      
  7593.       if(!opts.postProcess)
  7594.       { opts.postProcess = (void*)new_proc;}
  7595.       else
  7596.       {
  7597.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7598.         pp_task->next = (PP_TASK*)new_proc;
  7599.       }
  7600.       opts.postProcessFlags |= PP_MATH_FLAGS;
  7601.     }
  7602.     END_CASE
  7603. #endif 
  7604.  
  7605. #ifdef PostProcessSubtractPatch
  7606.     CASE(SUBTRACT_TOKEN)
  7607.     {
  7608.       PP_MATH *new_proc;
  7609. #ifdef UnofficialBlocking
  7610.       parseUnofficialFeature(60);
  7611. #endif
  7612.       new_proc = createPostMath();
  7613.       new_proc->doPostProcess = doPostSub;
  7614.      
  7615.       Parse_Begin();
  7616.       Parse_Pigment(&new_proc->Pig);
  7617.       Parse_End();
  7618.      
  7619.       if(!opts.postProcess)
  7620.       { opts.postProcess = (void*)new_proc;}
  7621.       else
  7622.       {
  7623.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7624.         pp_task->next = (PP_TASK*)new_proc;
  7625.       }
  7626.       opts.postProcessFlags |= PP_MATH_FLAGS;
  7627.     }
  7628.     END_CASE
  7629. #endif 
  7630.  
  7631. #ifdef PostProcessMultiplyPatch
  7632.     CASE(MULTIPLY_TOKEN)
  7633.     {
  7634.       PP_MATH *new_proc;
  7635. #ifdef UnofficialBlocking
  7636.       parseUnofficialFeature(50);
  7637. #endif
  7638.       new_proc = createPostMath();
  7639.       new_proc->doPostProcess = doPostMult;
  7640.      
  7641.       Parse_Begin();
  7642.       Parse_Pigment(&new_proc->Pig);
  7643.       Parse_End();
  7644.      
  7645.       if(!opts.postProcess)
  7646.       { opts.postProcess = (void*)new_proc;}
  7647.       else
  7648.       {
  7649.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7650.         pp_task->next = (PP_TASK*)new_proc;
  7651.       }
  7652.       opts.postProcessFlags |= PP_MATH_FLAGS;
  7653.     }
  7654.     END_CASE
  7655. #endif 
  7656.  
  7657. #ifdef PostProcessDividePatch
  7658.     CASE(DIVIDE_TOKEN)
  7659.     {
  7660.       PP_MATH *new_proc;
  7661. #ifdef UnofficialBlocking
  7662.       parseUnofficialFeature(60);
  7663. #endif
  7664.       new_proc = createPostMath();
  7665.       new_proc->doPostProcess = doPostDiv;
  7666.      
  7667.       Parse_Begin();
  7668.       Parse_Pigment(&new_proc->Pig);
  7669.       Parse_End();
  7670.      
  7671.       if(!opts.postProcess)
  7672.       { opts.postProcess = (void*)new_proc;}
  7673.       else
  7674.       {
  7675.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7676.         pp_task->next = (PP_TASK*)new_proc;
  7677.       }
  7678.       opts.postProcessFlags |= PP_MATH_FLAGS;
  7679.     }
  7680.     END_CASE
  7681. #endif   
  7682.    
  7683. #ifdef PostProcessExponentPatch
  7684.     CASE(EXPONENT_TOKEN)
  7685.     {
  7686.       PP_MATH *new_proc;
  7687. #ifdef UnofficialBlocking
  7688.       parseUnofficialFeature(50);
  7689. #endif
  7690.       new_proc = createPostMath();
  7691.       new_proc->doPostProcess = doPostExp;
  7692.      
  7693.       Parse_Begin();
  7694.       Parse_Pigment(&new_proc->Pig);
  7695.       Parse_End();
  7696.      
  7697.       if(!opts.postProcess)
  7698.       { opts.postProcess = (void*)new_proc;}
  7699.       else
  7700.       {
  7701.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7702.         pp_task->next = (PP_TASK*)new_proc;
  7703.       }
  7704.       opts.postProcessFlags |= PP_MATH_FLAGS;
  7705.     }
  7706.     END_CASE
  7707. #endif
  7708.    
  7709.    
  7710. #ifdef PostProcessInvertPatch
  7711.     CASE(INVERT_TOKEN)
  7712.     {
  7713.       PP_INVERT *new_invert;
  7714. #ifdef UnofficialBlocking
  7715.       parseUnofficialFeature(50);
  7716. #endif
  7717.       new_invert = createPostInvert();
  7718.      
  7719.       if(!opts.postProcess)
  7720.       { opts.postProcess = (void*)new_invert;}
  7721.       else
  7722.       {
  7723.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7724.         pp_task->next = (PP_TASK*)new_invert;
  7725.       }
  7726.       opts.postProcessFlags |= PP_INVERT_FLAGS;
  7727.     }
  7728.     END_CASE
  7729. #endif   
  7730.    
  7731. #ifdef PostProcessClipColorsPatch
  7732.     CASE(CLIP_COLORS_TOKEN)
  7733.     {
  7734.       PP_CLIP_COLORS *new_clip_colors;
  7735. #ifdef UnofficialBlocking
  7736.       parseUnofficialFeature(50);
  7737. #endif
  7738.       new_clip_colors = createPostClipColors();
  7739.      
  7740.       Parse_Begin();
  7741.       Parse_Colour(new_clip_colors->ClipMin);
  7742.       Parse_Comma();
  7743.       Parse_Colour(new_clip_colors->ClipMax);
  7744.       Parse_End();
  7745.      
  7746.       if(!opts.postProcess)
  7747.       { opts.postProcess = (void*)new_clip_colors;}
  7748.       else
  7749.       {
  7750.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7751.         pp_task->next = (PP_TASK*)new_clip_colors;
  7752.       }
  7753.       opts.postProcessFlags |= PP_CLIP_FLAGS;
  7754.     }
  7755.     END_CASE
  7756. #endif   
  7757.    
  7758. #ifdef PostProcessFindEdgesPatch
  7759.     CASE(FIND_EDGES_TOKEN)
  7760.     {
  7761.       PP_EDGES *new_edges;
  7762. #ifdef UnofficialBlocking
  7763.       parseUnofficialFeature(50);
  7764. #endif
  7765.       Parse_Begin();
  7766.       new_edges = createPostEdges();
  7767.  
  7768.       new_edges->ThreshDepthMax = Parse_Float();
  7769.       Parse_Comma();
  7770.  
  7771.       new_edges->ThreshNormMax = Parse_Float();
  7772.       Parse_Comma();
  7773.  
  7774.       new_edges->ThreshColMax = Parse_Float();
  7775.       Parse_Comma();
  7776.  
  7777.       new_edges->Radius = Parse_Float();
  7778.       Parse_Comma();
  7779.  
  7780.       new_edges->Sharpness = Parse_Float();
  7781.       Parse_Comma();
  7782.  
  7783.       /*Parse_Colour(new_edges->LineCol);*/
  7784.       Parse_Pigment(&(new_edges->LinePig));
  7785.       Post_Pigment(new_edges->LinePig);
  7786.       Parse_End();
  7787.      
  7788.       if(!opts.postProcess)
  7789.       { opts.postProcess = (void*)new_edges;}
  7790.       else
  7791.       {
  7792.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7793.         pp_task->next = (PP_TASK*)new_edges;
  7794.       }
  7795.       opts.postProcessFlags |= PP_EDGES_FLAGS;
  7796.     }
  7797.     END_CASE
  7798. #endif   
  7799.  
  7800. #ifdef PostProcessColorMatrixPatch
  7801.     CASE(COLOR_MATRIX_TOKEN)
  7802.     {
  7803.       PP_COLOR_MATRIX *new_color_matrix;
  7804.       int i = 0;
  7805.       int j = 0;
  7806. #ifdef UnofficialBlocking
  7807.       parseUnofficialFeature(50);
  7808. #endif
  7809.       new_color_matrix = createPostColor_Matrix();
  7810.       Parse_Begin();
  7811.       GET (LEFT_ANGLE_TOKEN);
  7812.       for (i = 0; i < 3; i++)
  7813.       {
  7814.         for (j = 0; j < 3; j++)
  7815.         {
  7816.           new_color_matrix->Matrix[j][i] = Parse_Float();
  7817.           if(!(i==2 && j==2))
  7818.           {    Parse_Comma();}
  7819.         }
  7820.       }
  7821.       GET (RIGHT_ANGLE_TOKEN);
  7822.       Parse_End();
  7823.       if(!opts.postProcess) opts.postProcess = (void*)new_color_matrix;
  7824.       else
  7825.       {
  7826.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7827.         pp_task->next = (PP_TASK*)new_color_matrix;
  7828.       }
  7829.       opts.postProcessFlags |= PP_COLOR_MATRIX_FLAGS;
  7830.     }
  7831.     END_CASE
  7832. #endif   
  7833.  
  7834. #ifdef PostProcessBlurMatrixPatch
  7835.     CASE(CONVOLUTION_MATRIX_TOKEN)
  7836.     {
  7837.       PP_BLUR_MATRIX *new_blur_matrix;
  7838.       int i = 0;
  7839.       int j = 0;
  7840.       int k = 0;
  7841. #ifdef UnofficialBlocking
  7842.       parseUnofficialFeature(50);
  7843. #endif
  7844.       Parse_Begin();
  7845.       new_blur_matrix = createPostBlur_Matrix();
  7846.       new_blur_matrix->xSize = (int)Parse_Float();
  7847.       Parse_Comma();
  7848.       new_blur_matrix->ySize = (int)Parse_Float();
  7849.       Parse_Comma();
  7850.       new_blur_matrix->Div = Parse_Float();
  7851.       Parse_Comma();
  7852.       new_blur_matrix->Levelling = Parse_Float();
  7853.       Parse_Comma();
  7854.       new_blur_matrix->Matrix = (DBL *)POV_MALLOC(new_blur_matrix->xSize*new_blur_matrix->ySize*sizeof(DBL),"blur_matrix data");
  7855.       GET (LEFT_ANGLE_TOKEN);
  7856.       for (i = 0; i < new_blur_matrix->ySize; i++)
  7857.       {
  7858.         for (j = 0; j < new_blur_matrix->xSize; j++)
  7859.         {
  7860.           new_blur_matrix->Matrix[k] = Parse_Float();
  7861.           if(!(i==new_blur_matrix->ySize-1 && j==new_blur_matrix->xSize-1))
  7862.           {    Parse_Comma();}
  7863.           k++;
  7864.         }
  7865.       }
  7866.       GET (RIGHT_ANGLE_TOKEN);
  7867.       Parse_End();
  7868.       if(!opts.postProcess) opts.postProcess = (void*)new_blur_matrix;
  7869.       else
  7870.       {
  7871.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
  7872.         pp_task->next = (PP_TASK*)new_blur_matrix;
  7873.       }
  7874.       opts.postProcessFlags |= PP_BLUR_MATRIX_FLAGS;
  7875.     }
  7876.     END_CASE
  7877. #endif
  7878.  
  7879.     CASE(FOCAL_BLUR_TOKEN)
  7880.     {
  7881.       PP_FOCAL_BLUR *new_focal;
  7882.       Parse_Begin();
  7883.       new_focal = createPostFocalBlur();
  7884.       new_focal->fieldStart = Parse_Float(); Parse_Comma();
  7885.       new_focal->fieldDepth = Parse_Float(); Parse_Comma();
  7886.       new_focal->maxPixelBlur = (int)Parse_Float(); Parse_Comma();
  7887.       new_focal->keepAA = Parse_Float();
  7888.       Parse_End();
  7889.       if(!opts.postProcess) opts.postProcess = (void*)new_focal;
  7890.       else
  7891.       {
  7892.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next);
  7893.         pp_task->next = (PP_TASK*)new_focal;
  7894.       }
  7895.       opts.postProcessFlags |= PP_FOCAL_BLUR_FLAGS;
  7896.     }
  7897.     END_CASE
  7898.  
  7899.     CASE(DEPTH_TOKEN)
  7900.     {
  7901.       PP_DEPTH *new_depth;
  7902.       Parse_Begin();
  7903.       new_depth = createPostDepth();
  7904.       new_depth->fieldStart = Parse_Float(); Parse_Comma();
  7905.       new_depth->fieldDepth = Parse_Float();
  7906.       Parse_End();
  7907.       if(!opts.postProcess) opts.postProcess = (void*)new_depth;
  7908.       else
  7909.       {
  7910.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next);
  7911.         pp_task->next = (PP_TASK*)new_depth;
  7912.       }
  7913.       opts.postProcessFlags |= PP_DEPTH_FLAGS;
  7914.     }
  7915.     END_CASE
  7916.  
  7917.     CASE(SOFT_GLOW_TOKEN)
  7918.     {
  7919.       PP_SOFT_GLOW *new_soft_glow;
  7920.       Parse_Begin();
  7921.       new_soft_glow = createPostSoftGlow();
  7922.       new_soft_glow->glowAmount = Parse_Float(); Parse_Comma();
  7923.       new_soft_glow->blurAmount = Parse_Float();
  7924.       Parse_End();
  7925.       if(!opts.postProcess) opts.postProcess = (void*)new_soft_glow;
  7926.       else
  7927.       {
  7928.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next);
  7929.         pp_task->next = (PP_TASK*)new_soft_glow;
  7930.       }
  7931.       opts.postProcessFlags |= PP_SOFT_GLOW_FLAGS;
  7932.     }
  7933.     END_CASE
  7934.  
  7935. #ifdef PostCartoonPatch
  7936.     CASE(CARTOON_TOKEN)
  7937.     {
  7938.       PP_CARTOON *new_cartoon;
  7939.       Parse_Begin();
  7940.       new_cartoon = createPostCartoon();
  7941.       new_cartoon->blurAmount = Parse_Float(); Parse_Comma();
  7942.       new_cartoon->hueThreshold = Parse_Float(); Parse_Comma();
  7943.       new_cartoon->lumThreshold = Parse_Float(); Parse_Comma();
  7944.       /*new_cartoon->lineWidth = Parse_Float(); Parse_Comma();
  7945.       new_cartoon->lineHueThreshold = Parse_Float(); Parse_Comma();
  7946.       Parse_Colour(new_cartoon->lineColour);*/
  7947.       Parse_End();
  7948.       if(!opts.postProcess) opts.postProcess = (void*)new_cartoon;
  7949.       else
  7950.       {
  7951.         for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next);
  7952.         pp_task->next = (PP_TASK*)new_cartoon;
  7953.       }
  7954.       opts.postProcessFlags |= PP_CARTOON_FLAGS;
  7955.     }
  7956.     END_CASE
  7957. #endif
  7958.  
  7959.    OTHERWISE
  7960.      UNGET
  7961.      EXIT
  7962.    END_CASE
  7963.   END_EXPECT
  7964.   Parse_End();
  7965. }
  7966. #endif
  7967.  
  7968.  
  7969. /*****************************************************************************
  7970. *
  7971. * FUNCTION
  7972. *
  7973. * INPUT
  7974. *   
  7975. * OUTPUT
  7976. *   
  7977. * RETURNS
  7978. *   
  7979. * AUTHOR
  7980. *   
  7981. * DESCRIPTION
  7982. *
  7983. * CHANGES
  7984. *
  7985. ******************************************************************************/
  7986.  
  7987. static void Parse_Global_Settings()
  7988. {
  7989.   char *optsString;
  7990.  
  7991.    Parse_Begin();
  7992.    EXPECT
  7993. #ifdef PostProcessPatch
  7994.      CASE (POST_PROCESS_TOKEN)
  7995. #ifdef UnofficialBlocking
  7996.        parseUnofficialFeature(40);
  7997. #endif
  7998.        Parse_Post_Process();
  7999.      END_CASE
  8000. #endif
  8001.  
  8002. #ifdef MotionBlurPatch
  8003.      CASE (MOTION_BLUR_TOKEN)
  8004. #ifdef UnofficialBlocking
  8005.        parseUnofficialFeature(30);
  8006. #endif
  8007.        if (parsedMotionBlurObject)
  8008.          Error("motion_blur in global_settings must preceed all motion_blur objects.\n");
  8009.  
  8010.        opts.motionBlurCount = (int)Parse_Float();
  8011.        Parse_Comma();
  8012.        opts.blurClockDelta = Parse_Float();
  8013.  
  8014.        if(opts.motionBlurCount<=1)
  8015.          Error("motion blur count must be greater than 1.\n");
  8016.        if(opts.blurClockDelta<=0)
  8017.          Error("blur clock delta must be greater than zero.\n");
  8018.      END_CASE
  8019. #endif
  8020.      CASE (IRID_WAVELENGTH_TOKEN)
  8021.        Parse_Colour (Frame.Irid_Wavelengths);
  8022.      END_CASE
  8023.  
  8024.      CASE (ASSUMED_GAMMA_TOKEN)
  8025.      {
  8026.        DBL AssumedGamma;
  8027.        AssumedGamma = Parse_Float ();
  8028.  
  8029.        if (fabs(AssumedGamma - opts.DisplayGamma) < 0.1)
  8030.        {
  8031.          opts.GammaFactor = 1.0;
  8032.          opts.Options &= ~GAMMA_CORRECT; /* turn off gamma correction */
  8033.        }
  8034.        else
  8035.        {
  8036.          opts.GammaFactor = AssumedGamma/opts.DisplayGamma;
  8037.          opts.Options |= GAMMA_CORRECT; /* turn on gamma correction */
  8038.        }
  8039.      }
  8040.      END_CASE
  8041.  
  8042.      CASE (MAX_TRACE_LEVEL_TOKEN)
  8043.        Max_Trace_Level = (int) Parse_Float ();
  8044.      END_CASE
  8045.  
  8046.      CASE (ADC_BAILOUT_TOKEN)
  8047.        ADC_Bailout = Parse_Float ();
  8048.      END_CASE
  8049.  
  8050.      CASE (NUMBER_OF_WAVES_TOKEN)
  8051.        Number_Of_Waves = (int) Parse_Float ();
  8052.        if(Number_Of_Waves == 0)
  8053.        {
  8054.          Warn(0, "Illegal Value: Number_Of_Waves = 0. Changed to 1.");
  8055.          Number_Of_Waves = 1;
  8056.        }
  8057.      END_CASE
  8058.  
  8059.      CASE (MAX_INTERSECTIONS)
  8060.        Max_Intersections = (int)Parse_Float ();
  8061.      END_CASE
  8062.  
  8063.      CASE (AMBIENT_LIGHT_TOKEN)
  8064.        Parse_Colour (Frame.Ambient_Light);
  8065.      END_CASE
  8066.  
  8067.      /* NK opts 1999 - adding options to parser */
  8068.      CASE (INI_OPTION_TOKEN)
  8069. #ifdef UnofficialBlocking
  8070.        parseUnofficialFeature(30);
  8071. #endif
  8072.        optsString = Parse_String();
  8073.        parse_option_line(optsString);
  8074.        POV_FREE(optsString);
  8075.      END_CASE
  8076.      /* NK ---- */
  8077.  
  8078.      /* NK phmap */
  8079.      CASE (PHOTONS_TOKEN)
  8080. #ifdef UnofficialBlocking
  8081.        parseUnofficialFeature(30);
  8082. #endif
  8083.        Parse_Begin();
  8084.        EXPECT
  8085.          CASE(RADIUS_TOKEN)
  8086.            photonOptions.photonMap.minGatherRad = Parse_Float();
  8087.          END_CASE
  8088.  
  8089.          CASE(SPACING_TOKEN)
  8090.            photonOptions.surfaceSeparation = Parse_Float();
  8091.          END_CASE
  8092.  
  8093.          CASE(GLOBAL_TOKEN)
  8094.            photonOptions.globalCount = (int)Parse_Float();
  8095.          END_CASE
  8096.          
  8097.          CASE (REFLECTION_BLUR_TOKEN)
  8098.            photonOptions.photonReflectionBlur = (int)Parse_Float();
  8099.          END_CASE
  8100.  
  8101.          CASE (EXPAND_THRESHOLDS_TOKEN)
  8102.            photonOptions.expandTolerance = Parse_Float(); Parse_Comma();
  8103.            photonOptions.minExpandCount = Parse_Float();
  8104.            if (photonOptions.expandTolerance<0.0)
  8105.            {
  8106.              Warning(100,"The first parameter of expand_thresholds must be greater than or equal to 0. Setting it to 0 now.\n");
  8107.              photonOptions.expandTolerance = 0.0;
  8108.            }
  8109.            if (photonOptions.minExpandCount<0)
  8110.            {
  8111.              Warning(100,"The second parameter of expand_thresholds must be greater than or equal to 0. Setting it to 0 now.\n");
  8112.              photonOptions.minExpandCount = 0;
  8113.            }
  8114.          END_CASE
  8115.  
  8116.          CASE (RANGE_DIVIDER_TOKEN)
  8117.            photonOptions.photonMap.rangeSelector = Parse_Float();
  8118.          END_CASE
  8119.  
  8120.          CASE (GATHER_TOKEN)
  8121.            photonOptions.minGatherCount = (int)Parse_Float();
  8122.            Parse_Comma();
  8123.            photonOptions.maxGatherCount = (int)Parse_Float();
  8124.          END_CASE
  8125.  
  8126.          CASE (JITTER_TOKEN)
  8127.            photonOptions.jitter = Parse_Float();
  8128.          END_CASE
  8129.  
  8130.          CASE (COUNT_TOKEN)
  8131.            photonOptions.surfaceCount = (int)Parse_Float();
  8132.          END_CASE
  8133.  
  8134.          CASE (AUTOSTOP_TOKEN)
  8135.            photonOptions.autoStopPercent = Parse_Float();
  8136.          END_CASE
  8137.  
  8138.          CASE (ADC_BAILOUT_TOKEN)
  8139.            photonOptions.ADC_Bailout = Parse_Float ();
  8140.          END_CASE
  8141.  
  8142.          CASE (MAX_TRACE_LEVEL_TOKEN)
  8143.            photonOptions.Max_Trace_Level = Parse_Float();
  8144.          END_CASE
  8145.  
  8146.          CASE(LOAD_FILE_TOKEN)
  8147.            if(photonOptions.fileName)
  8148.            {
  8149.              if(photonOptions.loadFile)
  8150.                Warn(100,"Filename already given, using new name\n");
  8151.              else
  8152.                Warn(100,"Cannot both load and save photon map. Now switching to load mode.\n");
  8153.              POV_FREE(photonOptions.fileName);
  8154.            }
  8155.            photonOptions.fileName = Parse_String();
  8156.            photonOptions.loadFile = TRUE;
  8157.          END_CASE
  8158.  
  8159.          CASE(SAVE_FILE_TOKEN)
  8160.            if(photonOptions.fileName)
  8161.            {
  8162.              if(!photonOptions.loadFile)
  8163.                Warn(100,"Filename already given, using new name\n");
  8164.              else
  8165.                Warn(100,"Cannot both load and save photon map. Now switching to save mode.\n");
  8166.              POV_FREE(photonOptions.fileName);
  8167.            }
  8168.            photonOptions.fileName = Parse_String();
  8169.            photonOptions.loadFile = FALSE;
  8170.          END_CASE
  8171.  
  8172.          CASE(MEDIA_TOKEN)
  8173.            photonOptions.maxMediaSteps = (int)Parse_Float(); Parse_Comma();
  8174.            if (photonOptions.maxMediaSteps<0)
  8175.              Error("max_media_steps must be non-negative.\n");
  8176.  
  8177.            photonOptions.mediaSpacingFactor = Allow_Float(1.0);
  8178.            if (photonOptions.mediaSpacingFactor <= 0.0)
  8179.              Error("media_spacing_factor must be greater than zero.\n");
  8180.          END_CASE
  8181.  
  8182.          OTHERWISE
  8183.            UNGET
  8184.            EXIT
  8185.          END_CASE
  8186.        END_EXPECT
  8187.  
  8188.        /* max_gather_count = 0  means no photon maps */
  8189.        if (photonOptions.maxGatherCount > 0)
  8190.          photonOptions.photonsEnabled = TRUE;
  8191.        else
  8192.          photonOptions.photonsEnabled = FALSE;
  8193.  
  8194.        if(photonOptions.photonsEnabled)
  8195.        {
  8196.          /* apply defaults if minimums are not specified */
  8197.          if (photonOptions.minGatherCount == 0)
  8198.            photonOptions.minGatherCount = 20;
  8199.  
  8200.          /* check for range errors */
  8201.          if (photonOptions.minGatherCount < 0)
  8202.            Error("min_gather_count cannot be negative.\n");
  8203.          if (photonOptions.maxGatherCount < 0)
  8204.            Error("max_gather_count cannot be negative.\n");
  8205.          if (photonOptions.minGatherCount > photonOptions.maxGatherCount)
  8206.            Error("min_gather_count must be less than max_gather_count.\n");
  8207.        }
  8208.  
  8209.        Parse_End();
  8210.      END_CASE
  8211.      /* NK ---- */
  8212.  
  8213.  
  8214.      CASE (RADIOSITY_TOKEN)
  8215.        Experimental_Flag |= EF_RADIOS;
  8216.        /* NK rad */
  8217.        opts.Radiosity_Enabled = TRUE;
  8218.        /* NK ---- */
  8219.        Parse_Begin();
  8220.        EXPECT
  8221.          CASE(LOAD_FILE_TOKEN)
  8222.            if(opts.Radiosity_Load_File_Name)
  8223.            {
  8224.              Warn(100,"Filename already given, using new name\n");
  8225.              POV_FREE(opts.Radiosity_Load_File_Name);
  8226.            }
  8227.            opts.Radiosity_Load_File_Name = Parse_String();
  8228.          END_CASE
  8229.  
  8230.          CASE(SAVE_FILE_TOKEN)
  8231.            if(opts.Radiosity_Save_File_Name)
  8232.            {
  8233.              Warn(100,"Filename already given, using new name\n");
  8234.              POV_FREE(opts.Radiosity_Save_File_Name);
  8235.            }
  8236.            opts.Radiosity_Save_File_Name = Parse_String();
  8237.          END_CASE
  8238.  
  8239.          CASE(ALWAYS_SAMPLE_TOKEN)
  8240.            opts.Radiosity_Add_On_Final_Trace = (int)Parse_Float();
  8241.          END_CASE
  8242.  
  8243.          CASE (PRETRACE_START_TOKEN)
  8244.            opts.radPretraceStart = Parse_Float();
  8245.          END_CASE
  8246.  
  8247.          CASE (PRETRACE_END_TOKEN)
  8248.            opts.radPretraceEnd = Parse_Float();
  8249.          END_CASE
  8250.  
  8251.          CASE (BRIGHTNESS_TOKEN)
  8252.            if ((opts.Radiosity_Brightness = Parse_Float()) <= 0.0)
  8253.            {
  8254.               Error("Radiosity brightness must be a positive number.");
  8255.            }
  8256.          END_CASE
  8257.  
  8258.          CASE (COUNT_TOKEN)
  8259.            if (( opts.Radiosity_Count = (int)Parse_Float()) <= 0)
  8260.            {
  8261.              Error("Radiosity count must be a positive number.");
  8262.            }
  8263.            if ( opts.Radiosity_Count > 1600)
  8264.            {
  8265.              Error("Radiosity count can not be more than 1600.");
  8266.              opts.Radiosity_Count = 1600;
  8267.            }
  8268.          END_CASE
  8269.  
  8270.          CASE (DISTANCE_MAXIMUM_TOKEN)
  8271.            if (( opts.Radiosity_Dist_Max = Parse_Float()) < 0.0)
  8272.            {
  8273.              Error("Radiosity distance maximum must be a positive number.");
  8274.            }
  8275.          END_CASE
  8276.  
  8277.          CASE (ERROR_BOUND_TOKEN)
  8278.            if (( opts.Radiosity_Error_Bound = Parse_Float()) <= 0.0)
  8279.            {
  8280.              Error("Radiosity error bound must be a positive number.");
  8281.            }
  8282.          END_CASE
  8283.  
  8284.          CASE (GRAY_THRESHOLD_TOKEN)
  8285.            opts.Radiosity_Gray = Parse_Float();
  8286.            if (( opts.Radiosity_Gray < 0.0) || ( opts.Radiosity_Gray > 1.0))
  8287.            {
  8288.               Error("Radiosity gray threshold must be from 0.0 to 1.0.");
  8289.            }
  8290.          END_CASE
  8291.  
  8292.          CASE (LOW_ERROR_FACTOR_TOKEN)
  8293.            if (( opts.Radiosity_Low_Error_Factor = Parse_Float()) <= 0.0)
  8294.            {
  8295.              Error("Radiosity low error factor must be a positive number.");
  8296.            }
  8297.          END_CASE
  8298.  
  8299.          CASE (MINIMUM_REUSE_TOKEN)
  8300.            if (( opts.Radiosity_Min_Reuse = Parse_Float()) < 0.0)
  8301.            {
  8302.               Error("Radiosity min reuse can not be a negative number.");
  8303.            }
  8304.          END_CASE
  8305.  
  8306.          CASE (NEAREST_COUNT_TOKEN)
  8307.            opts.Radiosity_Nearest_Count = (int)Parse_Float();
  8308.            if (( opts.Radiosity_Nearest_Count < 1) ||
  8309.                ( opts.Radiosity_Nearest_Count > MAX_NEAREST_COUNT))
  8310.            {
  8311.               Error("Radiosity nearest count must be a value from 1 to %ld.", (long)MAX_NEAREST_COUNT);
  8312.            }
  8313.          END_CASE
  8314.  
  8315.          CASE (RECURSION_LIMIT_TOKEN)
  8316.            if (( opts.Radiosity_Recursion_Limit = (int)Parse_Float()) <= 0)
  8317.            {
  8318.               Error("Radiosity recursion limit must be a positive number.");
  8319.            }
  8320.          END_CASE
  8321.  
  8322.          /* NK radiosity */
  8323.          CASE (MAX_SAMPLE_TOKEN)
  8324. #ifdef UnofficialBlocking
  8325.            parseUnofficialFeature(30);
  8326. #endif
  8327.            opts.Maximum_Sample_Brightness = Parse_Float();
  8328.          END_CASE
  8329.  
  8330.          CASE (ADC_BAILOUT_TOKEN)
  8331. #ifdef UnofficialBlocking
  8332.            parseUnofficialFeature(30);
  8333. #endif
  8334.            if (( opts.Radiosity_ADC_Bailout = Parse_Float()) <= 0)
  8335.            {
  8336.               Error("ADC Bailout must be a positive number.");
  8337.            }
  8338.          END_CASE
  8339.  
  8340.          CASE (TNORMAL_TOKEN)
  8341. #ifdef UnofficialBlocking
  8342.            parseUnofficialFeature(30);
  8343. #endif
  8344.            opts.Radiosity_Use_Normal = (int)Parse_Float();
  8345.          END_CASE
  8346.  
  8347.          CASE (MEDIA_TOKEN)
  8348. #ifdef UnofficialBlocking
  8349.            parseUnofficialFeature(30);
  8350. #endif
  8351.            opts.Radiosity_Use_Media = (int)Parse_Float();
  8352.          END_CASE
  8353.  
  8354. #ifdef MotionBlurPatch
  8355.          CASE (MOTION_BLUR_TOKEN)
  8356. #ifdef UnofficialBlocking
  8357.            parseUnofficialFeature(30);
  8358. #endif
  8359.            opts.Radiosity_Use_Motion_Blur = (int)Parse_Float();
  8360.          END_CASE
  8361.          /* NK ---- */
  8362. #endif
  8363.          OTHERWISE
  8364.            UNGET
  8365.            EXIT
  8366.          END_CASE
  8367.        END_EXPECT
  8368.        Parse_End();
  8369.      END_CASE
  8370.  
  8371.      CASE (STRING_ENCODING_TOKEN)
  8372.         {
  8373.         /*YS sept 17 2000 Memory leak */
  8374.          char *tempstring=Parse_String();
  8375.        String_Encoding = uniGetEncodingByName( tempstring );
  8376.           POV_FREE(tempstring); /*YS sept 17 Memory leak */
  8377.          }
  8378.        if ( !uniIsEncodingValid( String_Encoding ) ) {
  8379.            Error( "Invalid value for string_encoding." );
  8380.        }
  8381.      END_CASE
  8382.  
  8383.      CASE (HF_GRAY_16_TOKEN)
  8384.        if (Allow_Float(1.0)>EPSILON)     
  8385.        {
  8386.          opts.Options |= HF_GRAY_16;
  8387.          opts.PaletteOption = GREY;        /* Force gray scale preview */
  8388.          Output_File_Handle->file_type = HF_FTYPE;
  8389.        }
  8390.      END_CASE
  8391.  
  8392.      /* Added by MBP to support reflection-blur */
  8393.      CASE (REFLECTION_SAMPLES_TOKEN)
  8394.        Default_Texture->Finish->Reflection_Samples = (int) Parse_Float();
  8395.      END_CASE
  8396.  
  8397.      /* Added by MBP  6/27/98 */
  8398.      CASE (REFLECTION_BLUR_MAX_TOKEN)
  8399.        opts.Reflection_Blur_Max = (int) Parse_Float();
  8400.      END_CASE
  8401.      CASE (REFLECTION_BLUR_MAX_ADC_TOKEN)
  8402.        opts.Reflection_Blur_Max_ADC = Parse_Float();
  8403.      END_CASE
  8404.  
  8405.  
  8406.      OTHERWISE
  8407.        UNGET
  8408.        EXIT
  8409.      END_CASE
  8410.    END_EXPECT
  8411.    Parse_End();
  8412. }
  8413.  
  8414.  
  8415. #ifdef GlowPatch
  8416. /*****************************************************************************
  8417. *
  8418. * FUNCTION
  8419. *
  8420. * INPUT
  8421. *   
  8422. * OUTPUT
  8423. *   
  8424. * RETURNS
  8425. *   
  8426. * AUTHOR
  8427. *   
  8428. * DESCRIPTION
  8429. *
  8430. * CHANGES
  8431. *
  8432. ******************************************************************************/
  8433.  
  8434. void Parse_Glow(GLOW * Glow)
  8435. {
  8436.     MATRIX Matrix;
  8437.     int Warped = FALSE;
  8438.     TRANSFORM * Trans = Create_Transform();
  8439.     TRANSFORM * Temp_Trans = Create_Transform();
  8440.     TRANSFORM * Trans2;
  8441.     TURB * Local_Turb = NULL;
  8442.     VECTOR Local_Vector;
  8443.     TPATTERN * Warps = (TPATTERN *)POV_MALLOC(sizeof(TPATTERN), "TPATTERN");
  8444.     Init_TPat_Fields(Warps);
  8445.     Warps->Type = BOZO_PATTERN;/*Set it to a pattern type to allow turbulence*/
  8446.  
  8447.     Parse_Begin();
  8448.  
  8449.     EXPECT
  8450.         CASE(SIZE_TOKEN)
  8451.             Glow->Size = Parse_Float();
  8452.         END_CASE
  8453.  
  8454.         CASE(RADIUS_TOKEN)
  8455.             Glow->Cutoff_Radius = Parse_Float();
  8456.         END_CASE
  8457.  
  8458.         CASE(FADE_POWER_TOKEN)
  8459.             Glow->fade_pow = Parse_Float();
  8460.         END_CASE
  8461.  
  8462.         CASE(TYPE_TOKEN)
  8463.             Glow->Glow_Type = (int)Parse_Float();
  8464.             /*YS sept 22 2000 added type checking*/
  8465.             if(Glow->Glow_Type < 0 || Glow->Glow_Type > 3)
  8466.                 Error("\nUnknown glow type.\n");
  8467.             /*YS*/
  8468.         END_CASE
  8469.  
  8470.         CASE(LOCATION_TOKEN)
  8471.             Parse_Vector(Glow->Center);
  8472.         END_CASE
  8473.  
  8474.         CASE(COLOUR_TOKEN)
  8475.             Parse_Colour(Glow->Colour);
  8476.         END_CASE
  8477.  
  8478.         CASE (WARP_TOKEN)
  8479.             Warped = TRUE;
  8480.             Parse_Begin();
  8481.             Parse_Warp(&(Warps->Warps));
  8482.             Parse_End();
  8483.         END_CASE
  8484.  
  8485.         CASE (TRANSLATE_TOKEN)
  8486.             Parse_Vector(Local_Vector);
  8487.             Compute_Translation_Transform(Temp_Trans, Local_Vector);
  8488.             Compose_Transforms(Trans, Temp_Trans);
  8489.         END_CASE
  8490.  
  8491.         CASE (ROTATE_TOKEN)
  8492.             Parse_Vector(Local_Vector);
  8493.             Compute_Rotation_Transform(Temp_Trans, Local_Vector);
  8494.             Compose_Transforms(Trans, Temp_Trans);
  8495.         END_CASE
  8496.  
  8497.         CASE (SCALE_TOKEN)
  8498.             Parse_Scale_Vector(Local_Vector);
  8499.             Compute_Scaling_Transform(Trans, Local_Vector);
  8500.             Compose_Transforms(Trans, Temp_Trans);
  8501.         END_CASE
  8502.  
  8503.         CASE (MATRIX_TOKEN)
  8504.             Parse_Matrix(Matrix);
  8505.             Compute_Matrix_Transform(Temp_Trans, Matrix);
  8506.             Compose_Transforms(Trans, Temp_Trans);
  8507.         END_CASE
  8508.  
  8509.         CASE (TRANSFORM_TOKEN)
  8510.             Trans2 = Parse_Transform();
  8511.             Compose_Transforms(Trans, Trans2);
  8512.             Destroy_Transform(Trans2);
  8513.         END_CASE
  8514.  
  8515.         OTHERWISE
  8516.             UNGET
  8517.             EXIT
  8518.         END_CASE
  8519.     END_EXPECT
  8520.  
  8521.     Parse_End();
  8522.     if(Warped == TRUE)
  8523.     {    
  8524.         Glow->Warps = Warps;
  8525.     }
  8526.     else
  8527.     {
  8528.         Destroy_TPat_Fields(Warps);
  8529.         POV_FREE(Warps);
  8530.     }
  8531.     Transform_Glow(Glow, Trans);
  8532.     Destroy_Transform(Trans);
  8533.     Destroy_Transform(Temp_Trans);
  8534. }
  8535. #endif
  8536.  
  8537.  
  8538. /*****************************************************************************
  8539. *
  8540. * FUNCTION
  8541. *
  8542. * INPUT
  8543. *   
  8544. * OUTPUT
  8545. *   
  8546. * RETURNS
  8547. *   
  8548. * AUTHOR
  8549. *   
  8550. * DESCRIPTION
  8551. *
  8552. * CHANGES
  8553. *
  8554. ******************************************************************************/
  8555.  
  8556. void Destroy_Single_Object (OBJECT **ObjectPtr);
  8557. /* NK persist - added destroyAllObjects */
  8558. void Destroy_Frame(int destroyAllObjects)
  8559. {
  8560.     FOG *Fog, *Next_Fog;
  8561.     RAINBOW *Rainbow, *Next_Rainbow;
  8562.  
  8563.     /* can the camera have a name? */
  8564.     Destroy_Camera (Frame.Camera); Frame.Camera=NULL;
  8565.  
  8566.     /* Destroy fogs. [DB 12/94] */
  8567.  
  8568.     for (Fog = Frame.Fog; Fog != NULL;)
  8569.     {
  8570.       Next_Fog = Fog->Next;
  8571.  
  8572.       Destroy_Fog(Fog);
  8573.  
  8574.       Fog = Next_Fog;
  8575.     }
  8576.     
  8577.     Frame.Fog = NULL;
  8578.  
  8579.     /* Destroy rainbows. [DB 12/94] */
  8580.  
  8581.     for (Rainbow = Frame.Rainbow; Rainbow != NULL;)
  8582.     {
  8583.       Next_Rainbow = Rainbow->Next;
  8584.  
  8585.       Destroy_Rainbow(Rainbow);
  8586.  
  8587.       Rainbow = Next_Rainbow;
  8588.     }
  8589.  
  8590.     Frame.Rainbow = NULL;
  8591.  
  8592.     /* Destroy skysphere. [DB 12/94] */
  8593.  
  8594.     Destroy_Skysphere(Frame.Skysphere);
  8595.  
  8596.     Frame.Skysphere = NULL;
  8597.  
  8598.     /* Destroy atmosphere. [DB 1/95] */
  8599.  
  8600.     Destroy_Media(Frame.Atmosphere);
  8601.  
  8602.     Frame.Atmosphere = NULL;
  8603.  
  8604. #ifdef GlowPatch
  8605.     if(Frame.NumOfGlows > 0)
  8606.     {
  8607.         Destroy_Glow_List(Frame.Glows);
  8608.         Frame.Glows = NULL;
  8609.         Frame.NumOfGlows = 0;
  8610.     }
  8611. #endif
  8612.  
  8613.     /* NK persist */
  8614.     if(destroyAllObjects)
  8615.     {
  8616.       if (Frame.Objects != NULL) {
  8617.          Destroy_Object (Frame.Objects);
  8618.          Frame.Objects = NULL;
  8619.          Frame.Light_Sources = NULL;
  8620.       }
  8621.     }
  8622.     else
  8623.     {
  8624.       OBJECT *obj;
  8625.  
  8626.       while(Frame.Objects != NULL)
  8627.       {
  8628.         if (Frame.Objects->Label == NULL)
  8629.           Destroy_Single_Object(&Frame.Objects);
  8630.         else
  8631.           break;
  8632.       }
  8633.  
  8634.       obj = Frame.Objects;
  8635.       while(obj!=NULL && obj->Sibling != NULL)
  8636.       {
  8637.         if (obj->Sibling->Label == NULL)
  8638.           Destroy_Single_Object(&(obj->Sibling));
  8639.         else
  8640.           obj=obj->Sibling;
  8641.       }
  8642.     }
  8643. }
  8644.  
  8645.  
  8646.  
  8647.  
  8648. /*****************************************************************************
  8649. *
  8650. * FUNCTION
  8651. *
  8652. * INPUT
  8653. *
  8654. * OUTPUT
  8655. *
  8656. * RETURNS
  8657. *
  8658. * AUTHOR
  8659. *
  8660. * DESCRIPTION
  8661. *
  8662. * CHANGES
  8663. *
  8664. ******************************************************************************/
  8665.  
  8666. static void Parse_Camera (CAMERA **Camera_Ptr)
  8667. {
  8668.    int i;
  8669.    DBL Direction_Length = 1.0, Up_Length, Right_Length, Handedness;
  8670.    DBL k1, k2, k3;
  8671.    VECTOR Local_Vector;
  8672.    MATRIX Local_Matrix;
  8673.    TRANSFORM Local_Trans;
  8674.    CAMERA *New;
  8675.  
  8676.    Parse_Begin ();
  8677.  
  8678.    EXPECT
  8679.      CASE (CAMERA_ID_TOKEN)
  8680.        Destroy_Camera(*Camera_Ptr);
  8681.        *Camera_Ptr = Copy_Camera ((CAMERA *) Token.Data);
  8682.        EXIT
  8683.      END_CASE
  8684.  
  8685.      OTHERWISE
  8686.        UNGET
  8687.        EXIT
  8688.      END_CASE
  8689.    END_EXPECT
  8690.  
  8691.    New = *Camera_Ptr;
  8692.  
  8693.    EXPECT
  8694.      /* Get camera type. [DB 7/94] */
  8695.  
  8696.      CASE (PERSPECTIVE_TOKEN)
  8697.        New->Type = PERSPECTIVE_CAMERA;
  8698.      END_CASE
  8699.  
  8700.      CASE (ORTHOGRAPHIC_TOKEN)
  8701.        New->Type = ORTHOGRAPHIC_CAMERA;
  8702.        /* 
  8703.         * Resize right and up vector to get the same image 
  8704.         * area as we get with the perspective camera. 
  8705.         */
  8706.        VSub(Local_Vector, New->Look_At, New->Location);
  8707.        VLength(k1, Local_Vector);
  8708.        VLength(k2, New->Direction);
  8709.        if ((k1 > EPSILON) && (k2 > EPSILON))
  8710.        {
  8711.          VScaleEq(New->Right, k1 / k2);
  8712.          VScaleEq(New->Up, k1 / k2);
  8713.        }
  8714.      END_CASE
  8715.  
  8716.      CASE (FISHEYE_TOKEN)
  8717.        New->Type = FISHEYE_CAMERA;
  8718.      END_CASE
  8719.  
  8720.      CASE (ULTRA_WIDE_ANGLE_TOKEN)
  8721.        New->Type = ULTRA_WIDE_ANGLE_CAMERA;
  8722.      END_CASE
  8723.  
  8724.      CASE (OMNIMAX_TOKEN)
  8725.        New->Type = OMNIMAX_CAMERA;
  8726.      END_CASE
  8727.  
  8728.      CASE (PANORAMIC_TOKEN)
  8729.        New->Type = PANORAMIC_CAMERA;
  8730.      END_CASE
  8731.  
  8732.      CASE (CYLINDER_TOKEN)
  8733.        i = (int)Parse_Float();
  8734.        switch (i)
  8735.        {
  8736.          case 1: New->Type = CYL_1_CAMERA; break;
  8737.          case 2: New->Type = CYL_2_CAMERA; break;
  8738.          case 3: New->Type = CYL_3_CAMERA; break;
  8739.          case 4: New->Type = CYL_4_CAMERA; break;
  8740.        }       
  8741.      END_CASE
  8742.  
  8743.      /* Spherical camera [MH 6/99] */
  8744.  
  8745.      CASE2 (SPHERICAL_CAMERA_TOKEN,SPHERICAL_TOKEN)
  8746.        New->Type = SPHERICAL_CAMERA;
  8747.      END_CASE
  8748.  
  8749.      CASE (V_ANGLE_TOKEN)
  8750.        New->V_Angle = Parse_Float();
  8751.  
  8752.      if (New->V_Angle < 0.0)
  8753.      {
  8754.        Error("Negative v_angle.");
  8755.      }
  8756.  
  8757.      END_CASE
  8758.  
  8759.      CASE (H_ANGLE_TOKEN)
  8760.        New->H_Angle = Parse_Float();
  8761.  
  8762.      if (New->H_Angle < 0.0)
  8763.      {
  8764.        Error("Negative h_angle.");
  8765.      }
  8766.  
  8767.      END_CASE
  8768.  
  8769.  
  8770.      /* Read viewing angle. Scale direction vector if necessary. [DB 7/94] */
  8771.  
  8772.      CASE (ANGLE_TOKEN)
  8773.        New->Angle = Parse_Float();
  8774.  
  8775.        if (New->Angle < 0.0)
  8776.        {
  8777.          Error("Negative viewing angle.");
  8778.        }
  8779.  
  8780.        if (New->Type == PERSPECTIVE_CAMERA)
  8781.        {
  8782.          if (New->Angle >= 180.0)
  8783.          {
  8784.            Error("Viewing angle has to be smaller than 180 degrees.");
  8785.          }
  8786.  
  8787.          VNormalize(New->Direction, New->Direction);
  8788.  
  8789.          VLength (Right_Length, New->Right);
  8790.  
  8791.          Direction_Length = Right_Length / tan(New->Angle * M_PI_360)/2.0;
  8792.  
  8793.          VScaleEq(New->Direction, Direction_Length);
  8794.        }
  8795.      END_CASE
  8796.  
  8797.  
  8798.      /* Read primary ray pertubation. [DB 7/94] */
  8799.  
  8800.      CASE (TNORMAL_TOKEN)
  8801.        Parse_Begin ();
  8802.        Parse_Tnormal(&(New->Tnormal));
  8803.        Parse_End ();
  8804.      END_CASE
  8805.  
  8806.      CASE (LOCATION_TOKEN)
  8807.        Parse_Vector(New->Location);
  8808.      END_CASE
  8809.  
  8810.      CASE (DIRECTION_TOKEN)
  8811.        Parse_Vector(New->Direction);
  8812.      END_CASE
  8813.  
  8814.      CASE (UP_TOKEN)
  8815.        Parse_Vector(New->Up);
  8816.      END_CASE
  8817.  
  8818.      CASE (RIGHT_TOKEN)
  8819.        Parse_Vector(New->Right);
  8820.      END_CASE
  8821.  
  8822.      CASE (SKY_TOKEN)
  8823.        Parse_Vector(New->Sky);
  8824.      END_CASE
  8825.  
  8826.      CASE (LOOK_AT_TOKEN)
  8827.        VLength (Direction_Length, New->Direction);
  8828.        VLength (Up_Length,        New->Up);
  8829.        VLength (Right_Length,     New->Right);
  8830.        VCross  (Local_Vector,     New->Up,        New->Direction);
  8831.        VDot    (Handedness,       Local_Vector,   New->Right);
  8832.  
  8833.        Parse_Vector (New->Direction);
  8834.        Assign_Vector(New->Look_At, New->Direction);
  8835.  
  8836.        VSub          (New->Direction, New->Direction, New->Location);
  8837.  
  8838.        /* Check for zero length direction vector. */
  8839.  
  8840.        if (VSumSqr(New->Direction) < EPSILON)
  8841.        {
  8842.          Error("Camera location and look_at point must be different.\n");
  8843.        }
  8844.        
  8845.        VNormalize    (New->Direction, New->Direction);
  8846.  
  8847.        /* Save Right vector */
  8848.  
  8849.        Assign_Vector (Local_Vector, New->Right);
  8850.  
  8851.        VCross        (New->Right, New->Sky, New->Direction);
  8852.  
  8853.        /* Avoid DOMAIN error (from Terry Kanakis) */
  8854.  
  8855.        if((fabs(New->Right[X]) < EPSILON) &&
  8856.           (fabs(New->Right[Y]) < EPSILON) &&
  8857.           (fabs(New->Right[Z]) < EPSILON))
  8858.        {
  8859.          /* Restore Right vector*/
  8860.  
  8861.          Assign_Vector (New->Right, Local_Vector);
  8862.        }
  8863.  
  8864.        VNormalize (New->Right,     New->Right);
  8865.        VCross     (New->Up,        New->Direction, New->Right);
  8866.        VScale     (New->Direction, New->Direction, Direction_Length);
  8867.  
  8868.        if (Handedness > 0.0)
  8869.          VScaleEq (New->Right, Right_Length)
  8870.        else
  8871.          VScaleEq (New->Right, -Right_Length);
  8872.  
  8873.        VScaleEq(New->Up, Up_Length);
  8874.      END_CASE
  8875.  
  8876.      CASE (TRANSLATE_TOKEN)
  8877.        Parse_Vector (Local_Vector);
  8878.        Translate_Camera (New, Local_Vector);
  8879.      END_CASE
  8880.  
  8881.      CASE (ROTATE_TOKEN)
  8882.        Parse_Vector (Local_Vector);
  8883.        Rotate_Camera (New, Local_Vector);
  8884.      END_CASE
  8885.  
  8886.      CASE (SCALE_TOKEN)
  8887.        Parse_Scale_Vector (Local_Vector);
  8888.        Scale_Camera (New, Local_Vector);
  8889.      END_CASE
  8890.  
  8891.      CASE (TRANSFORM_TOKEN)
  8892. #ifndef TransformPatch /* Chris Huff april 2000 */
  8893.        GET(TRANSFORM_ID_TOKEN)
  8894.        Transform_Camera (New, (TRANSFORM *)Token.Data);
  8895. #else
  8896.        {
  8897.            TRANSFORM * Trans = Parse_Transform();
  8898.            Transform_Camera(New, Trans);
  8899.             /*YS sept 17 2000 Memory leak*/
  8900.             POV_FREE(Trans);
  8901.         }
  8902. #endif
  8903.      END_CASE
  8904.  
  8905.      CASE (MATRIX_TOKEN)
  8906.        Parse_Matrix (Local_Matrix);
  8907.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  8908.        Transform_Camera (New, &Local_Trans);
  8909.      END_CASE
  8910. #ifdef PostProcessInCameraPatch  /*Chris Huff post_process in camera patch*/
  8911.      CASE (POST_PROCESS_TOKEN)
  8912. #ifdef UnofficialBlocking
  8913.        parseUnofficialFeature(50);
  8914. #endif
  8915.        Parse_Post_Process();
  8916.      END_CASE
  8917. #endif
  8918.      /* Parse focal blur stuff. */
  8919.  
  8920.      CASE (BLUR_SAMPLES_TOKEN)
  8921.         New->Blur_Samples = Parse_Float();
  8922.         if (New->Blur_Samples <= 0)
  8923.         {
  8924.           Error("Illegal number of focal blur samples.\n");
  8925.         }
  8926.      END_CASE
  8927.  
  8928.      CASE (CONFIDENCE_TOKEN)
  8929.         k1 = Parse_Float();
  8930.         if ((k1 > 0.0) && (k1 < 1.0))
  8931.         {
  8932.           New->Confidence = k1;
  8933.         }
  8934.         else
  8935.         {
  8936.           Warn(0, "Illegal confidence value. Default is used.");
  8937.         }
  8938.      END_CASE
  8939.  
  8940.      CASE (VARIANCE_TOKEN)
  8941.         k1 = Parse_Float();
  8942.         if ((k1 >= 0.0) && (k1 <= 1.0))
  8943.         {
  8944.           New->Variance = k1;
  8945.         }
  8946.         else
  8947.         {
  8948.           Warn(0, "Illegal variance value. Default is used.");
  8949.         }
  8950.      END_CASE
  8951.  
  8952.      CASE (APERTURE_TOKEN)
  8953.         New->Aperture = Parse_Float();
  8954.      END_CASE
  8955.  
  8956.      CASE (FOCAL_POINT_TOKEN)
  8957.         Parse_Vector(Local_Vector);
  8958.         VSubEq(Local_Vector, New->Location);
  8959.         VLength (New->Focal_Distance, Local_Vector);
  8960.      END_CASE
  8961.  
  8962.      OTHERWISE
  8963.        UNGET
  8964.        EXIT
  8965.      END_CASE
  8966.    END_EXPECT
  8967.    Parse_End ();
  8968.  
  8969.    /* Make sure the focal distance hasn't been explicitly given */
  8970.    if ( New->Focal_Distance < 0.0 )
  8971.       New->Focal_Distance = Direction_Length;
  8972.    if ( New->Focal_Distance == 0.0 )
  8973.       New->Focal_Distance = 1.0;
  8974.  
  8975.    /* Print a warning message if vectors are not perpendicular. [DB 10/94] */
  8976.  
  8977.    VDot(k1, New->Right, New->Up);
  8978.    VDot(k2, New->Right, New->Direction);
  8979.    VDot(k3, New->Up, New->Direction);
  8980.  
  8981.    if ((fabs(k1) > EPSILON) || (fabs(k2) > EPSILON) || (fabs(k3) > EPSILON))
  8982.    {
  8983.      Warn(0, "Camera vectors are not perpendicular. "
  8984.                "Making look_at the last statement may help.");
  8985.    }
  8986. }
  8987.  
  8988.  
  8989.  
  8990. /*****************************************************************************
  8991. *
  8992. * FUNCTION
  8993. *
  8994. * INPUT
  8995. *
  8996. * OUTPUT
  8997. *
  8998. * RETURNS
  8999. *
  9000. * AUTHOR
  9001. *
  9002. * DESCRIPTION
  9003. *
  9004. * CHANGES
  9005. *
  9006. ******************************************************************************/
  9007.  
  9008. void Parse_Matrix(MATRIX Matrix)
  9009. {
  9010.   int i, j;
  9011.  
  9012.   EXPECT
  9013.     CASE (LEFT_ANGLE_TOKEN)
  9014.       Matrix[0][0] = Parse_Float();
  9015.       for (i = 0; i < 4; i++)
  9016.       {
  9017.         for (j = !i ? 1 : 0; j < 3; j++)
  9018.         {
  9019.           Parse_Comma();
  9020.  
  9021.           Matrix[i][j] = Parse_Float();
  9022.         }
  9023.  
  9024.         Matrix[i][3] = (i != 3 ? 0.0 : 1.0);
  9025.       }
  9026.       GET (RIGHT_ANGLE_TOKEN);
  9027.  
  9028.       /* Check to see that we aren't scaling any dimension by zero */
  9029.       for (i = 0; i < 3; i++)
  9030.       {
  9031.         if (fabs(Matrix[0][i]) < EPSILON && fabs(Matrix[1][i]) < EPSILON &&
  9032.             fabs(Matrix[2][i]) < EPSILON)
  9033.         {
  9034.           Warn(0,"Illegal matrix column: Scale by 0.0. Changed to 1.0.");
  9035.           Matrix[i][i] = 1.0;
  9036.         }
  9037.       }
  9038.       EXIT
  9039.     END_CASE
  9040.  
  9041.     OTHERWISE
  9042.       Parse_Error (LEFT_ANGLE_TOKEN);
  9043.     END_CASE
  9044.   END_EXPECT
  9045. }
  9046.  
  9047.  
  9048.  
  9049. /*****************************************************************************
  9050. *
  9051. * FUNCTION
  9052. *
  9053. * INPUT
  9054. *
  9055. * OUTPUT
  9056. *
  9057. * RETURNS
  9058. *
  9059. * AUTHOR
  9060. *
  9061. * DESCRIPTION
  9062. *
  9063. * CHANGES
  9064. *
  9065. ******************************************************************************/
  9066.  
  9067. #ifndef TransformPatch /* Chris Huff april 2000 */
  9068. static
  9069. TRANSFORM *Parse_Transform ()
  9070. {
  9071.    MATRIX Local_Matrix;
  9072.    TRANSFORM *New, Local_Trans;
  9073.    VECTOR Local_Vector;
  9074. #ifdef InverseTransformsPatch /*Chris Huff arpil 2000 */
  9075.    int isInverse = FALSE;
  9076. #endif
  9077.    Parse_Begin ();
  9078.    New = Create_Transform ();
  9079.  
  9080.    EXPECT
  9081. #ifdef InverseTransformsPatch /*Chris Huff arpil 2000 */
  9082.      CASE(INVERSE_TOKEN)
  9083.        isInverse = TRUE;
  9084.      END_CASE
  9085. #endif
  9086.      CASE(TRANSFORM_ID_TOKEN)
  9087.        Compose_Transforms (New, (TRANSFORM *)Token.Data);
  9088.      END_CASE
  9089.  
  9090.      CASE (TRANSFORM_TOKEN)
  9091.        GET(TRANSFORM_ID_TOKEN)
  9092.        Compose_Transforms(New, (TRANSFORM *)Token.Data);
  9093.      END_CASE
  9094.  
  9095.      CASE (TRANSLATE_TOKEN)
  9096.        Parse_Vector (Local_Vector);
  9097.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  9098.        Compose_Transforms (New, &Local_Trans);
  9099.      END_CASE
  9100.  
  9101.      CASE (ROTATE_TOKEN)
  9102.        Parse_Vector (Local_Vector);
  9103.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  9104.        Compose_Transforms (New, &Local_Trans);
  9105.      END_CASE
  9106.  
  9107.      CASE (SCALE_TOKEN)
  9108.        Parse_Scale_Vector (Local_Vector);
  9109.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  9110.        Compose_Transforms (New, &Local_Trans);
  9111.      END_CASE
  9112.  
  9113.      CASE (MATRIX_TOKEN)
  9114.        Parse_Matrix(Local_Matrix);
  9115.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  9116.        Compose_Transforms (New, &Local_Trans);
  9117.      END_CASE
  9118.  
  9119.      OTHERWISE
  9120.        UNGET
  9121.        EXIT
  9122.      END_CASE
  9123.    END_EXPECT
  9124.  
  9125.    Parse_End ();
  9126. #ifdef InverseTransformsPatch /*Chris Huff arpil 2000 */
  9127.    if(isInverse == TRUE)
  9128.    {
  9129.        MInvers(New->matrix, New->matrix);
  9130.        MInvers(New->inverse, New->inverse);
  9131.    }  
  9132. #endif
  9133.    return (New);
  9134.   }
  9135. #else
  9136. /*Chris Huff transform patch*/
  9137. TRANSFORM *Parse_Transform ()
  9138. {
  9139.     TRANSFORM * Trans = NULL;
  9140.     Get_Token();
  9141.     if(Token.Token_Id == TRANSFORM_ID_TOKEN)
  9142.     {
  9143.         /*using old "transform TRANS_IDENT" syntax*/
  9144.         Trans=Create_Transform();
  9145.        Compose_Transforms(Trans, (TRANSFORM *)Token.Data);
  9146.     }
  9147.     else
  9148.     {
  9149.         /*using new "transform {TRANS}" syntax*/
  9150.        Unget_Token();
  9151.        Trans = Parse_Transform_Block();
  9152.     }
  9153.     return Trans;
  9154. }
  9155.  
  9156. /*****************************************************************************
  9157. *
  9158. * FUNCTION
  9159. *
  9160. * INPUT
  9161. *
  9162. * OUTPUT
  9163. *
  9164. * RETURNS
  9165. *
  9166. * AUTHOR
  9167. *
  9168. * DESCRIPTION
  9169. *
  9170. * CHANGES
  9171. *
  9172. ******************************************************************************/
  9173.  
  9174. static/*Chris Huff transform patch*/
  9175. TRANSFORM *Parse_Transform_Block ()
  9176. {
  9177.    MATRIX Local_Matrix;
  9178.    TRANSFORM *New, Local_Trans;
  9179.    VECTOR Local_Vector;
  9180. #ifdef InverseTransformsPatch /*Chris Huff arpil 2000 */
  9181.    int isInverse = FALSE;
  9182. #endif
  9183.    Parse_Begin ();
  9184.    New = Create_Transform ();
  9185.  
  9186.    EXPECT
  9187. #ifdef InverseTransformsPatch /*Chris Huff arpil 2000 */
  9188.      CASE(INVERSE_TOKEN)
  9189.        isInverse = TRUE;
  9190.      END_CASE
  9191. #endif     
  9192.      CASE(TRANSFORM_ID_TOKEN)
  9193.        Compose_Transforms (New, (TRANSFORM *)Token.Data);
  9194.      END_CASE
  9195.  
  9196.      CASE (TRANSFORM_TOKEN)
  9197.        {
  9198.            TRANSFORM * Trans = Parse_Transform();
  9199.            Compose_Transforms(New, Trans);
  9200.        }
  9201.      END_CASE
  9202.  
  9203.      CASE (TRANSLATE_TOKEN)
  9204.        Parse_Vector (Local_Vector);
  9205.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  9206.        Compose_Transforms (New, &Local_Trans);
  9207.      END_CASE
  9208.  
  9209.      CASE (ROTATE_TOKEN)
  9210.        Parse_Vector (Local_Vector);
  9211.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  9212.        Compose_Transforms (New, &Local_Trans);
  9213.      END_CASE
  9214.  
  9215.      CASE (SCALE_TOKEN)
  9216.        Parse_Scale_Vector (Local_Vector);
  9217.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  9218.        Compose_Transforms (New, &Local_Trans);
  9219.      END_CASE
  9220.  
  9221.      CASE (MATRIX_TOKEN)
  9222.        Parse_Matrix(Local_Matrix);
  9223.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  9224.        Compose_Transforms (New, &Local_Trans);
  9225.      END_CASE
  9226.  
  9227.      OTHERWISE
  9228.        UNGET
  9229.        EXIT
  9230.      END_CASE
  9231.    END_EXPECT
  9232.  
  9233.    Parse_End ();
  9234. #ifdef InverseTransformsPatch /*Chris Huff arpil 2000 */
  9235.    if(isInverse == TRUE)
  9236.    {
  9237.        MInvers(New->matrix, New->matrix);
  9238.        MInvers(New->inverse, New->inverse);
  9239.    }
  9240. #endif
  9241.    return (New);
  9242.   }
  9243.  
  9244. #endif
  9245.  
  9246.  
  9247. /*****************************************************************************
  9248. *
  9249. * FUNCTION
  9250. *
  9251. * INPUT
  9252. *   
  9253. * OUTPUT
  9254. *   
  9255. * RETURNS
  9256. *   
  9257. * AUTHOR
  9258. *   
  9259. * DESCRIPTION
  9260. *
  9261. * CHANGES
  9262. *
  9263. ******************************************************************************/
  9264.  
  9265. #ifdef SetPatch
  9266. void Parse_Declare(int Modify_Only)
  9267. #else
  9268. void Parse_Declare ()
  9269. #endif
  9270. {
  9271.   int Previous=-1; /* tw */
  9272.   int Local_Index,Local_Flag;
  9273.   SYM_ENTRY *Temp_Entry;
  9274.   char local=0;
  9275.   
  9276.   /* NK 1999 - use $ for #declare - added PERCENT_TOKEN */
  9277.   /*Chris Huff 2000.8.30 - added #set */
  9278. #ifdef SetPatch
  9279.   Local_Flag = (Token.Token_Id==LOCAL_TOKEN || Token.Token_Id==PERCENT_TOKEN);
  9280.   if(Local_Flag)
  9281.   {
  9282.      Local_Index=Table_Index;
  9283.   }
  9284.   else
  9285.   {
  9286.      if(Token.Token_Id==SET_TOKEN || Modify_Only == TRUE)
  9287.      {
  9288.          /*Search for most recent table with an identifier with this name
  9289.          Parts copied from Read_Symbol*/
  9290.           int Idx;
  9291.           int Found = FALSE;
  9292.          
  9293.          Get_Token();
  9294.         /* Search tables from newest to oldest */
  9295.         for(Idx=Table_Index; Idx > 0; Idx--)
  9296.         {
  9297.             if(Find_Symbol(Idx, Token.Token_String) != NULL)
  9298.               {
  9299.                   Local_Index = Idx;
  9300.                   Found = TRUE;
  9301.                   break;
  9302.               }
  9303.         }
  9304.         if(Found != TRUE)
  9305.         {
  9306.             Error("#set cannot assign to uninitialized identifier %s.\n", Token.Token_String);
  9307.         }
  9308.          Unget_Token();
  9309.      }
  9310.      else
  9311.      {
  9312.          Local_Index=1;
  9313.      }
  9314.   }
  9315. #else
  9316.   if (Local_Flag=(Token.Token_Id==LOCAL_TOKEN || Token.Token_Id==PERCENT_TOKEN))
  9317.   {
  9318.      Local_Index=Table_Index;
  9319.   }
  9320.   else
  9321.   {
  9322.      Local_Index=1;
  9323.   }
  9324. #endif
  9325.   
  9326.   LValue_Ok = TRUE;
  9327.  
  9328.   EXPECT
  9329.     CASE (IDENTIFIER_TOKEN)
  9330.       Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
  9331.       Token.NumberPtr = &(Temp_Entry->Token_Number);
  9332.       Token.DataPtr   = &(Temp_Entry->Data);
  9333.       Previous        = Token.Token_Id;
  9334.       EXIT
  9335.     END_CASE
  9336.  
  9337. /*YS*/
  9338. #ifdef POVISO
  9339.     CASE (FUNC_ID_TOKEN)
  9340. #endif
  9341. #ifdef SplinePatch
  9342.     CASE(SPLINE_ID_TOKEN )
  9343. #endif
  9344. #ifdef RBezierPatch
  9345.     CASE(TRIMMED_BY_ID_TOKEN )
  9346. #endif
  9347. /*YS*/
  9348. #ifdef UnofficialBlocking
  9349.       parseUnofficialFeature(30);
  9350. #endif
  9351.     CASE4 (TNORMAL_ID_TOKEN, FINISH_ID_TOKEN, TEXTURE_ID_TOKEN, OBJECT_ID_TOKEN)
  9352.     CASE4 (COLOUR_MAP_ID_TOKEN, TRANSFORM_ID_TOKEN, CAMERA_ID_TOKEN, PIGMENT_ID_TOKEN)
  9353.     CASE4 (SLOPE_MAP_ID_TOKEN,NORMAL_MAP_ID_TOKEN,TEXTURE_MAP_ID_TOKEN,COLOUR_ID_TOKEN)
  9354.     CASE4 (PIGMENT_MAP_ID_TOKEN, MEDIA_ID_TOKEN,STRING_ID_TOKEN,INTERIOR_ID_TOKEN)
  9355.     CASE5 (DENSITY_MAP_ID_TOKEN, ARRAY_ID_TOKEN, DENSITY_ID_TOKEN,UV_ID_TOKEN,VECTOR_4D_ID_TOKEN)
  9356.     CASE4 (RAINBOW_ID_TOKEN, FOG_ID_TOKEN, SKYSPHERE_ID_TOKEN,MATERIAL_ID_TOKEN)
  9357.  
  9358.       if (Local_Flag && (Token.Table_Index != Table_Index))
  9359.       {
  9360.         Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
  9361.         Token.NumberPtr = &(Temp_Entry->Token_Number);
  9362.         Token.DataPtr   = &(Temp_Entry->Data);
  9363.         Previous        = IDENTIFIER_TOKEN;
  9364.       }
  9365.       else
  9366.       {
  9367.         Previous          = Token.Token_Id;
  9368.       }
  9369.       EXIT
  9370.     END_CASE
  9371.  
  9372.     CASE (EMPTY_ARRAY_TOKEN)
  9373.       Previous = Token.Token_Id;
  9374.       EXIT
  9375.     END_CASE
  9376.  
  9377.     CASE2 (VECTOR_FUNCT_TOKEN, FLOAT_FUNCT_TOKEN)
  9378.       switch(Token.Function_Id)
  9379.         {
  9380.          case VECTOR_ID_TOKEN:
  9381.          case FLOAT_ID_TOKEN:
  9382.            if (Local_Flag && (Token.Table_Index != Table_Index))
  9383.            {
  9384.               Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
  9385.               Token.NumberPtr = &(Temp_Entry->Token_Number);
  9386.               Token.DataPtr   = &(Temp_Entry->Data);
  9387.            }
  9388.            Previous           = Token.Function_Id;
  9389.            break;
  9390.  
  9391.          default:
  9392.            Parse_Error(IDENTIFIER_TOKEN);
  9393.            break;
  9394.         }
  9395.       EXIT
  9396.     END_CASE
  9397.  
  9398.     OTHERWISE
  9399.       Parse_Error(IDENTIFIER_TOKEN);
  9400.     END_CASE
  9401.   END_EXPECT
  9402.  
  9403.   LValue_Ok = FALSE;
  9404.  
  9405.   GET (EQUALS_TOKEN);
  9406.   
  9407.   if (!Parse_RValue (Previous,Token.NumberPtr,Token.DataPtr, FALSE,TRUE))
  9408.   {
  9409.     Parse_Error_Str("RValue to declare");
  9410.   }
  9411. }
  9412.  
  9413. int Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, int ParFlag, int SemiFlag)
  9414. {
  9415.   EXPRESS Local_Express;
  9416.   COLOUR *Local_Colour;
  9417.   PIGMENT *Local_Pigment;
  9418.   TNORMAL *Local_Tnormal;
  9419.   FINISH *Local_Finish;
  9420.   TEXTURE *Local_Texture, *Temp_Texture;
  9421.   TRANSFORM *Local_Trans;
  9422.   OBJECT *Local_Object;
  9423.   CAMERA *Local_Camera;
  9424.   IMEDIA *Local_Media;
  9425.   PIGMENT *Local_Density;
  9426.   INTERIOR *Local_Interior;
  9427.   MATERIAL *Local_Material;
  9428.   void *Temp_Data;
  9429.   POV_PARAM *New_Par;
  9430.   int Found=TRUE;
  9431.   int Temp_Count=30000;
  9432.   int Old_Ok=Ok_To_Declare;
  9433.   int Terms;
  9434. #ifdef RBezierPatch
  9435.   TRIM_SHAPE *Local_Trim;
  9436. #endif
  9437.   
  9438.   EXPECT
  9439.     CASE4 (TNORMAL_ID_TOKEN, FINISH_ID_TOKEN, TEXTURE_ID_TOKEN, OBJECT_ID_TOKEN)
  9440.     CASE4 (COLOUR_MAP_ID_TOKEN, TRANSFORM_ID_TOKEN, CAMERA_ID_TOKEN, PIGMENT_ID_TOKEN)
  9441.     CASE4 (SLOPE_MAP_ID_TOKEN,NORMAL_MAP_ID_TOKEN,TEXTURE_MAP_ID_TOKEN,ARRAY_ID_TOKEN)
  9442.     CASE4 (PIGMENT_MAP_ID_TOKEN, MEDIA_ID_TOKEN,INTERIOR_ID_TOKEN,DENSITY_ID_TOKEN)
  9443.     CASE4 (DENSITY_MAP_ID_TOKEN, RAINBOW_ID_TOKEN, FOG_ID_TOKEN, SKYSPHERE_ID_TOKEN)
  9444.     /* bugfix by Mark Wagner sept 2000*/
  9445.     CASE2 (MATERIAL_ID_TOKEN, SPLINE_ID_TOKEN)
  9446.       if (ParFlag)
  9447.       {
  9448.         New_Par            = (POV_PARAM *)POV_MALLOC(sizeof(POV_PARAM),"parameter");
  9449.         New_Par->NumberPtr = Token.NumberPtr;
  9450.         New_Par->DataPtr   = Token.DataPtr;
  9451.         *NumberPtr = PARAMETER_ID_TOKEN;
  9452.         *DataPtr   = (void *)New_Par;
  9453.       }
  9454.       else
  9455.       {
  9456.         Temp_Data  = (void *) Copy_Identifier((void *)*Token.DataPtr,*Token.NumberPtr);
  9457.         *NumberPtr = *Token.NumberPtr;
  9458.         Test_Redefine(Previous,NumberPtr,*DataPtr);
  9459.         *DataPtr   = Temp_Data;
  9460.       }
  9461.       EXIT
  9462.     END_CASE
  9463.  
  9464.     CASE (IDENTIFIER_TOKEN)
  9465.       if (ParFlag)
  9466.       {
  9467.          Error("Cannot pass uninitialized identifier as macro parameter.\nInitialize first.\n");
  9468.       }
  9469.       else
  9470.       {
  9471.          Error("Cannot assign uninitialized identifier.\n");
  9472.       }
  9473.       EXIT
  9474.     END_CASE
  9475.  
  9476.     CASE_COLOUR
  9477.       Local_Colour  = Create_Colour();
  9478.       Ok_To_Declare = FALSE;
  9479.       Parse_Colour (*Local_Colour);
  9480.       if (SemiFlag)
  9481.       {
  9482.          Parse_Semi_Colon();
  9483.       }
  9484.       Ok_To_Declare = TRUE;
  9485.       *NumberPtr    = COLOUR_ID_TOKEN;
  9486.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9487.       *DataPtr      = (void *) Local_Colour;
  9488.       EXIT
  9489.     END_CASE
  9490.  
  9491.     CASE_VECTOR
  9492.       Ok_To_Declare = FALSE;
  9493.       if (ParFlag && 
  9494.           ( ( (Token.Token_Id==FLOAT_FUNCT_TOKEN) && 
  9495.               (Token.Function_Id==FLOAT_ID_TOKEN) 
  9496.             ) ||
  9497.             ( (Token.Token_Id==VECTOR_FUNCT_TOKEN) && 
  9498.               (Token.Function_Id==VECTOR_ID_TOKEN) 
  9499.             ) ||
  9500.             (Token.Token_Id==VECTOR_4D_ID_TOKEN) 
  9501.               ||
  9502.             (Token.Token_Id==UV_ID_TOKEN) 
  9503.           ) 
  9504.          ) 
  9505.       {
  9506.          Temp_Count=token_count;
  9507.       }
  9508.       Terms = Parse_Unknown_Vector (Local_Express);
  9509.       if (SemiFlag)
  9510.       {
  9511.          Parse_Semi_Colon();
  9512.       }
  9513.       Temp_Count -= token_count;
  9514.       if ((Temp_Count==-1) || (Temp_Count==1000))
  9515.       {
  9516.          New_Par            = (POV_PARAM *)POV_MALLOC(sizeof(POV_PARAM),"parameter");
  9517.          New_Par->NumberPtr = Token.NumberPtr;
  9518.          New_Par->DataPtr   = Token.DataPtr;
  9519.          *NumberPtr = PARAMETER_ID_TOKEN;
  9520.          *DataPtr   = (void *)New_Par;
  9521.       }
  9522.       else
  9523.       {
  9524.          switch(Terms)
  9525.          {
  9526.            case 1:
  9527.             *NumberPtr = FLOAT_ID_TOKEN;
  9528.             Test_Redefine(Previous,NumberPtr,*DataPtr);
  9529.             *DataPtr   = (void *) Create_Float();
  9530.             *((DBL *)*DataPtr)  = Local_Express[X];
  9531.             break;
  9532.             
  9533.            case 2:
  9534.             *NumberPtr = UV_ID_TOKEN;
  9535.             Test_Redefine(Previous,NumberPtr,*DataPtr);
  9536.             *DataPtr   = (void *) Create_UV_Vect();
  9537.             Assign_UV_Vect(*DataPtr, Local_Express);
  9538.             break;
  9539.             
  9540.            case 3:
  9541.             *NumberPtr = VECTOR_ID_TOKEN;
  9542.             Test_Redefine(Previous,NumberPtr,*DataPtr);
  9543.             *DataPtr   = (void *) Create_Vector();
  9544.             Assign_Vector(*DataPtr ,Local_Express);
  9545.             break;
  9546.  
  9547.            case 4:
  9548.             *NumberPtr = VECTOR_4D_ID_TOKEN;
  9549.             Test_Redefine(Previous,NumberPtr,*DataPtr);
  9550.             *DataPtr   = (void *) Create_Vector_4D();
  9551.             Assign_Vector_4D(*DataPtr, Local_Express);
  9552.             break;
  9553.             
  9554.            case 5:
  9555.             *NumberPtr    = COLOUR_ID_TOKEN;
  9556.             Test_Redefine(Previous,NumberPtr,*DataPtr);
  9557.             *DataPtr   = (void *) Create_Colour();
  9558.             Assign_Colour_Express((COLC*)(*DataPtr), Local_Express); /* NK fix assign_colour bug */
  9559.             break;
  9560.          }
  9561.       } 
  9562.       Ok_To_Declare = TRUE;
  9563.       EXIT
  9564.     END_CASE
  9565.  
  9566.     CASE (PIGMENT_TOKEN)
  9567.       Local_Pigment = Copy_Pigment((Default_Texture->Pigment));
  9568.       Parse_Begin ();
  9569.       Parse_Pigment (&Local_Pigment);
  9570.       Parse_End ();
  9571.       *NumberPtr = PIGMENT_ID_TOKEN;
  9572.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9573.       *DataPtr   = (void *)Local_Pigment;
  9574.       EXIT
  9575.     END_CASE
  9576.  
  9577.     CASE (TNORMAL_TOKEN)
  9578.       Local_Tnormal = Copy_Tnormal((Default_Texture->Tnormal));
  9579.       Parse_Begin ();
  9580.       Parse_Tnormal (&Local_Tnormal);
  9581.       Parse_End ();
  9582.       *NumberPtr = TNORMAL_ID_TOKEN;
  9583.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9584.       *DataPtr   = (void *) Local_Tnormal;
  9585.       EXIT
  9586.     END_CASE
  9587.  
  9588.     CASE (FINISH_TOKEN)
  9589.       Local_Finish = Copy_Finish((Default_Texture->Finish));
  9590.       Parse_Finish (&Local_Finish);
  9591.       *NumberPtr = FINISH_ID_TOKEN;
  9592.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9593.       *DataPtr   = (void *) Local_Finish;
  9594.       EXIT
  9595.     END_CASE
  9596.  
  9597.     CASE (CAMERA_TOKEN)
  9598.       Local_Camera = Copy_Camera(Default_Camera);
  9599.       Parse_Camera (&Local_Camera);
  9600.       *NumberPtr = CAMERA_ID_TOKEN;
  9601.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9602.       *DataPtr   = (void *) Local_Camera;
  9603.       EXIT
  9604.     END_CASE
  9605.  
  9606. #ifdef RBezierPatch
  9607.     CASE (TRIMMED_BY_TOKEN)
  9608. #ifdef UnofficialBlocking
  9609.       parseUnofficialFeature(30);
  9610. #endif
  9611.       Local_Trim= Parse_Trim();
  9612.         *NumberPtr = TRIMMED_BY_ID_TOKEN;
  9613.       Test_Redefine(Previous, NumberPtr, *DataPtr);
  9614.         *DataPtr = (void *)(Local_Trim);
  9615.       EXIT
  9616.     END_CASE
  9617. #endif
  9618.  
  9619.     CASE (TEXTURE_TOKEN)
  9620.       Parse_Begin ();
  9621.       Local_Texture = Parse_Texture ();
  9622.       Parse_End ();
  9623.       Temp_Texture=NULL;
  9624.       Link_Textures(&Temp_Texture, Local_Texture);
  9625.       Ok_To_Declare = FALSE;
  9626.       EXPECT
  9627.         CASE (TEXTURE_TOKEN)
  9628.           Parse_Begin ();
  9629.           Local_Texture = Parse_Texture ();
  9630.           Parse_End ();
  9631.           Link_Textures(&Temp_Texture, Local_Texture);
  9632.         END_CASE
  9633.  
  9634.         OTHERWISE
  9635.           UNGET
  9636.           EXIT
  9637.         END_CASE
  9638.       END_EXPECT
  9639.  
  9640.       *NumberPtr    = TEXTURE_ID_TOKEN;
  9641.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9642.       *DataPtr      = (void *)Temp_Texture;
  9643.       Ok_To_Declare = TRUE;
  9644.       EXIT
  9645.     END_CASE
  9646.  
  9647.     CASE (COLOUR_MAP_TOKEN)
  9648.       Temp_Data=(void *) Parse_Colour_Map ();
  9649.       *NumberPtr = COLOUR_MAP_ID_TOKEN;
  9650.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9651.       *DataPtr   = Temp_Data;
  9652.       EXIT
  9653.     END_CASE
  9654.  
  9655.     CASE (PIGMENT_MAP_TOKEN)
  9656.       Temp_Data  = (void *) Parse_Blend_Map (PIGMENT_TYPE,NO_PATTERN);
  9657.       *NumberPtr = PIGMENT_MAP_ID_TOKEN;
  9658.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9659.       *DataPtr   = Temp_Data;
  9660.       EXIT
  9661.     END_CASE
  9662.  
  9663. #ifdef SplinePatch
  9664.     CASE (SPLINE_TOKEN)
  9665. #ifdef UnofficialBlocking
  9666.       parseUnofficialFeature(30);
  9667. #endif
  9668.       Parse_Begin();
  9669.       Temp_Data=(char *) Parse_Spline();
  9670.       Parse_End();
  9671.       *NumberPtr = SPLINE_ID_TOKEN;
  9672.       Test_Redefine( Previous, NumberPtr, *DataPtr );
  9673.       *DataPtr = (void *)Temp_Data;
  9674.       EXIT
  9675.     END_CASE
  9676. #endif
  9677.  
  9678.     CASE (DENSITY_MAP_TOKEN)
  9679.       Temp_Data  = (void *) Parse_Blend_Map (DENSITY_TYPE,NO_PATTERN);
  9680.       *NumberPtr = DENSITY_MAP_ID_TOKEN;
  9681.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9682.       *DataPtr   = Temp_Data;
  9683.       EXIT
  9684.     END_CASE
  9685.  
  9686.     CASE (SLOPE_MAP_TOKEN)
  9687.       Temp_Data  = (void *) Parse_Blend_Map (SLOPE_TYPE,NO_PATTERN);
  9688.       *NumberPtr = SLOPE_MAP_ID_TOKEN;
  9689.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9690.       *DataPtr   = Temp_Data;
  9691.       EXIT
  9692.     END_CASE
  9693.  
  9694.     CASE (TEXTURE_MAP_TOKEN)
  9695.       Temp_Data  = (void *) Parse_Blend_Map (TEXTURE_TYPE,NO_PATTERN);
  9696.       *NumberPtr = TEXTURE_MAP_ID_TOKEN;
  9697.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9698.       *DataPtr   = Temp_Data;
  9699.       EXIT
  9700.     END_CASE
  9701.  
  9702.     CASE (NORMAL_MAP_TOKEN)
  9703.       Temp_Data  = (void *) Parse_Blend_Map (NORMAL_TYPE,NO_PATTERN);
  9704.       *NumberPtr = NORMAL_MAP_ID_TOKEN;
  9705.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9706.       *DataPtr   = Temp_Data;
  9707.       EXIT
  9708.     END_CASE
  9709.  
  9710.     CASE (RAINBOW_TOKEN)
  9711.       Temp_Data  = (void *) Parse_Rainbow();
  9712.       *NumberPtr = RAINBOW_ID_TOKEN;
  9713.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9714.       *DataPtr   = Temp_Data;
  9715.       EXIT
  9716.     END_CASE
  9717.  
  9718.     CASE (FOG_TOKEN)
  9719.       Temp_Data  = (void *) Parse_Fog();
  9720.       *NumberPtr = FOG_ID_TOKEN;
  9721.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9722.       *DataPtr   = Temp_Data;
  9723.       EXIT
  9724.     END_CASE
  9725.  
  9726.     CASE (MEDIA_TOKEN)
  9727.       Local_Media = NULL;
  9728.       Parse_Media(&Local_Media);
  9729.       Temp_Data  = (void *)Local_Media;
  9730.       *NumberPtr = MEDIA_ID_TOKEN;
  9731.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9732.       *DataPtr   = Temp_Data;
  9733.       EXIT
  9734.     END_CASE
  9735.  
  9736.     CASE (DENSITY_TOKEN)
  9737.       Local_Density = NULL;
  9738.       Parse_Begin ();
  9739.       Parse_Media_Density_Pattern (&Local_Density);
  9740.       Parse_End ();
  9741.       *NumberPtr = DENSITY_ID_TOKEN;
  9742.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9743.       *DataPtr   = (void *)Local_Density;
  9744.       EXIT
  9745.     END_CASE
  9746.  
  9747.     CASE (INTERIOR_TOKEN)
  9748.       Local_Interior = NULL;
  9749.       Parse_Interior(&Local_Interior);
  9750.       Temp_Data  = (void *)Local_Interior;
  9751.       *NumberPtr = INTERIOR_ID_TOKEN;
  9752.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9753.       *DataPtr   = Temp_Data;
  9754.       EXIT
  9755.     END_CASE
  9756.  
  9757.     CASE (MATERIAL_TOKEN)
  9758.       Local_Material = Create_Material();
  9759.       Parse_Material(Local_Material);
  9760.       Temp_Data  = (void *)Local_Material;
  9761.       *NumberPtr = MATERIAL_ID_TOKEN;
  9762.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9763.       *DataPtr   = Temp_Data;
  9764.       EXIT
  9765.     END_CASE
  9766.  
  9767.     CASE (SKYSPHERE_TOKEN)
  9768.       Temp_Data  = (void *) Parse_Skysphere();
  9769.       *NumberPtr = SKYSPHERE_ID_TOKEN;
  9770.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9771.       *DataPtr   = Temp_Data;
  9772.       EXIT
  9773.     END_CASE
  9774.  
  9775.     CASE (TRANSFORM_TOKEN)
  9776. #ifndef TransformPatch /* Chris Huff april 2000 */
  9777.      Local_Trans = Parse_Transform ();
  9778. #else
  9779.       Local_Trans = Parse_Transform_Block ();
  9780. #endif
  9781.       *NumberPtr  = TRANSFORM_ID_TOKEN;
  9782.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9783.       *DataPtr    = (void *) Local_Trans;
  9784.       EXIT
  9785.     END_CASE
  9786.  
  9787. /** poviso: May 97, Mar 99 for v3.1 R.S. **/
  9788. #ifdef POVISO
  9789.     CASE (FUNCTION_TOKEN)
  9790.       Temp_Data = (char *)Parse_Function ();
  9791.       *NumberPtr = FUNC_ID_TOKEN;
  9792.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9793.       *DataPtr   = Temp_Data;
  9794.       EXIT
  9795.     END_CASE
  9796. #endif
  9797. /** --- **/
  9798.  
  9799. #ifdef TimeDatePatch
  9800.     CASE(GET_DATE_TOKEN) /*YS get date and time string*/
  9801. #endif
  9802.     CASE4 (STRING_LITERAL_TOKEN,CHR_TOKEN,SUBSTR_TOKEN,STR_TOKEN)
  9803.     CASE4 (CONCAT_TOKEN,STRUPR_TOKEN,STRLWR_TOKEN,STRING_ID_TOKEN)
  9804.       UNGET
  9805.       Temp_Data  = Parse_String();
  9806.       *NumberPtr = STRING_ID_TOKEN;
  9807.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9808.       *DataPtr   = Temp_Data;
  9809.       EXIT
  9810.     END_CASE
  9811.  
  9812.     CASE (ARRAY_TOKEN)
  9813.       Temp_Data  = (void *) Parse_Array_Declare();
  9814.       *NumberPtr = ARRAY_ID_TOKEN;
  9815.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9816.       *DataPtr   = Temp_Data;
  9817.       EXIT
  9818.     END_CASE
  9819.  
  9820.     OTHERWISE
  9821.       UNGET
  9822.       Local_Object = Parse_Object ();
  9823.       Found=(Local_Object!=NULL);
  9824.       *NumberPtr   = OBJECT_ID_TOKEN;
  9825.       Test_Redefine(Previous,NumberPtr,*DataPtr);
  9826.       *DataPtr     = (void *) Local_Object;
  9827.       EXIT
  9828.     END_CASE
  9829.  
  9830.   END_EXPECT
  9831.   
  9832.   Ok_To_Declare=Old_Ok;
  9833.   return(Found);
  9834. }
  9835.  
  9836. void Destroy_Ident_Data (void *Data, int Type)
  9837. {
  9838.   int i;
  9839.   POV_ARRAY *a;
  9840.   DATA_FILE *Temp_File;
  9841.   
  9842.   if (Data==NULL)
  9843.   {
  9844.      return;
  9845.   }
  9846.  
  9847.   switch (Type)
  9848.   {
  9849.      case COLOUR_ID_TOKEN:
  9850.        Destroy_Colour((COLOUR *)Data);
  9851.        break;
  9852.      case VECTOR_ID_TOKEN:
  9853.        Destroy_Vector((VECTOR *)Data);
  9854.        break;
  9855.      case UV_ID_TOKEN:
  9856.        Destroy_UV_Vect((UV_VECT *)Data);
  9857.        break;
  9858.      case VECTOR_4D_ID_TOKEN:
  9859.        Destroy_Vector((VECTOR_4D *)Data);
  9860.        break;
  9861.      case FLOAT_ID_TOKEN:
  9862.        Destroy_Float((DBL *)Data);
  9863.        break;
  9864.      case PIGMENT_ID_TOKEN:
  9865.      case DENSITY_ID_TOKEN:
  9866.        Destroy_Pigment((PIGMENT *)Data);
  9867.        break;
  9868.      case TNORMAL_ID_TOKEN:
  9869.        Destroy_Tnormal((TNORMAL *)Data);
  9870.        break;
  9871.      case FINISH_ID_TOKEN:
  9872.        Destroy_Finish((FINISH *)Data);
  9873.        break;
  9874.      case MEDIA_ID_TOKEN:
  9875.        Destroy_Media((IMEDIA *)Data);
  9876.        break;
  9877.      case INTERIOR_ID_TOKEN:
  9878.        Destroy_Interior((INTERIOR *)Data);
  9879.        break;
  9880.      case MATERIAL_ID_TOKEN:
  9881.        Destroy_Material((MATERIAL *)Data);
  9882.        break;
  9883.      case TEXTURE_ID_TOKEN:
  9884.        Destroy_Textures((TEXTURE *)Data);
  9885.        break;
  9886.      case OBJECT_ID_TOKEN:
  9887.        Destroy_Object((OBJECT *)Data);
  9888.        break;
  9889.      case COLOUR_MAP_ID_TOKEN:
  9890.      case PIGMENT_MAP_ID_TOKEN:
  9891.      case SLOPE_MAP_ID_TOKEN:
  9892.      case TEXTURE_MAP_ID_TOKEN:
  9893.      case NORMAL_MAP_ID_TOKEN:
  9894.      case DENSITY_MAP_ID_TOKEN:
  9895.        Destroy_Blend_Map((BLEND_MAP *)Data);
  9896.        break;
  9897.      case TRANSFORM_ID_TOKEN:
  9898.        Destroy_Transform((TRANSFORM *)Data);
  9899.        break;
  9900.      case CAMERA_ID_TOKEN:
  9901.        Destroy_Camera((CAMERA *)Data);
  9902.        break;
  9903.      case RAINBOW_ID_TOKEN:
  9904.        Destroy_Rainbow((RAINBOW *)Data);
  9905.        break;
  9906.      case FOG_ID_TOKEN:
  9907.        Destroy_Fog((FOG *)Data);
  9908.        break;
  9909.      case SKYSPHERE_ID_TOKEN:
  9910.        Destroy_Skysphere((SKYSPHERE *)Data);
  9911.        break;
  9912.      case MACRO_ID_TOKEN:
  9913.        Destroy_Macro((POV_MACRO *)Data);
  9914.        break;
  9915.      case STRING_ID_TOKEN:
  9916.        POV_FREE((char *)Data);
  9917.        break;
  9918.      case ARRAY_ID_TOKEN:
  9919.        a=(POV_ARRAY *)Data;
  9920.        for (i=0; i<a->Total; i++)
  9921.        {
  9922.          Destroy_Ident_Data (a->DataPtrs[i],a->Type);
  9923.        }
  9924.        POV_FREE(a->DataPtrs);
  9925.        POV_FREE(a);
  9926.        break;
  9927.      case PARAMETER_ID_TOKEN:
  9928.        POV_FREE(Data);
  9929.        break;
  9930.      case FILE_ID_TOKEN:
  9931.        Temp_File=(DATA_FILE *)Data;
  9932. #ifdef FastMacroPatch
  9933.        if (Temp_File->Close!=NULL)
  9934.        {
  9935.          Data_File_Close(Temp_File);
  9936.        }
  9937. #else
  9938.        if (Temp_File->File!=NULL)
  9939.        {
  9940.          fflush(Temp_File->File);
  9941.          fclose(Temp_File->File);
  9942.        }
  9943. #endif
  9944.        if (Temp_File->Filename!=NULL)
  9945.        {
  9946.          POV_FREE(Temp_File->Filename);
  9947.        }
  9948.        POV_FREE(Data);
  9949.        break;
  9950.      case SPLINE_ID_TOKEN:
  9951.        Destroy_Spline((SPLINE2 *)Data);
  9952.        break;
  9953.        
  9954.    }
  9955. }
  9956.  
  9957.  
  9958.  
  9959.  
  9960.  
  9961. /*****************************************************************************
  9962. *
  9963. * FUNCTION
  9964. *
  9965. * INPUT
  9966. *   
  9967. * OUTPUT
  9968. *   
  9969. * RETURNS
  9970. *   
  9971. * AUTHOR
  9972. *   
  9973. * DESCRIPTION
  9974. *
  9975. * CHANGES
  9976. *
  9977. ******************************************************************************/
  9978.  
  9979. static void Link (OBJECT *New_Object, OBJECT  **Field, OBJECT  **Old_Object_List)
  9980. {
  9981.   *Field = *Old_Object_List;
  9982.   *Old_Object_List = New_Object;
  9983.   }
  9984.  
  9985.  
  9986. /*****************************************************************************
  9987. *
  9988. * FUNCTION
  9989. *
  9990. * INPUT
  9991. *
  9992. * OUTPUT
  9993. *   
  9994. * RETURNS
  9995. *   
  9996. * AUTHOR
  9997. *   
  9998. * DESCRIPTION
  9999. *
  10000. * CHANGES
  10001. *
  10002. ******************************************************************************/
  10003.  
  10004. void Link_Textures (TEXTURE **Old_Textures, TEXTURE *New_Textures)
  10005. {
  10006.   TEXTURE *Layer;
  10007.    
  10008.   if (New_Textures == NULL)
  10009.     return;
  10010.  
  10011.   if ((*Old_Textures) != NULL)
  10012.   {
  10013.      if ((*Old_Textures)->Type != PLAIN_PATTERN) 
  10014.      {
  10015.         Error("Cannot layer over a patterned texture.\n");
  10016.      }
  10017.   }
  10018.  
  10019.   for (Layer = New_Textures;
  10020.        Layer->Next != NULL;
  10021.        Layer = (TEXTURE *)Layer->Next)
  10022.   {
  10023.     /* NK layers - 1999 June 10 - for backwards compatiblity with layered textures */
  10024. #ifdef UnofficialBlocking
  10025.     if(opts.unofficialVersion<0)
  10026. #else
  10027.     if(opts.Language_Version<=310)
  10028. #endif
  10029.       Convert_Filter_To_Transmit(Layer->Pigment);
  10030.     /* NK ---- */
  10031.   }
  10032.  
  10033.   /* NK layers - 1999 Nov 16 - for backwards compatiblity with layered textures */
  10034.   if ((opts.Language_Version<=310) && (*Old_Textures!=NULL))
  10035.     Convert_Filter_To_Transmit(Layer->Pigment);
  10036.   /* NK ---- */
  10037.  
  10038.    Layer->Next = (TPATTERN *)*Old_Textures;
  10039.    *Old_Textures = New_Textures;
  10040.  
  10041.    if ((New_Textures->Type != PLAIN_PATTERN) && (New_Textures->Next != NULL))
  10042.    {
  10043.       Error("Cannot layer a patterned texture over another.\n");
  10044.    }
  10045.   }
  10046.  
  10047.  
  10048.  
  10049. /*****************************************************************************
  10050. *
  10051. * FUNCTION
  10052. *
  10053. * INPUT
  10054. *
  10055. * OUTPUT
  10056. *
  10057. * RETURNS
  10058. *
  10059. * AUTHOR
  10060. *
  10061. * DESCRIPTION
  10062. *
  10063. * CHANGES
  10064. *
  10065. ******************************************************************************/
  10066.  
  10067. char *Get_Token_String (TOKEN Token_Id)
  10068. {
  10069.   register int i;
  10070.  
  10071.   for (i = 0 ; i < LAST_TOKEN ; i++)
  10072.      if (Reserved_Words[i].Token_Number == Token_Id)
  10073.         return (Reserved_Words[i].Token_Name);
  10074.   return ("");
  10075.   }
  10076.  
  10077.  
  10078.  
  10079. /*****************************************************************************
  10080. *
  10081. * FUNCTION
  10082. *
  10083. * INPUT
  10084. *
  10085. * OUTPUT
  10086. *
  10087. * RETURNS
  10088. *
  10089. * AUTHOR
  10090. *
  10091. * DESCRIPTION
  10092. *
  10093. * CHANGES
  10094. *
  10095. ******************************************************************************/
  10096.  
  10097. void Test_Redefine(TOKEN Previous, TOKEN *NumberPtr, void *Data)
  10098. {
  10099.   /*char *oldt, *newt;*/
  10100.  
  10101.   if ((Previous == IDENTIFIER_TOKEN) || (Previous == EMPTY_ARRAY_TOKEN))
  10102.   {
  10103.     return;
  10104.   }
  10105. /* NK 1998 - allow user to redefine all identifiers! */
  10106. #define ALLOW_REDEFINE
  10107. #ifdef ALLOW_REDEFINE
  10108.   if (getUnofficialVersion() > 0)
  10109.   {
  10110.      Destroy_Ident_Data(Data,Previous);
  10111.   }
  10112.   else
  10113.   {
  10114. #endif
  10115.   if (Previous == *NumberPtr)
  10116.   {
  10117.      Destroy_Ident_Data(Data,*NumberPtr);
  10118.   }
  10119.   else
  10120.   {
  10121.      char *oldt, *newt;
  10122.  
  10123.      oldt = Get_Token_String (Previous);
  10124.      newt = Get_Token_String (*NumberPtr);
  10125.      *NumberPtr = Previous;
  10126.      
  10127.      Error ("Attempted to redefine %s as %s.", oldt, newt);
  10128.   }
  10129. #ifdef ALLOW_REDEFINE
  10130.   }
  10131. #endif
  10132. }
  10133.  
  10134.  
  10135.  
  10136. /*****************************************************************************
  10137. *
  10138. * FUNCTION
  10139. *
  10140. * INPUT
  10141. *
  10142. * OUTPUT
  10143. *
  10144. * RETURNS
  10145. *
  10146. * AUTHOR
  10147. *
  10148. * DESCRIPTION
  10149. *
  10150. * CHANGES
  10151. *
  10152. ******************************************************************************/
  10153.  
  10154. void Parse_Error (TOKEN Token_Id)
  10155. {
  10156.   char *expected;
  10157.  
  10158.   expected = Get_Token_String (Token_Id);
  10159.   Parse_Error_Str(expected);
  10160.   }
  10161.  
  10162.  
  10163.  
  10164. /*****************************************************************************
  10165. *
  10166. * FUNCTION
  10167. *
  10168. * INPUT
  10169. *
  10170. * OUTPUT
  10171. *
  10172. * RETURNS
  10173. *
  10174. * AUTHOR
  10175. *
  10176. * DESCRIPTION
  10177. *
  10178. * CHANGES
  10179. *
  10180. ******************************************************************************/
  10181.  
  10182. void Parse_Error_Str (char *str)
  10183. {
  10184.    Where_Error ();
  10185.    Error_Line("%s expected but", str);
  10186.    Found_Instead ();
  10187. }
  10188.  
  10189.  
  10190.  
  10191. /*****************************************************************************
  10192. *
  10193. * FUNCTION
  10194. *
  10195. * INPUT
  10196. *
  10197. * OUTPUT
  10198. *
  10199. * RETURNS
  10200. *
  10201. * AUTHOR
  10202. *
  10203. * DESCRIPTION
  10204. *
  10205. * CHANGES
  10206. *
  10207. ******************************************************************************/
  10208.  
  10209. static void Found_Instead ()
  10210. {
  10211.   char *found;
  10212.   
  10213.   Stage=STAGE_FOUND_INSTEAD;
  10214.  
  10215.   switch(Token.Token_Id)
  10216.   {
  10217.     case IDENTIFIER_TOKEN:
  10218.       Error (" undeclared identifier '%s' found instead.\n", Token.Token_String);
  10219.       break;
  10220.       
  10221.     case VECTOR_FUNCT_TOKEN:
  10222.       found = Get_Token_String (Token.Function_Id);
  10223.       Error (" vector function '%s' found instead.\n", found);
  10224.       break;
  10225.       
  10226.     case FLOAT_FUNCT_TOKEN:
  10227.       found = Get_Token_String (Token.Function_Id);
  10228.       Error (" float function '%s' found instead.\n", found);
  10229.       break;
  10230.  
  10231.     case COLOUR_KEY_TOKEN:
  10232.       found = Get_Token_String (Token.Function_Id);
  10233.       Error (" color keyword '%s' found instead.\n", found);
  10234.       break;
  10235.  
  10236.     default:
  10237.       found = Get_Token_String (Token.Token_Id);
  10238.       Error (" %s found instead.\n", found);
  10239.   }
  10240. }
  10241.   
  10242.  
  10243.  
  10244. /*****************************************************************************
  10245. *
  10246. * FUNCTION
  10247. *
  10248. * INPUT
  10249. *
  10250. * OUTPUT
  10251. *
  10252. * RETURNS
  10253. *
  10254. * AUTHOR
  10255. *
  10256. * DESCRIPTION
  10257. *
  10258. * CHANGES
  10259. *
  10260. ******************************************************************************/
  10261.  
  10262. void Warn_State (TOKEN Token_Id,TOKEN  Type)
  10263. {
  10264.   char *found;
  10265.   char *should;
  10266.  
  10267.   found = Get_Token_String (Token_Id);
  10268.   should = Get_Token_String (Type);
  10269.   Warning (150, "%s:%d: warning: Found %s that should be in %s statement.\n",
  10270.            Token.Filename, Token.Token_Line_No+1, found, should);
  10271.   }
  10272.  
  10273.  
  10274.  
  10275. /*****************************************************************************
  10276. *
  10277. * FUNCTION
  10278. *
  10279. * INPUT
  10280. *
  10281. * OUTPUT
  10282. *
  10283. * RETURNS
  10284. *
  10285. * AUTHOR
  10286. *
  10287. * DESCRIPTION
  10288. *
  10289. * CHANGES
  10290. *
  10291. ******************************************************************************/
  10292.  
  10293. void Warn (int Level, char *str)
  10294. {
  10295.   if (opts.Language_Version < Level)
  10296.     return;
  10297.  
  10298.   Warning(Level, "%s:%d: warning: %s\n", Token.Filename, Token.Token_Line_No+1, str);
  10299.   }
  10300.  
  10301.  
  10302.  
  10303. /*****************************************************************************
  10304. *
  10305. * FUNCTION
  10306. *
  10307. * INPUT
  10308. *
  10309. * OUTPUT
  10310. *
  10311. * RETURNS
  10312. *
  10313. * AUTHOR
  10314. *
  10315. * DESCRIPTION
  10316. *
  10317. * CHANGES
  10318. *
  10319. ******************************************************************************/
  10320.  
  10321. void MAError (char *str,size_t size)
  10322. {
  10323.   Error ("Out of memory.  Cannot allocate %ld bytes for %s.\n",size,str);
  10324.   }
  10325.  
  10326.  
  10327.  
  10328. /*****************************************************************************
  10329. *
  10330. * FUNCTION
  10331. *
  10332. * INPUT
  10333. *
  10334. * OUTPUT
  10335. *
  10336. * RETURNS
  10337. *
  10338. * AUTHOR
  10339. *
  10340. * DESCRIPTION
  10341. *
  10342. * CHANGES
  10343. *
  10344. ******************************************************************************/
  10345.  
  10346. static void Post_Process (OBJECT *Object,OBJECT  *Parent)
  10347. {
  10348.   DBL Volume;
  10349.   OBJECT *Sib;
  10350.   FINISH *Finish;
  10351.  
  10352.   if (Object == NULL)
  10353.   {
  10354.     return;
  10355.   }
  10356.  
  10357.   if (Object->Type & LT_SRC_UNION_OBJECT) 
  10358.   {
  10359.     for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  10360.     {
  10361.       Post_Process(Sib, Object);
  10362.     }
  10363.     return;
  10364.   }
  10365.  
  10366.   Post_Light_Groups(Object);
  10367.  
  10368.   /* Promote texture etc. from parent to children. */
  10369.  
  10370.   if (Parent != NULL)
  10371.   {
  10372.     if (Object->Texture == NULL)
  10373.     {
  10374.       Object->Texture = Copy_Texture_Pointer(Parent->Texture);
  10375.       /* NK 1998 copy uv_mapping flag if and only if we copy the texture */
  10376.       if (Test_Flag(Parent, UV_FLAG))
  10377.         Set_Flag(Object, UV_FLAG);
  10378.       /* NK ---- */
  10379.     }
  10380.     
  10381.     #ifdef InteriorTexturePatch    /* fix from Nicolas Calimet july 2000 */
  10382.         if (Object->Interior_Texture == NULL)
  10383.         {
  10384.           Object->Interior_Texture = Copy_Texture_Pointer(Parent->Interior_Texture);
  10385.           if (Test_Flag(Parent, UV_FLAG))
  10386.             Set_Flag(Object, UV_FLAG);
  10387.         }
  10388.     #endif
  10389.     if (Object->Interior == NULL)
  10390.     {
  10391.       Object->Interior = Copy_Interior_Pointer(Parent->Interior);
  10392.     }
  10393.  
  10394.     if (Test_Flag(Parent, NO_SHADOW_FLAG))
  10395.     {
  10396.       Set_Flag(Object, NO_SHADOW_FLAG);
  10397.     }
  10398.  
  10399.     /* NK phmap */
  10400.     /* promote photon mapping flags to child */
  10401.     if (Parent->Ph_Flags & PH_FLAG_TARGET)
  10402.     {
  10403.       Object->Ph_Flags |= PH_FLAG_TARGET;
  10404.       Object->Ph_Density = Parent->Ph_Density;
  10405.       CheckPassThru(Object, PH_FLAG_TARGET);
  10406.     }
  10407.  
  10408.     if(Parent->Ph_Flags & PH_FLAG_PASSTHRU)
  10409.     {
  10410.       Object->Ph_Flags |= PH_FLAG_PASSTHRU;
  10411.       CheckPassThru(Object, PH_FLAG_PASSTHRU);
  10412.     }
  10413.  
  10414.     if (Parent->Ph_Flags & PH_FLAG_RFL_ON)
  10415.     {
  10416.       SET_PH_FLAG(Object, PH_FLAG_RFL_ON, PH_FLAG_RFL_OFF);
  10417.     }
  10418.     else if (Parent->Ph_Flags & PH_FLAG_RFL_OFF)
  10419.     {
  10420.       SET_PH_FLAG(Object, PH_FLAG_RFL_OFF, PH_FLAG_RFL_ON);
  10421.     }
  10422.  
  10423.     if (Parent->Ph_Flags & PH_FLAG_RFR_ON)
  10424.     {
  10425.       SET_PH_FLAG(Object, PH_FLAG_RFR_ON, PH_FLAG_RFR_OFF);
  10426.       CheckPassThru(Object, PH_FLAG_RFR_ON);
  10427.     }
  10428.     else if (Parent->Ph_Flags & PH_FLAG_RFR_OFF)
  10429.     {
  10430.       SET_PH_FLAG(Object, PH_FLAG_RFR_OFF, PH_FLAG_RFR_ON);
  10431.     }
  10432.  
  10433.     if(Parent->Ph_Flags & PH_FLAG_IGNORE_PHOTONS)
  10434.     {
  10435.       Object->Ph_Flags |= PH_FLAG_IGNORE_PHOTONS;
  10436.     }
  10437.     /* NK ---- */
  10438. #ifdef MotionBlurPatch
  10439.     if(Parent->TimeStamp)
  10440.     {
  10441.       Object->TimeStamp = Parent->TimeStamp;
  10442.     }
  10443. #endif
  10444.   }
  10445.  
  10446.   if (Object->Interior != NULL)
  10447.   {
  10448.      Post_Media(Object->Interior->IMedia);
  10449.   }
  10450.  
  10451.   if ((Object->Texture == NULL) &&
  10452.       !(Object->Type & TEXTURED_OBJECT) &&
  10453.       !(Object->Type & LIGHT_SOURCE_OBJECT))
  10454.   {
  10455. #ifdef MultiTextureCsgPatch
  10456.     if (Parent)
  10457.     {
  10458.       if(Parent->Methods != &CSG_Intersection_Methods ||
  10459.          !Test_Flag(Parent, MULTITEXTURE_FLAG))
  10460.       {
  10461.         Object->Texture = Copy_Textures(Default_Texture);
  10462.       }
  10463.     }
  10464.     else
  10465. #endif
  10466.  
  10467.     Object->Texture = Copy_Textures(Default_Texture);
  10468.   }
  10469.  
  10470.   Post_Textures(Object->Texture);  /*moved cey 6/97*/
  10471.  
  10472.   if (Object->Type & LIGHT_SOURCE_OBJECT)
  10473.   {
  10474.     ((LIGHT_SOURCE *)Object)->Next_Light_Source = Frame.Light_Sources;
  10475.  
  10476.     if (((LIGHT_SOURCE *)Object)->Projected_Through_Object != NULL) {
  10477.         if (((LIGHT_SOURCE *)Object)->Projected_Through_Object->Interior != NULL){
  10478.             Destroy_Interior(((LIGHT_SOURCE *)Object)->Projected_Through_Object->Interior);
  10479.             ((LIGHT_SOURCE *)Object)->Projected_Through_Object->Interior=NULL;
  10480.             Warn(400,"Projected through objects can not have interior, interior removed.\n");
  10481.         }
  10482.         if (((LIGHT_SOURCE *)Object)->Projected_Through_Object->Texture != NULL) {
  10483.             Destroy_Textures(((LIGHT_SOURCE *)Object)->Projected_Through_Object->Texture);
  10484.             ((LIGHT_SOURCE *)Object)->Projected_Through_Object->Texture = NULL;
  10485.             Warn(400,"Projected through objects can not have texture, texture removed.\n");
  10486.         }
  10487.     }
  10488.  
  10489.     Frame.Light_Sources = (LIGHT_SOURCE *)Object;
  10490.  
  10491.     Frame.Number_Of_Light_Sources++;
  10492.   }
  10493.   else
  10494.   {
  10495.     /* If there is no interior create one. */
  10496.  
  10497.     if (Object->Interior == NULL)
  10498.     {
  10499.       Object->Interior = Create_Interior();
  10500.     }
  10501.  
  10502.     /* Promote hollow flag to interior. */
  10503.  
  10504.     Object->Interior->hollow = (Test_Flag(Object, HOLLOW_FLAG) != FALSE);
  10505.  
  10506.     /* Promote finish's IOR to interior IOR. */
  10507.  
  10508.     if (Object->Texture != NULL)
  10509.     {
  10510.       if (Object->Texture->Type == PLAIN_PATTERN)
  10511.       {
  10512.         if ((Finish = Object->Texture->Finish) != NULL)
  10513.         {
  10514.           if (Finish->Temp_IOR >= 0.0)
  10515.           {
  10516.             Object->Interior->IOR = Finish->Temp_IOR;
  10517.             Object->Interior->Dispersion = Finish->Temp_Dispersion;
  10518.           }
  10519.           if (Finish->Temp_Caustics >= 0.0)
  10520.           {
  10521.             Object->Interior->Caustics = Finish->Temp_Caustics;
  10522.           }
  10523.  
  10524.           Object->Interior->Old_Refract = Finish->Temp_Refract;
  10525.         }
  10526.       }
  10527.     }
  10528.  
  10529.     /* If there is no IOR specified use the atmopshere ior. */
  10530.  
  10531.     if (Object->Interior->IOR == 0.0)
  10532.     {
  10533.       Object->Interior->IOR = Frame.Atmosphere_IOR;
  10534.         Object->Interior->Dispersion = Frame.Atmosphere_Dispersion;
  10535.     }
  10536.   }
  10537.  
  10538.   if (Object->Type & COMPOUND_OBJECT)
  10539.   {
  10540.     for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  10541.     {
  10542.       Post_Process(Sib, Object);
  10543.     }
  10544.   }
  10545. #define PUT_DOUBLE_ILL_ON_PLAIN_PATTERNS 0
  10546. #if(PUT_DOUBLE_ILL_ON_PLAIN_PATTERNS)
  10547.   else
  10548.   {
  10549.     if (Object->Texture != NULL)
  10550.     {
  10551.       if (Object->Texture->Type == PLAIN_PATTERN)
  10552.       {
  10553.         if (Object->Texture->Tnormal != NULL)
  10554.         {
  10555.           /* NK 1998 double_illuminate */
  10556.           /*Object->Type |= DOUBLE_ILLUMINATE;*/
  10557.           Set_Flag(Object, DOUBLE_ILLUMINATE_FLAG);
  10558.           /* NK ---- */
  10559.         }
  10560.       }
  10561.     }
  10562.   }
  10563. #endif
  10564.  
  10565.   /* Test wether the object is finite or infinite. [DB 9/94] */
  10566.  
  10567.   BOUNDS_VOLUME(Volume, Object->BBox);
  10568.  
  10569.   if (Volume > INFINITE_VOLUME)
  10570.   {
  10571.     Set_Flag(Object, INFINITE_FLAG);
  10572.   }
  10573.  
  10574.   /* Test wether the object is opaque or not. [DB 8/94] */
  10575.  
  10576.   if ((Object->Methods != &Blob_Methods) &&
  10577.       (Object->Methods != &Mesh_Methods) &&
  10578.       (Test_Opacity(Object->Texture)) 
  10579. #ifdef InteriorTexturePatch
  10580.       &&
  10581.       (
  10582.         (!Object->Interior_Texture) ||
  10583.         Test_Opacity(Object->Interior_Texture)
  10584.       )
  10585. #endif
  10586.       )
  10587.   {
  10588.     Set_Flag(Object, OPAQUE_FLAG);
  10589.   }
  10590.   else
  10591.   {
  10592.     /* Objects with multiple textures have to be handled separately. */
  10593.  
  10594.     if (Object->Methods == &Blob_Methods)
  10595.     {
  10596.       Test_Blob_Opacity((BLOB *)Object);
  10597.     }
  10598.  
  10599.     if (Object->Methods == &Mesh_Methods)
  10600.     {
  10601.       Test_Mesh_Opacity((MESH *)Object);
  10602.     }
  10603.   }
  10604. }
  10605.  
  10606. /*****************************************************************************
  10607. *
  10608. * FUNCTION
  10609. *
  10610. *   Link_To_Frame
  10611. *
  10612. * INPUT
  10613. *
  10614. *   Object - Pointer to object
  10615. *   
  10616. * OUTPUT
  10617. *
  10618. *   Object
  10619. *   
  10620. * RETURNS
  10621. *   
  10622. * AUTHOR
  10623. *
  10624. *   POV-Ray Team
  10625. *   
  10626. * DESCRIPTION
  10627. *
  10628. *   -
  10629. *
  10630. * CHANGES
  10631. *
  10632. *   Sep 1994 : Added optional splitting of bounded unions if children are
  10633. *              finite. Added removing of unnecessary bounding. [DB]
  10634. *
  10635. ******************************************************************************/
  10636.  
  10637. static void Link_To_Frame(OBJECT *Object)
  10638. {
  10639.   int finite;
  10640.   DBL Volume;
  10641.   OBJECT *This_Sib, *Next_Sib;
  10642.  
  10643.   if (Object == NULL)           /* patches a memory addressing error jdm mar/95 */
  10644.     return;
  10645.  
  10646.   /* Remove bounding object if object is cheap to intersect. [DB 8/94]  */
  10647.  
  10648.   if ((opts.Options & REMOVE_BOUNDS) && (Object->Bound != NULL))
  10649.   {
  10650.     if ((Object->Methods != &CSG_Union_Methods)        &&
  10651.         (Object->Methods != &CSG_Intersection_Methods) &&
  10652.         (Object->Methods != &CSG_Merge_Methods)        &&
  10653.         (Object->Methods != &Poly_Methods)             &&
  10654.         (Object->Methods != &TTF_Methods))
  10655.     {
  10656.       /* Destroy only, if bounding object is not used as clipping object. */
  10657.  
  10658.       if (Object->Bound != Object->Clip)
  10659.       {
  10660.         Destroy_Object(Object->Bound);
  10661.       }
  10662.  
  10663.       Object->Bound = NULL;
  10664.  
  10665.       Warn(0, "Unnecessary bounding object removed.");
  10666.     }
  10667.   }
  10668.  
  10669.   /*
  10670.    * Link the object to the frame if it's not a CSG union object,
  10671.    * if it's clipped or if bounding slabs aren't used.
  10672.    */
  10673.  
  10674.   if ((Object->Methods != &CSG_Union_Methods) ||
  10675.       (Object->Clip != NULL) ||
  10676.       (!opts.Use_Slabs))
  10677.   {
  10678.     Link(Object, &(Object->Sibling), &(Frame.Objects));
  10679.  
  10680.     return;
  10681.   }
  10682.  
  10683.   /*
  10684.    * [DB 8/94]
  10685.    *
  10686.    * The object is a CSG union object. It will be split if all siblings are
  10687.    * finite, i.e. the volume of the bounding box doesn't exceed a threshold.
  10688.    */
  10689.  
  10690.   /* NK phmap - added code so union is not split up if it is
  10691.                 flagged for hi-density photon mapping...
  10692.             maybe we SHOULD split it anyways... do speed tests later */
  10693.   if(!((CSG *)Object)->do_split)
  10694.   {
  10695.     Link(Object, &(Object->Sibling), &(Frame.Objects));
  10696.     return;
  10697.   }
  10698.   /* NK ---- */
  10699.  
  10700.   if (Object->Bound != NULL)
  10701.   {
  10702.     /* Test if all siblings are finite. */
  10703.  
  10704.     finite = TRUE;
  10705.  
  10706.     for (This_Sib = ((CSG *)Object)->Children; This_Sib != NULL; This_Sib = This_Sib->Sibling)
  10707.     {
  10708.       BOUNDS_VOLUME(Volume, This_Sib->BBox);
  10709.  
  10710.       if (Volume > BOUND_HUGE)
  10711.       {
  10712.         finite = FALSE;
  10713.  
  10714.         break;
  10715.       }
  10716.     }
  10717.  
  10718.     /*
  10719.      * If the union has infinite children or splitting is not used link
  10720.      * the union to the frame.
  10721.      */
  10722.  
  10723.     if ((!finite) || !(opts.Options & SPLIT_UNION))
  10724.     {
  10725.       if (finite)
  10726.       {
  10727.         Warn(0, "CSG union unnecessarily bounded.");
  10728.       }
  10729.  
  10730.       Link(Object, &(Object->Sibling), &(Frame.Objects));
  10731.  
  10732.       return;
  10733.     }
  10734.  
  10735.     Warn(0, "Bounded CSG union split.");
  10736.   }
  10737.  
  10738.   /* Link all siblings of a union to the frame. */
  10739.  
  10740.   for (This_Sib = ((CSG *)Object)->Children; This_Sib != NULL; This_Sib = Next_Sib)
  10741.   {
  10742.     /* Link_To_Frame() changes Sibling so save it */
  10743.  
  10744.     Next_Sib = This_Sib->Sibling;
  10745.  
  10746.     /* Sibling is no longer inside a CSG object. */
  10747.  
  10748.     This_Sib->Type &= ~IS_CHILD_OBJECT;
  10749.  
  10750.     Link_To_Frame (This_Sib);
  10751.   }
  10752.  
  10753. /*
  10754.   Object->Texture = NULL;
  10755. */
  10756.  
  10757.   Object->Sibling = NULL;
  10758.  
  10759.   ((CSG *)Object)->Children = NULL;
  10760.  
  10761.   Destroy_Object (Object);
  10762. }
  10763.  
  10764.  
  10765.  
  10766. /*****************************************************************************
  10767. *
  10768. * FUNCTION
  10769. *
  10770. * INPUT
  10771. *
  10772. * OUTPUT
  10773. *
  10774. * RETURNS
  10775. *
  10776. * AUTHOR
  10777. *
  10778. * DESCRIPTION
  10779. *
  10780. * CHANGES
  10781. *
  10782. ******************************************************************************/
  10783.  
  10784. void Only_In(char *s1,char  *s2)
  10785. {
  10786.   Error("Keyword '%s' can only be used in a %s statement.",s1,s2);
  10787. }
  10788.  
  10789.  
  10790.  
  10791. /*****************************************************************************
  10792. *
  10793. * FUNCTION
  10794. *
  10795. * INPUT
  10796. *
  10797. * OUTPUT
  10798. *
  10799. * RETURNS
  10800. *
  10801. * AUTHOR
  10802. *
  10803. * DESCRIPTION
  10804. *
  10805. * CHANGES
  10806. *
  10807. ******************************************************************************/
  10808.  
  10809. void Not_With(char *s1,char  *s2)
  10810. {
  10811.   Error("Keyword '%s' cannot be used with %s.",s1,s2);
  10812. }
  10813.  
  10814. void Warn_Compat(int f)
  10815. {
  10816.   Warning(0,"Use of this syntax ");
  10817.  
  10818.   if (f)
  10819.   {
  10820.     Warning(0,"is not");
  10821.   }
  10822.   else
  10823.   {
  10824.     Warning(0,"may not be");
  10825.   }
  10826.     
  10827.   Warning(0," backwards compatable with earlier versions\n%s",
  10828.   "of POV-Ray. The #version directive or +MV switch will not help.\n\n");
  10829. }
  10830.  
  10831. #ifdef BsplinePatch
  10832. /*****************************************************************************
  10833. *
  10834. * FUNCTION
  10835. *
  10836. * INPUT
  10837. *
  10838. * OUTPUT
  10839. *
  10840. * RETURNS
  10841. *
  10842. * AUTHOR
  10843. *
  10844. * DESCRIPTION
  10845. *
  10846. * CHANGES
  10847. *
  10848. ******************************************************************************/
  10849.  
  10850. static void Create_Spline_1D (SPLINE_STACK_1D *base,int nr,char *name,int type,DBL p1,DBL p2)
  10851. {
  10852.     SPLINE *New,*help1;
  10853.     KNOT   *New_Knots;
  10854.     COEFF_1D *New_Coeffs;
  10855.     SPLINE_STACK_1D *help;
  10856.     int   i,t,j;
  10857.  
  10858.     DBL  *a,*b,*c,*rs,*l,*r,*y,*s_j,koeff2,koeff3;
  10859.     
  10860.      
  10861.     New = (SPLINE *)POV_MALLOC(sizeof(SPLINE), NULL);
  10862.  
  10863.     New->name = name;
  10864.     New->type = type;
  10865.     New->res = nr-1;
  10866.     if (New->type==CLOSED_SPLINE) New->res++;
  10867.     New->next=NULL;
  10868.  
  10869.     New_Knots = (KNOT *)POV_MALLOC(sizeof(KNOT)*(New->res+1), NULL);
  10870.  
  10871.     /* copy knots from list to array */
  10872.     
  10873.     help=base;
  10874.     New_Knots[0].t = help->t;
  10875.     New_Knots[0].y = help->y;    
  10876.     i=1;
  10877.     while (help->next !=NULL)
  10878.     {
  10879.         help=(SPLINE_STACK_1D*)help->next;
  10880.         New_Knots[i].t=help->t;
  10881.         New_Knots[i].y=help->y;        
  10882.         i++;
  10883.     }
  10884.     if (type==CLOSED_SPLINE) { New_Knots[i].t=p1; New_Knots[i].y=New_Knots[0].y; }
  10885.  
  10886.     New->Knots = New_Knots;
  10887.  
  10888.  
  10889.     /* the Coefficients ... */
  10890.     
  10891.     New_Coeffs = (COEFF_1D *)POV_MALLOC(sizeof(COEFF_1D)*New->res, NULL);
  10892.     s_j = (DBL *)POV_MALLOC (sizeof(DBL)*(New->res+1), "Spline Stuff (sj's)");
  10893.     a   = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (a)");
  10894.     b   = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (b)");
  10895.     c   = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (c)");
  10896.     rs  = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (rs)");
  10897.     l   = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (l)");
  10898.     r   = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (r)");
  10899.     y   = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (y)");
  10900.     
  10901.     /*    Compute Coeffs ...    */
  10902.     
  10903.     if (type==DIRECTION_SPLINE || type==NATURAL_SPLINE)
  10904.     {
  10905.         /* first and last row of the matrix */
  10906.         if (type==NATURAL_SPLINE)
  10907.         {
  10908.           a[0] = -4/(New_Knots[1].t-New_Knots[0].t);
  10909.           b[0] = -2/((New_Knots[1].t-New_Knots[0].t));
  10910.           c[0] = 0;
  10911.           rs[0] = -6*( (New_Knots[1].y-New_Knots[0].y)/
  10912.           ( (New_Knots[1].t-New_Knots[0].t)*(New_Knots[1].t-New_Knots[0].t) ) );
  10913.     
  10914.           c[nr-1] = 2/(New_Knots[nr-1].t-New_Knots[nr-2].t);
  10915.           a[nr-1] = 4/(New_Knots[nr-1].t-New_Knots[nr-2].t);
  10916.           b[nr-1] = 0;
  10917.           rs[nr-1] = 6*( (New_Knots[nr-1].y-New_Knots[nr-2].y)/
  10918.           ( (New_Knots[nr-1].t-New_Knots[nr-2].t)*(New_Knots[nr-1].t-New_Knots[nr-2].t) ) );
  10919.         }
  10920.  
  10921.         if (type==DIRECTION_SPLINE)
  10922.         {
  10923.           a[0] = 1;
  10924.           b[0] = 0;
  10925.           rs[0] = p1;
  10926.  
  10927.           a[nr-1] = 1;
  10928.           c[nr-1] = 0;
  10929.           rs[nr-1] = p2;
  10930.         }
  10931.  
  10932.         /* the other rows */
  10933.         for (t=1;t<nr-1;t++)
  10934.         {
  10935.           c[t] = New_Knots[t+1].t-New_Knots[t].t;
  10936.           a[t] = 2*((New_Knots[t+1].t-New_Knots[t].t)+(New_Knots[t].t-New_Knots[t-1].t));
  10937.           b[t] = New_Knots[t].t-New_Knots[t-1].t;
  10938.           rs[t] = 3*( ((New_Knots[t+1].y-New_Knots[t].y)/(New_Knots[t+1].t-New_Knots[t].t))*(New_Knots[t].t-New_Knots[t-1].t) );
  10939.           rs[t] = rs[t] + 3*( ((New_Knots[t].y-New_Knots[t-1].y)/(New_Knots[t].t-New_Knots[t-1].t))*(New_Knots[t+1].t-New_Knots[t].t) );
  10940.         }
  10941.  
  10942.         Jacobi(a,b,c,rs,s_j,nr);
  10943.  
  10944.         /* Compute coefficients */
  10945.         for(j=0;j<nr-1;j++)
  10946.         {
  10947.           /* der 3. und 4. Eintrag im Schema der dividierten Differenzen... */
  10948.   
  10949.           koeff2 = ( ( (New_Knots[j+1].y-New_Knots[j].y)/
  10950.           (New_Knots[j+1].t-New_Knots[j].t) ) - s_j[j] )/(New_Knots[j+1].t-New_Knots[j].t);
  10951.           koeff3 = s_j[j+1] + s_j[j] -2*( (New_Knots[j+1].y-New_Knots[j].y)/(New_Knots[j+1].t-New_Knots[j].t) );
  10952.           koeff3 = koeff3/( (New_Knots[j+1].t-New_Knots[j].t)*(New_Knots[j+1].t-New_Knots[j].t) );
  10953.  
  10954.           /* die Koeffizienten der Rj von 1, x, x*x, x*x*x ... */
  10955.           New_Coeffs[j].c[0] = New_Knots[j].y - (New_Knots[j].t*s_j[j]) + (New_Knots[j].t*New_Knots[j].t*koeff2);
  10956.           New_Coeffs[j].c[0] = New_Coeffs[j].c[0] - (New_Knots[j].t*New_Knots[j].t*New_Knots[j+1].t*koeff3);
  10957.           New_Coeffs[j].c[1] = s_j[j] - (2*New_Knots[j].t*koeff2) + ( (2*New_Knots[j].t*New_Knots[j+1].t+New_Knots[j].t*New_Knots[j].t)*koeff3 );
  10958.           New_Coeffs[j].c[2] = koeff2 - (2*New_Knots[j].t + New_Knots[j+1].t)*koeff3;
  10959.           New_Coeffs[j].c[3] = koeff3;
  10960.         }           
  10961.     }
  10962.     else    
  10963.     {
  10964.         /* first and last row */
  10965.         c[0] = New_Knots[1].t-New_Knots[0].t; /* Coeff of s(nr-1) ! */
  10966.         a[0] = 2*(New_Knots[1].t-New_Knots[0].t+New_Knots[nr].t-New_Knots[nr-1].t);
  10967.         b[0] = New_Knots[nr].t-New_Knots[nr-1].t;
  10968.         rs[0] = 3*( ((New_Knots[1].y-New_Knots[0].y)/(New_Knots[1].t-New_Knots[0].t))*(New_Knots[nr].t-New_Knots[nr-1].t) );
  10969.         rs[0] = rs[0] + 3*( ((New_Knots[nr].y-New_Knots[nr-1].y)/(New_Knots[nr].t-New_Knots[nr-1].t))*(New_Knots[1].t-New_Knots[0].t) );
  10970.  
  10971.         /* smooth at t(nr-1) */
  10972.         c[nr-1] = New_Knots[nr].t-New_Knots[nr-1].t;
  10973.         a[nr-1] = 2*(New_Knots[nr].t-New_Knots[nr-2].t);
  10974.         b[nr-1] = New_Knots[nr-1].t-New_Knots[nr-2].t; /* Coeff of s(0) */
  10975.         rs[nr-1] = 3*( ((New_Knots[nr].y-New_Knots[nr-1].y)/(New_Knots[nr].t-New_Knots[nr-1].t))*(New_Knots[nr-1].t-New_Knots[nr-2].t) );
  10976.         rs[nr-1] = rs[nr-1] + 3*( ((New_Knots[nr-1].y-New_Knots[nr-2].y)/(New_Knots[nr-1].t-New_Knots[nr-2].t))*(New_Knots[nr].t-New_Knots[nr-1].t) );
  10977.  
  10978.         /* the other rows */
  10979.         for (t=1;t<nr-1;t++)
  10980.         {
  10981.           c[t] = New_Knots[t+1].t-New_Knots[t].t;
  10982.           a[t] = 2*((New_Knots[t+1].t-New_Knots[t].t)+(New_Knots[t].t-New_Knots[t-1].t));
  10983.           b[t] = New_Knots[t].t-New_Knots[t-1].t;
  10984.           rs[t] = 3*( ((New_Knots[t+1].y-New_Knots[t].y)/(New_Knots[t+1].t-New_Knots[t].t))*(New_Knots[t].t-New_Knots[t-1].t) );
  10985.           rs[t] = rs[t] + 3*( ((New_Knots[t].y-New_Knots[t-1].y)/(New_Knots[t].t-New_Knots[t-1].t))*(New_Knots[t+1].t-New_Knots[t].t) );
  10986.         }
  10987.  
  10988.         /* solve the equivalations with Jacobi process */
  10989.         
  10990.         Jacobi(a,b,c,rs,s_j,nr);
  10991.         
  10992.         s_j[nr] = s_j[0];
  10993.  
  10994.         /* Compute coefficients */
  10995.         for(j=0;j<nr;j++)
  10996.         {
  10997.           /* der 3. und 4. Eintrag im Schema der dividierten Differenzen... */
  10998.   
  10999.           koeff2 = ( ( (New_Knots[j+1].y-New_Knots[j].y)/
  11000.           (New_Knots[j+1].t-New_Knots[j].t) ) - s_j[j] )/(New_Knots[j+1].t-New_Knots[j].t);
  11001.           koeff3 = s_j[j+1] + s_j[j] -2*( (New_Knots[j+1].y-New_Knots[j].y)/(New_Knots[j+1].t-New_Knots[j].t) );
  11002.           koeff3 = koeff3/( (New_Knots[j+1].t-New_Knots[j].t)*(New_Knots[j+1].t-New_Knots[j].t) );
  11003.  
  11004.           /* die Koeffizienten der Rj von 1, x, x*x, x*x*x ...  */
  11005.           New_Coeffs[j].c[0] = New_Knots[j].y - (New_Knots[j].t*s_j[j]) + (New_Knots[j].t*New_Knots[j].t*koeff2);
  11006.           New_Coeffs[j].c[0] = New_Coeffs[j].c[0] - (New_Knots[j].t*New_Knots[j].t*New_Knots[j+1].t*koeff3);
  11007.           New_Coeffs[j].c[1] = s_j[j] - (2*New_Knots[j].t*koeff2) + ( (2*New_Knots[j].t*New_Knots[j+1].t+New_Knots[j].t*New_Knots[j].t)*koeff3 );
  11008.           New_Coeffs[j].c[2] = koeff2 - (2*New_Knots[j].t + New_Knots[j+1].t)*koeff3;
  11009.           New_Coeffs[j].c[3] = koeff3;
  11010.         }           
  11011.     }    
  11012.  
  11013.     New->Coeffs = New_Coeffs;
  11014.  
  11015.     /* destroy the list */
  11016.     
  11017.     while (base != NULL)
  11018.     {
  11019.         help=(SPLINE_STACK_1D*)base->next;
  11020.         POV_FREE(base);
  11021.         base=help;
  11022.     }
  11023.  
  11024.     
  11025.     /* put the new spline in the list */
  11026.  
  11027.     if (The_Splines==NULL) The_Splines=New;
  11028.     else
  11029.     {
  11030.         help1=The_Splines;
  11031.         while(help1->next != NULL) 
  11032.             help1=(SPLINE*)help1->next;
  11033.         help1->next=New;
  11034.     }
  11035.  
  11036.     /* ... und weg damit .... */
  11037.     POV_FREE (s_j);
  11038.     POV_FREE (a);
  11039.     POV_FREE (b);
  11040.     POV_FREE (c);
  11041.     POV_FREE (rs);
  11042.     POV_FREE (l);
  11043.     POV_FREE (r);
  11044.     POV_FREE (y);    
  11045. }
  11046. #endif
  11047.  
  11048. /*****************************************************************************
  11049. *
  11050. * FUNCTION
  11051. *
  11052. *  Set_CSG_Children_Hollow
  11053. *
  11054. * INPUT
  11055. *
  11056. * OUTPUT
  11057. *
  11058. * RETURNS
  11059. *
  11060. * AUTHOR
  11061. *
  11062. * DESCRIPTION
  11063. *
  11064. * CHANGES
  11065. *
  11066. ******************************************************************************/
  11067.  
  11068. static void Set_CSG_Children_Flag(OBJECT *Object, unsigned long f, unsigned long  flag, unsigned long  set_flag)
  11069. {
  11070.   OBJECT *Sib;
  11071.  
  11072.   for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  11073.   {
  11074.     if (!Test_Flag(Sib, set_flag))
  11075.     {
  11076.       if ((Sib->Methods == &CSG_Intersection_Methods) ||
  11077.           (Sib->Methods == &CSG_Merge_Methods) ||
  11078.           (Sib->Methods == &CSG_Union_Methods))
  11079.       {
  11080.         Set_CSG_Children_Flag(Sib, f, flag, set_flag);
  11081.       }
  11082.       else
  11083.       {
  11084.         Sib->Flags = (Sib->Flags & (~flag)) | f;
  11085.       }
  11086.     }
  11087.   }
  11088. }
  11089.  
  11090.  
  11091.  
  11092. static void *Copy_Identifier (void *Data, int Type)
  11093. {
  11094.   int i;
  11095.   POV_ARRAY *a, *na;
  11096.   VECTOR *vp;
  11097.   DBL *dp;
  11098.   UV_VECT *uvp;
  11099.   VECTOR_4D *v4p;
  11100.   void *New;
  11101.   
  11102.   if (Data==NULL)
  11103.   {
  11104.      return(NULL);
  11105.   }
  11106.  
  11107.   switch (Type)
  11108.   {
  11109.      case COLOUR_ID_TOKEN:
  11110.        New = (void *)Copy_Colour(*(COLOUR *)Data);
  11111.        break;
  11112.      case VECTOR_ID_TOKEN:
  11113.        vp = Create_Vector();
  11114.        Assign_Vector((*vp),(*((VECTOR *)Data)));
  11115.        New=vp;
  11116.        break;
  11117.      case UV_ID_TOKEN:
  11118.        uvp = Create_UV_Vect();
  11119.        Assign_Vector((*uvp),(*((UV_VECT *)Data)));
  11120.        New=uvp;
  11121.        break;
  11122.      case VECTOR_4D_ID_TOKEN:
  11123.        v4p = Create_Vector_4D();
  11124.        Assign_Vector_4D((*v4p),(*((VECTOR_4D *)Data)));
  11125.        New=v4p;
  11126.        break;
  11127.      case FLOAT_ID_TOKEN:
  11128.        dp = Create_Float();
  11129.        *dp = *((DBL *)Data);
  11130.        New = dp;
  11131.        break;
  11132.      case PIGMENT_ID_TOKEN:
  11133.      case DENSITY_ID_TOKEN:
  11134.        New = (void *)Copy_Pigment((PIGMENT *)Data);
  11135.        break;
  11136.      case TNORMAL_ID_TOKEN:
  11137.        New = (void *)Copy_Tnormal((TNORMAL *)Data);
  11138.        break;
  11139.      case FINISH_ID_TOKEN:
  11140.        New = (void *)Copy_Finish((FINISH *)Data);
  11141.        break;
  11142.      case MEDIA_ID_TOKEN:
  11143.        New = (void *)Copy_Media((IMEDIA *)Data);
  11144.        break;
  11145.      case INTERIOR_ID_TOKEN:
  11146.        New = (void *)Copy_Interior((INTERIOR *)Data);
  11147.        break;
  11148.      case MATERIAL_ID_TOKEN:
  11149.        New = (void *)Copy_Material((MATERIAL *)Data);
  11150.        break;
  11151.      case TEXTURE_ID_TOKEN:
  11152.        New = (void *)Copy_Textures((TEXTURE *)Data);
  11153.        break;
  11154.      case OBJECT_ID_TOKEN:
  11155.        New = (void *)Copy_Object((OBJECT *)Data);
  11156.        break;
  11157.      case COLOUR_MAP_ID_TOKEN:
  11158.      case PIGMENT_MAP_ID_TOKEN:
  11159.      case SLOPE_MAP_ID_TOKEN:
  11160.      case TEXTURE_MAP_ID_TOKEN:
  11161.      case NORMAL_MAP_ID_TOKEN:
  11162.      case DENSITY_MAP_ID_TOKEN:
  11163.        New = (void *)Copy_Blend_Map((BLEND_MAP *)Data);
  11164.        break;
  11165.      case TRANSFORM_ID_TOKEN:
  11166.        New = (void *)Copy_Transform((TRANSFORM *)Data);
  11167.        break;
  11168.      case CAMERA_ID_TOKEN:
  11169.        New = (void *)Copy_Camera((CAMERA *)Data);
  11170.        break;
  11171.      case RAINBOW_ID_TOKEN:
  11172.        New = (void *)Copy_Rainbow((RAINBOW *)Data);
  11173.        break;
  11174.      case FOG_ID_TOKEN:
  11175.        New = (void *)Copy_Fog((FOG *)Data);
  11176.        break;
  11177.      case SKYSPHERE_ID_TOKEN:
  11178.        New = (void *)Copy_Skysphere((SKYSPHERE *)Data);
  11179.        break;
  11180.      case STRING_ID_TOKEN:
  11181.        New = (void *)POV_STRDUP((char *)Data);
  11182.        break;
  11183.      case ARRAY_ID_TOKEN:
  11184.        a=(POV_ARRAY *)Data;
  11185.        na=(POV_ARRAY *)POV_MALLOC(sizeof(POV_ARRAY),"array");
  11186.        *na=*a;
  11187.        na->DataPtrs = (void **)POV_MALLOC(sizeof(void *)*(a->Total),"array");
  11188.        for (i=0; i<a->Total; i++)
  11189.        {
  11190.          na->DataPtrs[i] = (void *)Copy_Identifier (a->DataPtrs[i],a->Type);
  11191.        }
  11192.        New = (void *)na;
  11193.        break;
  11194.      default:
  11195.        Error("Cannot copy identifier");
  11196.        New = NULL; /* tw */
  11197.    }
  11198.    return(New);
  11199. }
  11200.  
  11201. #ifdef BsplinePatch
  11202.  
  11203. /*****************************************************************************
  11204. *
  11205. * FUNCTION
  11206. *
  11207. * INPUT
  11208. *
  11209. * OUTPUT
  11210. *
  11211. * RETURNS
  11212. *
  11213. * AUTHOR
  11214. *
  11215. * DESCRIPTION
  11216. *
  11217. * CHANGES
  11218. *
  11219. ******************************************************************************/
  11220.  
  11221. static void Create_Spline_3D (SPLINE_STACK_3D *base,int nr,char *name,int type,VECTOR temp1,VECTOR temp2)
  11222. {
  11223.     SPLINE_3D *New,*help1;
  11224.     KNOT3D   *New_Knots;
  11225.     SPLINE_STACK_3D *help;
  11226.     DBL      sp_len=0,delta_len;
  11227.     int      i,s,t,j;
  11228.     COEFF_3D *New_Coeffs;
  11229.     DBL  *a,*b,*c,*rs,*l,*r,*y,*s_j,koeff2,koeff3;
  11230.  
  11231.  
  11232.     New = (SPLINE_3D *)POV_MALLOC(sizeof(SPLINE_3D), NULL);
  11233.  
  11234.     New->name = name;
  11235.     New->type = type;
  11236.     New->res = nr-1;
  11237.     if (New->type==CLOSED_SPLINE) New->res++;
  11238.     New->next=NULL;
  11239.  
  11240.     New_Knots = (KNOT3D *)POV_MALLOC(sizeof(KNOT3D)*(New->res+1), NULL);
  11241.  
  11242.     /* copy knots from list to array */
  11243.     
  11244.     help=base;
  11245.     New_Knots[0].y[X] = help->Knot[X];
  11246.     New_Knots[0].y[Y] = help->Knot[Y];
  11247.     New_Knots[0].y[Z] = help->Knot[Z];
  11248.     i=1;
  11249.     while (help->next !=NULL)
  11250.     {
  11251.         help=(SPLINE_STACK_3D*)help->next;
  11252.         New_Knots[i].y[X] = help->Knot[X];
  11253.         New_Knots[i].y[Y] = help->Knot[Y];
  11254.         New_Knots[i].y[Z] = help->Knot[Z];
  11255.         i++;
  11256.     }
  11257.     if (type==CLOSED_SPLINE)
  11258.     {
  11259.         New_Knots[i].y[X]=New_Knots[0].y[X];
  11260.         New_Knots[i].y[Y]=New_Knots[0].y[Y];
  11261.         New_Knots[i].y[Z]=New_Knots[0].y[Z];
  11262.     }
  11263.  
  11264.     New->Knots = New_Knots;
  11265.  
  11266.     /* get t's from distance of control points */
  11267.     /* compute splines lenghth first */
  11268.     
  11269.     for (i=0;i<New->res;i++)
  11270.     {
  11271.         VDist(delta_len,New_Knots[i+1].y,New_Knots[i].y);
  11272.         sp_len = sp_len + delta_len;
  11273.     }
  11274.  
  11275.     /* knots from 0 to 1 ... */
  11276.     
  11277.     New_Knots[0].t=0;
  11278.     New_Knots[New->res].t=1;
  11279.  
  11280.     for (i=1;i<New->res;i++)
  11281.     {
  11282.         VDist(delta_len,New_Knots[i].y,New_Knots[i-1].y);
  11283.         New_Knots[i].t = New_Knots[i-1].t+delta_len/sp_len;
  11284.     }
  11285.  
  11286.     /* destroy the list */
  11287.     
  11288.     while (base != NULL)
  11289.     {
  11290.         help=(SPLINE_STACK_3D*)base->next;
  11291.         POV_FREE(base);
  11292.         base=help;
  11293.     }
  11294.  
  11295.     /* the Coefficients ... */
  11296.     
  11297.     New_Coeffs = (COEFF_3D *)POV_MALLOC(sizeof(COEFF_3D)*New->res, NULL);
  11298.     s_j = (DBL *)POV_MALLOC (sizeof(DBL)*(New->res+1), "Spline Stuff (sj's)");
  11299.     a   = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (a)");
  11300.     b   = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (b)");
  11301.     c   = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (c)");
  11302.     rs  = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (rs)");
  11303.     l   = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (l)");
  11304.     r   = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (r)");
  11305.     y   = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (y)");
  11306.     
  11307.     /*    Compute Coeffs ...    */
  11308.  
  11309.     for (s=0;s<3;s++) /* for each coordinate */
  11310.     {
  11311.     if (type==DIRECTION_SPLINE || type==NATURAL_SPLINE)
  11312.     {
  11313.         /* first and last row of the matrix */
  11314.         if (type==NATURAL_SPLINE)
  11315.         {
  11316.           a[0] = -4/(New_Knots[1].t-New_Knots[0].t);
  11317.           b[0] = -2/((New_Knots[1].t-New_Knots[0].t));
  11318.           c[0] = 0;
  11319.           rs[0] = -6*( (New_Knots[1].y[s]-New_Knots[0].y[s])/
  11320.           ( (New_Knots[1].t-New_Knots[0].t)*(New_Knots[1].t-New_Knots[0].t) ) );
  11321.     
  11322.           c[nr-1] = 2/(New_Knots[nr-1].t-New_Knots[nr-2].t);
  11323.           a[nr-1] = 4/(New_Knots[nr-1].t-New_Knots[nr-2].t);
  11324.           b[nr-1] = 0;
  11325.           rs[nr-1] = 6*( (New_Knots[nr-1].y[s]-New_Knots[nr-2].y[s])/
  11326.           ( (New_Knots[nr-1].t-New_Knots[nr-2].t)*(New_Knots[nr-1].t-New_Knots[nr-2].t) ) );
  11327.         }
  11328.  
  11329.         if (type==DIRECTION_SPLINE)
  11330.         {
  11331.           a[0] = 1;
  11332.           b[0] = 0;
  11333.           rs[0] = temp1[s];
  11334.  
  11335.           a[nr-1] = 1;
  11336.           c[nr-1] = 0;
  11337.           rs[nr-1] = temp2[s];
  11338.         }
  11339.  
  11340.         /* the other rows */
  11341.         for (t=1;t<nr-1;t++)
  11342.         {
  11343.           c[t] = New_Knots[t+1].t-New_Knots[t].t;
  11344.           a[t] = 2*((New_Knots[t+1].t-New_Knots[t].t)+(New_Knots[t].t-New_Knots[t-1].t));
  11345.           b[t] = New_Knots[t].t-New_Knots[t-1].t;
  11346.           rs[t] = 3*( ((New_Knots[t+1].y[s]-New_Knots[t].y[s])/(New_Knots[t+1].t-New_Knots[t].t))*(New_Knots[t].t-New_Knots[t-1].t) );
  11347.           rs[t] = rs[t] + 3*( ((New_Knots[t].y[s]-New_Knots[t-1].y[s])/(New_Knots[t].t-New_Knots[t-1].t))*(New_Knots[t+1].t-New_Knots[t].t) );
  11348.         }
  11349.  
  11350.         Jacobi(a,b,c,rs,s_j,nr);
  11351.  
  11352.         /* Compute coefficients */
  11353.         for(j=0;j<nr-1;j++)
  11354.         {
  11355.           /* der 3. und 4. Eintrag im Schema der dividierten Differenzen... */
  11356.   
  11357.           koeff2 = ( ( (New_Knots[j+1].y[s]-New_Knots[j].y[s])/
  11358.           (New_Knots[j+1].t-New_Knots[j].t) ) - s_j[j] )/(New_Knots[j+1].t-New_Knots[j].t);
  11359.           koeff3 = s_j[j+1] + s_j[j] -2*( (New_Knots[j+1].y[s]-New_Knots[j].y[s])/(New_Knots[j+1].t-New_Knots[j].t) );
  11360.           koeff3 = koeff3/( (New_Knots[j+1].t-New_Knots[j].t)*(New_Knots[j+1].t-New_Knots[j].t) );
  11361.  
  11362.           /* die Koeffizienten der Rj von 1, x, x*x, x*x*x ...  */
  11363.           New_Coeffs[j].c[s][0] = New_Knots[j].y[s] - (New_Knots[j].t*s_j[j]) + (New_Knots[j].t*New_Knots[j].t*koeff2);
  11364.           New_Coeffs[j].c[s][0] = New_Coeffs[j].c[s][0] - (New_Knots[j].t*New_Knots[j].t*New_Knots[j+1].t*koeff3);
  11365.           New_Coeffs[j].c[s][1] = s_j[j] - (2*New_Knots[j].t*koeff2) + ( (2*New_Knots[j].t*New_Knots[j+1].t+New_Knots[j].t*New_Knots[j].t)*koeff3 );
  11366.           New_Coeffs[j].c[s][2] = koeff2 - (2*New_Knots[j].t + New_Knots[j+1].t)*koeff3;
  11367.           New_Coeffs[j].c[s][3] = koeff3;
  11368.         }           
  11369.     }
  11370.     else    
  11371.     {
  11372.         /* first and last row */
  11373.         /* smooth at t(0) , t(nr) */
  11374.         c[0] = New_Knots[1].t-New_Knots[0].t; /* Coeff of s(nr-1) ! */
  11375.         a[0] = 2*(New_Knots[1].t-New_Knots[0].t+New_Knots[nr].t-New_Knots[nr-1].t);
  11376.         b[0] = New_Knots[nr].t-New_Knots[nr-1].t;
  11377.         rs[0] = 3*( ((New_Knots[1].y[s]-New_Knots[0].y[s])/(New_Knots[1].t-New_Knots[0].t))*(New_Knots[nr].t-New_Knots[nr-1].t) );
  11378.         rs[0] = rs[0] + 3*( ((New_Knots[nr].y[s]-New_Knots[nr-1].y[s])/(New_Knots[nr].t-New_Knots[nr-1].t))*(New_Knots[1].t-New_Knots[0].t) );
  11379.       
  11380.         /* smooth at t(nr-1) */
  11381.         c[nr-1] = New_Knots[nr].t-New_Knots[nr-1].t;
  11382.         a[nr-1] = 2*(New_Knots[nr].t-New_Knots[nr-2].t);
  11383.         b[nr-1] = New_Knots[nr-1].t-New_Knots[nr-2].t; /* Coeff of s(0) */
  11384.         rs[nr-1] = 3*( ((New_Knots[nr].y[s]-New_Knots[nr-1].y[s])/(New_Knots[nr].t-New_Knots[nr-1].t))*(New_Knots[nr-1].t-New_Knots[nr-2].t) );
  11385.         rs[nr-1] = rs[nr-1] + 3*( ((New_Knots[nr-1].y[s]-New_Knots[nr-2].y[s])/(New_Knots[nr-1].t-New_Knots[nr-2].t))*(New_Knots[nr].t-New_Knots[nr-1].t) );
  11386.  
  11387.         /* the other rows */
  11388.         for (t=1;t<nr-1;t++)
  11389.         {
  11390.           c[t] = New_Knots[t+1].t-New_Knots[t].t;
  11391.           a[t] = 2*((New_Knots[t+1].t-New_Knots[t].t)+(New_Knots[t].t-New_Knots[t-1].t));
  11392.           b[t] = New_Knots[t].t-New_Knots[t-1].t;
  11393.           rs[t] = 3*( ((New_Knots[t+1].y[s]-New_Knots[t].y[s])/(New_Knots[t+1].t-New_Knots[t].t))*(New_Knots[t].t-New_Knots[t-1].t) );
  11394.           rs[t] = rs[t] + 3*( ((New_Knots[t].y[s]-New_Knots[t-1].y[s])/(New_Knots[t].t-New_Knots[t-1].t))*(New_Knots[t+1].t-New_Knots[t].t) );
  11395.         }
  11396.  
  11397.         /* solve the equivalations with Jacobi process */
  11398.         
  11399.         Jacobi(a,b,c,rs,s_j,nr);
  11400.         
  11401.         s_j[nr] = s_j[0];
  11402.  
  11403.         /* Compute coefficients */
  11404.         for(j=0;j<nr;j++)
  11405.         {
  11406.           /* der 3. und 4. Eintrag im Schema der dividierten Differenzen... */
  11407.   
  11408.           koeff2 = ( ( (New_Knots[j+1].y[s]-New_Knots[j].y[s])/
  11409.           (New_Knots[j+1].t-New_Knots[j].t) ) - s_j[j] )/(New_Knots[j+1].t-New_Knots[j].t);
  11410.           koeff3 = s_j[j+1] + s_j[j] -2*( (New_Knots[j+1].y[s]-New_Knots[j].y[s])/(New_Knots[j+1].t-New_Knots[j].t) );
  11411.           koeff3 = koeff3/( (New_Knots[j+1].t-New_Knots[j].t)*(New_Knots[j+1].t-New_Knots[j].t) );
  11412.  
  11413.           /* die Koeffizienten der Rj von 1, x, x*x, x*x*x ...  */
  11414.           New_Coeffs[j].c[s][0] = New_Knots[j].y[s] - (New_Knots[j].t*s_j[j]) + (New_Knots[j].t*New_Knots[j].t*koeff2);
  11415.           New_Coeffs[j].c[s][0] = New_Coeffs[j].c[s][0] - (New_Knots[j].t*New_Knots[j].t*New_Knots[j+1].t*koeff3);
  11416.           New_Coeffs[j].c[s][1] = s_j[j] - (2*New_Knots[j].t*koeff2) + ( (2*New_Knots[j].t*New_Knots[j+1].t+New_Knots[j].t*New_Knots[j].t)*koeff3 );
  11417.           New_Coeffs[j].c[s][2] = koeff2 - (2*New_Knots[j].t + New_Knots[j+1].t)*koeff3;
  11418.           New_Coeffs[j].c[s][3] = koeff3;
  11419.         }           
  11420.     }
  11421.     }
  11422.  
  11423.     New->Coeffs = New_Coeffs;
  11424.  
  11425.     /* put the new spline in the list */
  11426.  
  11427.     if (The_3D_Splines==NULL) The_3D_Splines=New;
  11428.     else
  11429.     {
  11430.         help1=The_3D_Splines;
  11431.         while(help1->next != NULL) 
  11432.             help1=(SPLINE_3D*)help1->next;
  11433.         help1->next=New;
  11434.     }
  11435.  
  11436.     /* ... und weg damit .... */
  11437.     POV_FREE (s_j);
  11438.     POV_FREE (a);
  11439.     POV_FREE (b);
  11440.     POV_FREE (c);
  11441.     POV_FREE (rs);
  11442.     POV_FREE (l);
  11443.     POV_FREE (r);
  11444.     POV_FREE (y);    
  11445. }   
  11446.  
  11447. /*****************************************************************************
  11448. *
  11449. * FUNCTION
  11450. *
  11451. * INPUT
  11452. *
  11453. * OUTPUT
  11454. *
  11455. * RETURNS
  11456. *
  11457. * AUTHOR
  11458. *
  11459. * DESCRIPTION
  11460. *
  11461. * CHANGES
  11462. *
  11463. ******************************************************************************/
  11464.  
  11465. static void Jacobi (DBL *a,DBL *b,DBL *c,DBL *rs,DBL *s,int n)
  11466. {
  11467.     int i,is_first=TRUE;
  11468.     DBL err=1,*next_s;
  11469.     
  11470.     next_s = (DBL *)POV_MALLOC (sizeof(DBL)*(n), "Spline Stuff ");
  11471.  
  11472.     /* modify right side and matrix and set startpoint to 0 */
  11473.     for (i=0;i<n;i++)
  11474.     {
  11475.         rs[i] = rs[i]/a[i];
  11476.         b[i] = -b[i]/a[i];
  11477.         c[i] = -c[i]/a[i];
  11478.         a[i] = 0;
  11479.         s[i] = 0;
  11480.     }
  11481.  
  11482.     while (err>0.000000001)
  11483.     {
  11484.         /* first row */
  11485.         next_s[0] = s[1]*b[0]+s[n-1]*c[0];
  11486.         /* row 1 to n-2 */
  11487.         for (i=1;i<n-1;i++) next_s[i] = c[i]*s[i-1]+b[i]*s[i+1];
  11488.         /* last row */
  11489.         next_s[n-1] = b[n-1]*s[0]+c[n-1]*s[n-2];
  11490.  
  11491.         for(i=0;i<n;i++) next_s[i]=next_s[i]+rs[i];
  11492.  
  11493.         if (is_first)
  11494.         {
  11495.             is_first=FALSE;
  11496.             err=0;
  11497.             for(i=0;i<n;i++) if (fabs(next_s[i]>err)) err=fabs(next_s[i]);
  11498.         }
  11499.         else
  11500.         {
  11501.             err *= 0.5;
  11502.         }
  11503.         for(i=0;i<n;i++) s[i]=next_s[i];
  11504.     }
  11505.  
  11506.     POV_FREE (next_s);    
  11507. }
  11508.  
  11509. /*****************************************************************************
  11510. *
  11511. * FUNCTION
  11512. *
  11513. * INPUT
  11514. *
  11515. * OUTPUT
  11516. *
  11517. * RETURNS
  11518. *
  11519. * AUTHOR
  11520. *
  11521. * DESCRIPTION
  11522. *
  11523. * CHANGES
  11524. *
  11525. ******************************************************************************/
  11526.  
  11527. static void Destroy_Splines ()
  11528. {
  11529.     SPLINE *help1;
  11530.     SPLINE_3D *help2;
  11531.  
  11532.     while (The_Splines != NULL)
  11533.     {
  11534.         help1=(SPLINE*)The_Splines->next;
  11535.         POV_FREE(The_Splines->name);
  11536.         POV_FREE(The_Splines->Coeffs);
  11537.         POV_FREE(The_Splines->Knots);
  11538.         POV_FREE(The_Splines);
  11539.         The_Splines=help1;
  11540.     }
  11541.     
  11542.     while (The_3D_Splines != NULL)
  11543.     {
  11544.         help2=(SPLINE_3D*)The_3D_Splines->next;
  11545.         POV_FREE(The_3D_Splines->name);
  11546.         POV_FREE(The_3D_Splines->Coeffs);
  11547.         POV_FREE(The_3D_Splines->Knots);
  11548.         POV_FREE(The_3D_Splines);
  11549.         The_3D_Splines=help2;
  11550.     }
  11551. }
  11552.  
  11553. #endif
  11554.  
  11555.  
  11556. /* NK layers - 1999 June 10 - for backwards compatiblity with layered textures */
  11557. void Convert_Filter_To_Transmit(PIGMENT *Pigment)
  11558. {
  11559.   int i;
  11560.   BLEND_MAP *Map;
  11561.  
  11562.   if (Pigment==NULL) return;
  11563.  
  11564.   switch (Pigment->Type)
  11565.   {
  11566.     case PLAIN_PATTERN:
  11567.       Pigment->Colour[TRANSM]+=Pigment->Colour[FILTER];
  11568.       Pigment->Colour[FILTER]=0;
  11569.       break;
  11570.  
  11571.     default:
  11572.       if (Pigment->Blend_Map != NULL)
  11573.       {
  11574.         Map = Pigment->Blend_Map;
  11575.         /* go through blend map */
  11576.         if ((Map->Type == PIGMENT_TYPE) || (Map->Type == DENSITY_TYPE))
  11577.         {
  11578.            for (i = 0; i < Map->Number_Of_Entries; i++)
  11579.            {
  11580.              Convert_Filter_To_Transmit(Map->Blend_Map_Entries[i].Vals.Pigment);
  11581.            }
  11582.         }
  11583.         else
  11584.         {
  11585.            for (i = 0; i < Map->Number_Of_Entries; i++)
  11586.            {
  11587.              Map->Blend_Map_Entries[i].Vals.Colour[TRANSM]+=Map->Blend_Map_Entries[i].Vals.Colour[FILTER];
  11588.              Map->Blend_Map_Entries[i].Vals.Colour[FILTER]=0;
  11589.            }
  11590.         }
  11591.  
  11592.       }
  11593.  
  11594.       break;
  11595.   }
  11596. }
  11597. /* NK ---- */
  11598.  
  11599. #ifdef IsoBlobPatch
  11600.  
  11601. /* Isoblob parse routines -- Lummox JR, July 1999 */
  11602.  
  11603. /*****************************************************************************
  11604. *
  11605. * FUNCTION
  11606. *
  11607. *   Parse_Blob_Element_Mods
  11608. *
  11609. * INPUT
  11610. *   
  11611. * OUTPUT
  11612. *   
  11613. * RETURNS
  11614. *   
  11615. * DESCRIPTION
  11616. *
  11617. *   -
  11618. *
  11619. * CHANGES
  11620. *
  11621. *   Jul 1999 : Creation.
  11622. *
  11623. ******************************************************************************/
  11624.  
  11625. static void Parse_Isoblob_Element_Mods(ISOBLOB_ELEMENT *Element)
  11626. {
  11627.   VECTOR Local_Vector;
  11628.   MATRIX Local_Matrix;
  11629.   TRANSFORM Local_Trans;
  11630.   TEXTURE *Local_Texture;
  11631.  
  11632.   EXPECT
  11633.     CASE (TRANSLATE_TOKEN)
  11634.       Parse_Vector (Local_Vector);
  11635.       Translate_Isoblob_Element (Element, Local_Vector);
  11636.     END_CASE
  11637.  
  11638.     CASE (ROTATE_TOKEN)
  11639.       Parse_Vector (Local_Vector);
  11640.       Rotate_Isoblob_Element (Element, Local_Vector);
  11641.     END_CASE
  11642.  
  11643.     CASE (SCALE_TOKEN)
  11644.       Parse_Scale_Vector (Local_Vector);
  11645.       Scale_Isoblob_Element (Element, Local_Vector);
  11646.     END_CASE
  11647.  
  11648.     CASE (TRANSFORM_TOKEN)
  11649. #ifndef TransformPatch /* Chris Huff april 2000 */
  11650.       GET(TRANSFORM_ID_TOKEN)
  11651.       Transform_Isoblob_Element (Element, (TRANSFORM *)Token.Data);
  11652. #else
  11653.        {
  11654.            TRANSFORM * Trans = Parse_Transform();
  11655.            Transform_Isoblob_Element (Element, Trans);
  11656.             /*YS sept 17 2000 Memory leak*/
  11657.                 POV_FREE(Trans);
  11658.        }
  11659. #endif
  11660.     END_CASE
  11661.  
  11662.     CASE (MATRIX_TOKEN)
  11663.       Parse_Matrix (Local_Matrix);
  11664.       Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  11665.       Transform_Isoblob_Element (Element, &Local_Trans);
  11666.     END_CASE
  11667.  
  11668.     CASE (TEXTURE_TOKEN)
  11669.       Parse_Begin ();
  11670.       Local_Texture = Parse_Texture();
  11671.       Parse_End ();
  11672.       Link_Textures(&Element->Texture, Local_Texture);
  11673.     END_CASE
  11674.  
  11675.     CASE3 (PIGMENT_TOKEN, TNORMAL_TOKEN, FINISH_TOKEN)
  11676.       if (Element->Texture == NULL)
  11677.       {
  11678.         Element->Texture = Copy_Textures(Default_Texture);
  11679.       }
  11680.       else
  11681.       {
  11682.         if (Element->Texture->Type != PLAIN_PATTERN)
  11683.         {
  11684.            Link_Textures(&Element->Texture, Copy_Textures(Default_Texture));
  11685.         }
  11686.       }
  11687.       UNGET
  11688.  
  11689.       EXPECT
  11690.         CASE (PIGMENT_TOKEN)
  11691.           Parse_Begin ();
  11692.           Parse_Pigment(&Element->Texture->Pigment);
  11693.           Parse_End ();
  11694.         END_CASE
  11695.  
  11696.         CASE (TNORMAL_TOKEN)
  11697.           Parse_Begin ();
  11698.           Parse_Tnormal(&Element->Texture->Tnormal);
  11699.           Parse_End ();
  11700.         END_CASE
  11701.  
  11702.         CASE (FINISH_TOKEN)
  11703.           Parse_Finish(&Element->Texture->Finish);
  11704.         END_CASE
  11705.  
  11706.         OTHERWISE
  11707.           UNGET
  11708.           EXIT
  11709.         END_CASE
  11710.       END_EXPECT
  11711.     END_CASE
  11712.  
  11713.     OTHERWISE
  11714.       UNGET
  11715.       EXIT
  11716.     END_CASE
  11717.   END_EXPECT
  11718.  
  11719.   Parse_End();
  11720.  
  11721.   /* Postprocess to make sure that HAS_FILTER will be set correctly. */
  11722.  
  11723.   Post_Textures(Element->Texture);
  11724. }
  11725.  
  11726. /*****************************************************************************
  11727. *
  11728. * FUNCTION
  11729. *
  11730. *   Parse_Isoblob
  11731. *
  11732. * INPUT
  11733. *
  11734. * OUTPUT
  11735. *   
  11736. * RETURNS
  11737. *   
  11738. * DESCRIPTION
  11739. *
  11740. *   -
  11741. *
  11742. * CHANGES
  11743. *
  11744. *   Jul 1999 : Creation.
  11745. *
  11746. ******************************************************************************/
  11747.  
  11748. static OBJECT *Parse_Isoblob()
  11749. {
  11750.   int npoints,nfuncs,myfunc,i;
  11751.   char normal_type=0;
  11752.   DBL threshold,accuracy;
  11753.   int max_trace;
  11754.   VECTOR Axis, Base, Apex;
  11755.   ISOBLOB *Object;
  11756.   ISOBLOB_LIST *isoblob_components, *isoblob_component;
  11757.   ISOBLOB_FUNC_LIST *isoblob_funcs, *isoblob_func, *thisfunc;
  11758.   FUNCTION *func;
  11759.  
  11760.   Parse_Begin();
  11761.  
  11762.   if ((Object = (ISOBLOB *)Parse_Object_Id()) != NULL)
  11763.   {
  11764.     return ((OBJECT *) Object);
  11765.   }
  11766.  
  11767.   Object = Create_Isoblob();
  11768.  
  11769.   isoblob_components = NULL;
  11770.   isoblob_funcs = NULL;
  11771.  
  11772.   npoints = 0;
  11773.   nfuncs = 0;
  11774.  
  11775.   threshold = 1.0;
  11776.   accuracy = 1.0e-6;
  11777.   max_trace = 10;
  11778.  
  11779.   EXPECT
  11780.     CASE (THRESHOLD_TOKEN)
  11781.       threshold = Parse_Float();
  11782.     END_CASE
  11783.  
  11784.     CASE (ACCURACY_TOKEN)
  11785.       accuracy = Parse_Float();
  11786.     END_CASE
  11787.  
  11788.     CASE (MAX_TRACE_TOKEN)
  11789.       max_trace = Parse_Float();
  11790.     END_CASE
  11791.  
  11792.     CASE (TNORMAL_TOKEN)
  11793.       normal_type = (char)(int)Allow_Float(1.0);
  11794.     END_CASE
  11795.  
  11796.     CASE (FUNCTION_TOKEN)
  11797.         if(npoints>0) Error("Isoblob density functions must be specified before components");
  11798.         else
  11799.         {
  11800.         func=Parse_Function();
  11801.         func->sign=-1;        /* To insure proper operation */
  11802.           isoblob_func=(ISOBLOB_FUNC_LIST*)Create_Isoblob_List_Element();
  11803.         isoblob_func->func=func;
  11804.         if(isoblob_funcs==NULL) isoblob_funcs=isoblob_func;
  11805.         else
  11806.         {
  11807.           for(thisfunc=isoblob_funcs;thisfunc->next!=NULL;thisfunc=thisfunc->next);
  11808.           thisfunc->next=isoblob_func;
  11809.         }
  11810.         ++nfuncs;
  11811.       }
  11812.     END_CASE
  11813.     /*************************************************************************
  11814.      * Read sperical component.
  11815.      *************************************************************************/
  11816.  
  11817.     CASE (SPHERE_TOKEN)
  11818.       isoblob_component = Create_Isoblob_List_Element();
  11819.  
  11820.       isoblob_component->elem.Type = ISOBLOB_SPHERE;
  11821.       isoblob_component->elem.Trans = Create_Transform();
  11822.  
  11823.       Parse_Begin();
  11824.  
  11825.       Parse_Vector(Base);
  11826.       Compute_Translation_Transform(isoblob_component->elem.Trans,Base);
  11827.  
  11828.       Parse_Comma();
  11829.  
  11830.       isoblob_component->elem.rad2 = Parse_Float();
  11831.  
  11832.       isoblob_component->elem.rad2 = Sqr(isoblob_component->elem.rad2);
  11833.  
  11834.       Parse_Comma();
  11835.  
  11836.       ALLOW(STRENGTH_TOKEN)
  11837.  
  11838.       isoblob_component->elem.str = Parse_Float();
  11839.  
  11840.       ALLOW(FUNCTION_TOKEN)
  11841.       myfunc=(int)Parse_Float();
  11842.  
  11843.       if(myfunc<1 || myfunc>nfuncs) {Error("Function #%d is not defined for this isoblob.",nfuncs);}
  11844.  
  11845.       for(i=1,thisfunc=isoblob_funcs;(thisfunc!=NULL && i<myfunc);thisfunc=thisfunc->next,++i);
  11846.       isoblob_component->elem.Func=thisfunc->func;
  11847.  
  11848.       Parse_Isoblob_Element_Mods(&isoblob_component->elem);
  11849.  
  11850.       /* Next component. */
  11851.  
  11852.       isoblob_component->next = isoblob_components;
  11853.  
  11854.       isoblob_components = isoblob_component;
  11855.  
  11856.       npoints++;
  11857.     END_CASE
  11858.  
  11859.     /*************************************************************************
  11860.      * Read cylindrical component.
  11861.      *************************************************************************/
  11862.  
  11863.     CASE (CYLINDER_TOKEN)
  11864.       isoblob_component = Create_Isoblob_List_Element();
  11865.  
  11866.       isoblob_component->elem.Type = ISOBLOB_CYLINDER;
  11867.  
  11868.       isoblob_component->elem.Trans = Create_Transform();
  11869.  
  11870.       Parse_Begin();
  11871.  
  11872.       Parse_Vector(Base);
  11873.  
  11874.       Parse_Comma();
  11875.  
  11876.       Parse_Vector(Apex);
  11877.  
  11878.       Parse_Comma();
  11879.  
  11880.       isoblob_component->elem.rad2 = Parse_Float();
  11881.  
  11882.       isoblob_component->elem.rad2 = Sqr(isoblob_component->elem.rad2);
  11883.  
  11884.       Parse_Comma();
  11885.  
  11886.       ALLOW(STRENGTH_TOKEN)
  11887.  
  11888.       isoblob_component->elem.str = Parse_Float();
  11889.  
  11890.       /* Calculate cylinder's coordinate system. */
  11891.  
  11892.       VSub(Axis, Apex, Base);
  11893.  
  11894.       VLength(isoblob_component->elem.len, Axis);
  11895.  
  11896.       if (isoblob_component->elem.len < EPSILON)
  11897.       {
  11898.         Error("Degenerate cylindrical component in isoblob.\n");
  11899.       }
  11900.  
  11901.       VInverseScaleEq(Axis, isoblob_component->elem.len);
  11902.  
  11903.       Compute_Coordinate_Transform(isoblob_component->elem.Trans, Base, Axis, 1.0, 1.0);
  11904.  
  11905.       ALLOW(FUNCTION_TOKEN)
  11906.       myfunc=(int)Parse_Float();
  11907.  
  11908.       if(myfunc<1 || myfunc>nfuncs) {Error("Function #%d is not defined for this isoblob.",nfuncs);}
  11909.  
  11910.       for(i=1,thisfunc=isoblob_funcs;(thisfunc!=NULL && i<myfunc);thisfunc=thisfunc->next,++i);
  11911.       isoblob_component->elem.Func=thisfunc->func;
  11912.  
  11913.       Parse_Isoblob_Element_Mods(&isoblob_component->elem);
  11914.  
  11915.       /* Next component. */
  11916.  
  11917.       isoblob_component->next = isoblob_components;
  11918.  
  11919.       isoblob_components = isoblob_component;
  11920.  
  11921.       npoints++;
  11922.     END_CASE
  11923.  
  11924.     OTHERWISE
  11925.       UNGET
  11926.       EXIT
  11927.     END_CASE
  11928.   END_EXPECT
  11929.  
  11930.   Create_Isoblob_Element_Texture_List(Object, isoblob_components, npoints);
  11931.  
  11932.   Parse_Object_Mods((OBJECT *)Object);
  11933.  
  11934.   /* The blob's texture has to be processed before Make_Isoblob() is called. */
  11935.  
  11936.   Post_Textures(Object->Texture);
  11937.   
  11938.   /* Finally, process the information */
  11939.  
  11940.   Make_Isoblob(Object, threshold, accuracy, max_trace, normal_type, isoblob_funcs, isoblob_components, npoints);
  11941.  
  11942.   return((OBJECT *)Object);
  11943. }
  11944.  
  11945. /* End Lummox JR's isoblob additions */
  11946.  
  11947. #endif
  11948.  
  11949. #ifdef MotionBlurPatch
  11950.  
  11951. static OBJECT *Parse_Motion_Blur ()
  11952. {
  11953.   MOTION_BLUR *Object;
  11954.   OBJECT *Local;
  11955.   DBL saveClock,clockDelta;
  11956.   int i;
  11957.  
  11958.   saveFilePos();
  11959.  
  11960.  
  11961.   Object = Create_Motion_Blur ();
  11962.  
  11963.   Object->Children = NULL;
  11964.  
  11965.   saveClock = opts.FrameSeq.Clock_Value;
  11966.   if (opts.motionBlurCount>1)
  11967.   {
  11968.     opts.FrameSeq.Clock_Value -= opts.blurClockDelta/2.0;
  11969.     clockDelta = (opts.blurClockDelta)/(opts.motionBlurCount-1);
  11970.   }
  11971.   else
  11972.     clockDelta = 0;
  11973.  
  11974.   beginCS_Index = CS_Index;
  11975.   for(i=1; i<=opts.motionBlurCount; i++)
  11976.   {
  11977.     restoreFilePos();
  11978.     Parse_Begin ();
  11979.     Local = Parse_Object ();
  11980.  
  11981.     if(Local)
  11982.     {
  11983.       Object->Type |= (Local->Type & CHILDREN_FLAGS);
  11984.  
  11985.       /* NK Apr 2000 - allow light sources inside motion blur
  11986.       if ((Local->Type & LIGHT_SOURCE_OBJECT))
  11987.       {
  11988.         Error("Light source not allowed in motion_blur\n");
  11989.       }
  11990.       */
  11991.  
  11992.       if ((Local->Type & MOTION_BLUR_OBJECT))
  11993.       {
  11994.         Error("motion_blur objects cannot be nested\n");
  11995.       }
  11996.       Local->Type |= IS_CHILD_OBJECT;
  11997.       Local->TimeStamp = i;
  11998.       Link(Local, &Local->Sibling, &Object->Children);
  11999.  
  12000.       /* now parse the mods for motion_blur */
  12001.       Parse_Object_Mods(Local);
  12002.     }
  12003.  
  12004.     opts.FrameSeq.Clock_Value += clockDelta;
  12005.  
  12006.     if (CS_Index != beginCS_Index)
  12007.     {
  12008.       Error("close brace for motion_blur cannot be enclosed in an #if, #case, or #while block.\n");
  12009.     }
  12010.   }
  12011.  
  12012.   if (!Object->Children)
  12013.     Error("No object inside motion_blur.");
  12014.  
  12015.   Object->Type |= MOTION_BLUR_OBJECT;
  12016.  
  12017.   opts.FrameSeq.Clock_Value = saveClock;
  12018.  
  12019.   Compute_Motion_Blur_BBox((OBJECT *)Object);
  12020.  
  12021.   return ((OBJECT *) Object);
  12022. }
  12023.  
  12024. static void Parse_MBlur_Transform (TRANSFORM *New)
  12025. {
  12026.    MATRIX Local_Matrix;
  12027.    TRANSFORM Local_Trans;
  12028.    VECTOR Local_Vector;
  12029.  
  12030.    MIdentity(New->inverse);
  12031.    MIdentity(New->matrix);
  12032.  
  12033.    EXPECT
  12034.      CASE(TRANSFORM_ID_TOKEN)
  12035.        Compose_Transforms (New, (TRANSFORM *)Token.Data);
  12036.      END_CASE
  12037.  
  12038.      CASE (TRANSFORM_TOKEN)
  12039.  #ifndef TransformPatch /* Chris Huff april 2000 */
  12040.        GET(TRANSFORM_ID_TOKEN)
  12041.        Compose_Transforms(New, (TRANSFORM *)Token.Data);
  12042. #else
  12043.        {
  12044.            TRANSFORM * Trans = Parse_Transform();
  12045.            Compose_Transforms(New, Trans);
  12046.             /*YS sept 17 2000 Memory leak*/
  12047.             POV_FREE(Trans);
  12048.         }
  12049. #endif
  12050.      END_CASE
  12051.  
  12052.      CASE (TRANSLATE_TOKEN)
  12053.        Parse_Vector (Local_Vector);
  12054.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  12055.        Compose_Transforms (New, &Local_Trans);
  12056.      END_CASE
  12057.  
  12058.      CASE (ROTATE_TOKEN)
  12059.        Parse_Vector (Local_Vector);
  12060.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  12061.        Compose_Transforms (New, &Local_Trans);
  12062.      END_CASE
  12063.  
  12064.      CASE (SCALE_TOKEN)
  12065.        Parse_Scale_Vector (Local_Vector);
  12066.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  12067.        Compose_Transforms (New, &Local_Trans);
  12068.      END_CASE
  12069.  
  12070.      CASE (MATRIX_TOKEN)
  12071.        Parse_Matrix(Local_Matrix);
  12072.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  12073.        Compose_Transforms (New, &Local_Trans);
  12074.      END_CASE
  12075.  
  12076.      OTHERWISE
  12077.        UNGET
  12078.        EXIT
  12079.      END_CASE
  12080.    END_EXPECT
  12081.  
  12082.   }
  12083.  
  12084. #if(0)
  12085. static OBJECT *Parse_Motion_Blur2 ()
  12086. {
  12087.   MOTION_BLUR2 *Object;
  12088.   OBJECT *Local;
  12089.   DBL saveClock;
  12090.  
  12091.   Object = Create_Motion_Blur2 ();
  12092.  
  12093.   Object->Children = NULL;
  12094.  
  12095.   Parse_Begin ();
  12096.   Local = Parse_Object ();
  12097.  
  12098.   if(!Local)
  12099.     Error("Missing object within motion_blur\n");
  12100.  
  12101.   Object->Type |= (Local->Type & CHILDREN_FLAGS);
  12102.  
  12103.   if ((Local->Type & LIGHT_SOURCE_OBJECT))
  12104.   {
  12105.     Error("Light source not allowed in motion_blur2\n");
  12106.   }
  12107.   if ((Local->Type & MOTION_BLUR_OBJECT))
  12108.   {
  12109.     Error("motion_blur objects cannot be nested\n");
  12110.   }
  12111.   Local->Type |= IS_CHILD_OBJECT;
  12112.   Link(Local, &Local->Sibling, &Object->Children);
  12113.  
  12114.   /* now parse the mods for motion_blur2 */
  12115.   /* only allow transformations */
  12116.   saveClock = opts.FrameSeq.Clock_Value;
  12117.  
  12118.   saveFilePos();
  12119.   beginCS_Index = CS_Index;
  12120.  
  12121.   opts.FrameSeq.Clock_Value = saveClock - opts.blurClockDelta/2.0;
  12122.   Parse_MBlur_Transform (&Object->Trans1);
  12123.   Parse_End();
  12124.  
  12125.   if (CS_Index != beginCS_Index)
  12126.   {
  12127.     Error("close brace for motion_blur2 cannot be enclosed in an #if, #case, or #while block.\n");
  12128.   }
  12129.   restoreFilePos();
  12130.  
  12131.   opts.FrameSeq.Clock_Value = saveClock + opts.blurClockDelta/2.0;
  12132.   Parse_MBlur_Transform (&Object->Trans2);
  12133.   Parse_End();
  12134.  
  12135.   Object->Type |= MOTION_BLUR_OBJECT;
  12136.  
  12137.   opts.FrameSeq.Clock_Value = saveClock;
  12138.  
  12139.   Compute_Motion_Blur2_BBox((OBJECT *)Object);
  12140.  
  12141.   return ((OBJECT *) Object);
  12142. }
  12143. #endif
  12144.  
  12145. #endif
  12146.