home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: Graphics
/
Graphics.zip
/
povsrc31.zip
/
parse.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-01-31
|
297KB
|
12,146 lines
/****************************************************************************
* parse.c
*
* ------------------------------------------------------------------------
* ATTENTION:
* This is an unofficial version of parse.c modified by
* Ryoichi Suzuki, rsuzuki@etl.go.jp for "isosurface".
*
* WARNING: This is a changed copy of the original file.
* Support of sphere sweep primitive added by Jochen Lippert.
*
* ------------------------------------------------------------------------
* This module implements a parser for the scene description files.
*
* from Persistence of Vision(tm) Ray Tracer
* Copyright 1996,1999 Persistence of Vision Team
*---------------------------------------------------------------------------
* NOTICE: This source code file is provided so that users may experiment
* with enhancements to POV-Ray and to port the software to platforms other
* than those supported by the POV-Ray Team. There are strict rules under
* which you are permitted to use this file. The rules are in the file
* named POVLEGAL.DOC which should be distributed with this file.
* If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
* Team Coordinator by email to team-coord@povray.org or visit us on the web at
* http://www.povray.org. The latest version of POV-Ray may be found at this site.
*
* This program is based on the popular DKB raytracer version 2.12.
* DKBTrace was originally written by David K. Buck.
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
*
* Modifications by Thomas Willhalm, March 1999, used with permission.
*
* Further modifications by Lummox JR to include isoblob support
*
*****************************************************************************/
#include "frame.h"
#include "vector.h"
#include "povproto.h"
#include "parse.h"
#include "parstxtr.h"
#include "atmosph.h"
#include "bezier.h"
#ifdef RBezierPatch
#include "rbezier.h"
#endif
#include "blob.h"
#include "boxes.h"
#include "bsphere.h"
#include "colour.h"
#include "cones.h"
#include "csg.h"
#include "discs.h"
#ifdef SplinePatch
#include "splines.h"
#endif
#include "express.h"
#include "fractal.h"
#ifndef BurnAllGifs
#include "gif.h"
#endif
#include "hfield.h"
#include "iff.h"
#include "image.h"
#include "interior.h"
#ifdef IsoBlobPatch
#include "isoblob.h"
#endif
#include "lathe.h"
#include "polysolv.h"
#include "matrices.h"
#include "mesh.h"
#include "normal.h"
#include "objects.h"
#include "octree.h"
#include "pigment.h"
#include "planes.h"
#include "poly.h"
#include "polygon.h"
#include "povray.h"
#include "pgm.h"
#include "ppm.h"
#include "prism.h"
#include "quadrics.h"
#include "radiosit.h"
#include "render.h"
#include "sor.h"
#include "spheres.h"
#include "sphsweep.h" /* Sphere sweep support */
#include "super.h"
#include "targa.h"
#include "texture.h"
#include "tokenize.h"
#include "torus.h"
#include "triangle.h"
#include "truetype.h"
/*YS*/
#include "lightgrp.h"
/*YS*/
#include "uniutils.h"
/* NK phmap */
#include "photons.h"
/* NK ---- */
#include "optin.h"
/** poviso: **/
#ifdef POVISO
#include "isosrf.h" /* July 14 '96 R.S. */
#include "f_expr.h" /* Tue 06-04-1996 0rf */
void Parse_Parm(int PMax, int *pnum);
void Iso_Parse_Box(ISOSURFACE *Object);
void Iso_Parse_Sphere(ISOSURFACE *Object);
#endif
/** --- **/
#ifdef MotionBlurPatch
#include "mblur.h"
/*#include "mblur2.h"*/
#endif
#ifdef PostProcessPatch
#include "postproc.h"
void Parse_Post_Process(void);
#endif
#ifdef GlowPatch
#include "glow.h"
#endif
/* NK phmap */
/*****************************************************************************
* Global Variables
******************************************************************************/
extern int backtraceFlag;
extern PHOTON_OPTIONS photonOptions;
/* NK ---- */
/*****************************************************************************
* Local preprocessor defines
******************************************************************************/
/* Volume that is considered to be infinite. [DB 9/94] */
#define INFINITE_VOLUME BOUND_HUGE
/*****************************************************************************
* Local typedefs
******************************************************************************/
#ifdef BsplinePatch
typedef struct Spline_Stack_1D_Struct SPLINE_STACK_1D;
struct Spline_Stack_1D_Struct
{
DBL t,y;
void *next;
};
typedef struct Spline_Stack_3D_Struct SPLINE_STACK_3D;
struct Spline_Stack_3D_Struct
{
VECTOR Knot;
void *next;
};
#endif
/*****************************************************************************
* Local variables
******************************************************************************/
short Have_Vector;
short Not_In_Default;
short Ok_To_Declare;
short LValue_Ok;
static TOKEN *Brace_Stack;
static int Brace_Index;
static CAMERA *Default_Camera;
/** poviso: July 8, '96 R.S. **/
#ifdef POVISO
DBL iso_p[ISOSURFACE_MAXPARM];
#endif
/** --- **/
#ifdef BsplinePatch
SPLINE *The_Splines;
SPLINE_3D *The_3D_Splines;
#endif
#ifdef MotionBlurPatch
static int parsedMotionBlurObject;
#endif
/*****************************************************************************
* Static functions
******************************************************************************/
#ifdef MotionBlurPatch
static void Parse_MBlur_Transform (TRANSFORM *New);
#endif
#ifndef TransformPatch /* Chris Huff april 2000 */
static TRANSFORM *Parse_Transform (void);
#else
static TRANSFORM *Parse_Transform_Block (void);/*Chris Huff transform patch*/
#endif
static void Frame_Init (void);
static void Parse_Coeffs (int order, DBL *Coeffs);
static OBJECT *Parse_Bicubic_Patch (void);
#ifndef BlobPatternPatch
static OBJECT *Parse_Blob (void);
#endif
static OBJECT *Parse_Bound_Clip (void);
static OBJECT *Parse_Box (void);
static OBJECT *Parse_Cone (void);
static OBJECT *Parse_CSG (int CSG_Type);
static OBJECT *Parse_Cylinder (void);
static OBJECT *Parse_Disc (void);
static OBJECT *Parse_Julia_Fractal (void);
static OBJECT *Parse_HField (void);
static OBJECT *Parse_Lathe (void);
static OBJECT *Parse_Light_Source (void);
static OBJECT *Parse_Object_Id (void);
static OBJECT *Parse_Plane (void);
static OBJECT *Parse_Poly (int order);
static OBJECT *Parse_Polygon (void);
static OBJECT *Parse_Prism (void);
static OBJECT *Parse_Quadric (void);
static OBJECT *Parse_Smooth_Triangle (void);
static OBJECT *Parse_Sor (void);
static OBJECT *Parse_Sphere (void);
static OBJECT *Parse_Superellipsoid (void);
static OBJECT *Parse_Torus (void);
static OBJECT *Parse_Triangle (void);
static OBJECT *Parse_Mesh (void);
/* NK 1998 */
static OBJECT *Parse_Mesh2 (void);
/* NK ---- */
#ifdef ColorTrianglePatch
static TEXTURE *Parse_Mesh_Texture (TEXTURE **t2, TEXTURE **t3);
#else
static TEXTURE *Parse_Mesh_Texture (void);
#endif
static OBJECT *Parse_TrueType (void);
static void Parse_Blob_Element_Mods (BLOB_ELEMENT *Element);
#ifdef MotionBlurPatch
static OBJECT *Parse_Motion_Blur ();
/*static OBJECT *Parse_Motion_Blur2 ();*/
#endif
static void Parse_Camera (CAMERA **Camera_Ptr);
static void Parse_Frame (void);
static void Found_Instead (void);
static void Link (OBJECT *New_Object,OBJECT **Field,OBJECT **Old_Object_List);
static void Link_To_Frame (OBJECT *Object);
static void Post_Process (OBJECT *Object, OBJECT *Parent);
static void Parse_Global_Settings (void);
static void Global_Setting_Warn (void);
#ifdef BsplinePatch
static void Create_Spline_1D (SPLINE_STACK_1D *base,int nr,char *name,int type,DBL p1,DBL p2);
static void Create_Spline_3D (SPLINE_STACK_3D *base,int nr,char *name,int type,VECTOR temp1,VECTOR temp2);
static void Destroy_Splines (void);
static void Jacobi (DBL *a,DBL *b,DBL *c,DBL *rs,DBL *s,int n);
#endif
static void Set_CSG_Children_Flag (OBJECT*, unsigned long, unsigned long, unsigned long);
#ifdef NoImageNoReflectionPatch
/* JG start */
static void Set_CSG_Tree_Flag (OBJECT*, unsigned long);
/* JG end */
#endif
static void *Copy_Identifier (void *Data, int Type);
/* NK layers - 1999 July 10 - for backwards compatiblity with layered textures */
static void Convert_Filter_To_Transmit(PIGMENT *Pigment);
/* NK ---- */
/* NK persist */
static void Parse_Modify_Object(void);
static void Parse_Destroy_Object(void);
/* NK ---- */
#ifdef IsoBlobPatch
/* Lummox JR, July 1999 */
static OBJECT *Parse_Isoblob (void);
static void Parse_Isolob_Element_Mods (ISOBLOB_ELEMENT *Element);
/* end Lummox JR's additions */
#endif
/* NK super */
static OBJECT *Parse_Sphere_Sweep (void); /* Sphere sweep support */
static OBJECT *Parse_Mesh2 (void);
/* NK ---- */
/** poviso: 1/22 '96 R.S. **/
#ifdef POVISO
static OBJECT *Parse_IsoSurface (int parse_type);
extern int Func_Parse_Flag;
#define PARSE_IMPFUN 1
#define PARSE_FUNC_XY 2
FUNCTION *Parse_Function (void);
#endif
#ifdef RBezierPatch
static OBJECT *Parse_RBezier_Patch (void);
static void bicubic_patch_warning(BICUBIC_PATCH *Object,char flag);
static TRIM_SHAPE *Parse_Trim (void);
#endif
/* NK persist */
int findObjectsByLabel(OBJECT **objHandle, OBJECT* parent, char **objectNames, int nameCount,
int (*function)(OBJECT **objHandle, OBJECT* parent, void *handle), void *handle,
int (*functionParent)(OBJECT **objHandle, OBJECT* parent, void *handle), void *handle2 );
int modifyObjectCallback(OBJECT **objHandle, OBJECT* parent, void *handle);
int modifyObjectParentCallback(OBJECT **objHandle, OBJECT *parent, void *handle);
int destroyObjectCallback(OBJECT **objHandle, OBJECT* parent, void *handle);
int destroyObjectParentCallback(OBJECT **objHandle, OBJECT *parent, void *handle);
/* NK ---- */
int Parse_Three_UVCoords(UV_VECT UV1, UV_VECT UV2, UV_VECT UV3);
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
/* Parse the file. */
void Parse ()
{
#ifdef BsplinePatch
The_Splines = NULL;
The_3D_Splines = NULL;
#endif
Initialize_Tokenizer();
Brace_Stack = (TOKEN *)POV_MALLOC(MAX_BRACES*sizeof (TOKEN), "brace stack");
Brace_Index = 0;
Default_Camera = Create_Camera();
Default_Texture = Create_Texture();
Default_Texture->Pigment = Create_Pigment();
Default_Texture->Tnormal = NULL;
Default_Texture->Finish = Create_Finish();
Not_In_Default = TRUE;
Ok_To_Declare = TRUE;
LValue_Ok = FALSE;
#ifdef MotionBlurPatch
parsedMotionBlurObject = FALSE;
#endif
Frame_Init ();
Stage = STAGE_PARSING;
Parse_Frame ();
Post_Media(Frame.Atmosphere);
#ifdef GlowPatch
if (Frame.Objects == NULL && Frame.NumOfGlows == 0)
{
Error ("No objects or glows in scene.");
}
#else
if (Frame.Objects == NULL)
{
Error ("No objects in scene.");
}
#endif
Stage = STAGE_CLEANUP_PARSE;
Terminate_Tokenizer(FALSE);
Destroy_Textures(Default_Texture);
Destroy_Camera(Default_Camera);
POV_FREE (Brace_Stack);
Default_Texture = NULL;
Default_Camera = NULL;
Brace_Stack = NULL;
#ifdef BsplinePatch
Destroy_Splines();
#endif
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
/* Set up the fields in the frame to default values. */
static void Frame_Init (void)
{
Frame.Camera = Copy_Camera(Default_Camera);
Frame.Number_Of_Light_Sources = 0;
Frame.Light_Sources = NULL;
#ifdef GlowPatch
Frame.Glows = NULL;
Frame.NumOfGlows = 0;
#endif
/* NK persist - commented this out - do this in main/alt_main instead */
/*Frame.Objects = NULL;*/
Frame.Atmosphere_IOR = 1.0;
Frame.Atmosphere_Dispersion = 1.0;
Frame.Antialias_Threshold = opts.Antialias_Threshold;
/* dmf -- the first is physically "more correct". The second works better */
/* Make_Colour (Frame.Irid_Wavelengths, 0.70, 0.52, 0.48); */
Make_Colour (Frame.Irid_Wavelengths, 0.25, 0.18, 0.14);
Make_Colour (Frame.Background_Colour, 0.0, 0.0, 0.0);
Make_Colour (Frame.Ambient_Light, 1.0, 1.0, 1.0);
/* Init atmospheric stuff. [DB 12/94] */
Frame.Atmosphere = NULL;
Frame.Fog = NULL;
Frame.Rainbow = NULL;
Frame.Skysphere = NULL;
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Parse_Begin ()
{
char *front;
if (++Brace_Index >= MAX_BRACES)
{
Warn(0,"Too many nested '{' braces.\n");
Brace_Index--;
}
Brace_Stack[Brace_Index]=Token.Token_Id;
Get_Token ();
if (Token.Token_Id == LEFT_CURLY_TOKEN)
{
return;
}
front = Get_Token_String (Brace_Stack[Brace_Index]);
Where_Error ();
Error_Line ("Missing { after %s, ", front);
Found_Instead ();
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Parse_End ()
{
char *front;
Get_Token ();
if (Token.Token_Id == RIGHT_CURLY_TOKEN)
{
if(--Brace_Index < 0)
{
Warn(0,"Possible '}' brace missmatch.");
Brace_Index = 0;
}
return;
}
front = Get_Token_String (Brace_Stack[Brace_Index]);
Where_Error ();
Error_Line("No matching } in %s,", front);
Found_Instead ();
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static OBJECT *Parse_Object_Id ()
{
OBJECT *Object;
EXPECT
CASE (OBJECT_ID_TOKEN)
Warn_State(OBJECT_ID_TOKEN, OBJECT_TOKEN);
Object = Copy_Object((OBJECT *) Token.Data);
Parse_Object_Mods (Object);
EXIT
END_CASE
OTHERWISE
Object = NULL;
UNGET
EXIT
END_CASE
END_EXPECT
return (Object);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Parse_Comma (void)
{
Get_Token();
if (Token.Token_Id != COMMA_TOKEN)
{
UNGET;
}
}
void Parse_Semi_Colon (void)
{
Get_Token();
if (Token.Token_Id != SEMI_COLON_TOKEN)
{
UNGET;
if (opts.Language_Version >= 310)
{
Warn(0,"All #version and #declares of float, vector, and color require semi-colon ';' at end.\n");
}
}
}
/** poviso: Mar '96 R.S. **/
#ifdef POVISO
/*****************************************************************************
*
* FUNCTION Parse_Parm
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR R.Suzuki
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
/*--------- R.Suzuki Mar '96-----------*/
void Parse_Parm(int PMax, int *pnum)
{
int i;
if (PMax==0) PMax = ISOSURFACE_MAXPARM;
EXPECT
CASE (LEFT_ANGLE_TOKEN)
iso_p[0] = Parse_Float();
for (i = 1; i < PMax; i++)
{
Get_Token();
if (Token.Token_Id == COMMA_TOKEN) iso_p[i] = Parse_Float();
else {Unget_Token(); break;}
}
GET (RIGHT_ANGLE_TOKEN);
EXIT
END_CASE
OTHERWISE
Parse_Error (LEFT_ANGLE_TOKEN);
END_CASE
END_EXPECT
*pnum=i;
}
#endif
/** --- **/
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static void Parse_Coeffs(int order, DBL *Coeffs)
{
int i;
EXPECT
CASE (LEFT_ANGLE_TOKEN)
Coeffs[0] = Parse_Float();
for (i = 1; i < term_counts(order); i++)
{
Parse_Comma();
Coeffs[i] = Parse_Float();
}
GET (RIGHT_ANGLE_TOKEN);
EXIT
END_CASE
OTHERWISE
Parse_Error (LEFT_ANGLE_TOKEN);
END_CASE
END_EXPECT
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static OBJECT *Parse_Bound_Clip (void)
{
VECTOR Local_Vector;
MATRIX Local_Matrix;
TRANSFORM Local_Trans;
OBJECT *First, *Current, *Prev;
First = Prev = NULL;
while ((Current = Parse_Object ()) != NULL)
{
if (Current->Type & (TEXTURED_OBJECT+PATCH_OBJECT))
Error ("Illegal texture or patch in clip or bound.");
if (First == NULL)
First = Current;
if (Prev != NULL)
Prev->Sibling = Current;
Prev = Current;
}
EXPECT
CASE (TRANSLATE_TOKEN)
Parse_Vector (Local_Vector);
Compute_Translation_Transform(&Local_Trans, Local_Vector);
for (Current = First; Current != NULL; Current = Current->Sibling)
{
Translate_Object (Current, Local_Vector, &Local_Trans);
}
END_CASE
CASE (ROTATE_TOKEN)
Parse_Vector (Local_Vector);
Compute_Rotation_Transform(&Local_Trans, Local_Vector);
for (Current = First; Current != NULL; Current = Current->Sibling)
{
Rotate_Object (Current, Local_Vector, &Local_Trans);
}
END_CASE
CASE (SCALE_TOKEN)
Parse_Scale_Vector (Local_Vector);
Compute_Scaling_Transform(&Local_Trans, Local_Vector);
for (Current = First; Current != NULL; Current = Current->Sibling)
{
Scale_Object (Current, Local_Vector, &Local_Trans);
}
END_CASE
CASE (TRANSFORM_TOKEN)
#ifndef TransformPatch /* Chris Huff april 2000 */
GET(TRANSFORM_ID_TOKEN)
for (Current = First; Current != NULL; Current = Current->Sibling)
{
Transform_Object (Current, (TRANSFORM *)Token.Data);
}
#else
{
TRANSFORM * Trans = Parse_Transform();
for (Current = First; Current != NULL; Current = Current->Sibling)
{
Transform_Object (Current, Trans);
}
/*YS sept 17 2000 Memory leak*/
POV_FREE(Trans);
}
#endif
END_CASE
CASE (MATRIX_TOKEN)
Parse_Matrix (Local_Matrix);
Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
for (Current = First; Current != NULL; Current = Current->Sibling)
{
Transform_Object (Current, &Local_Trans);
}
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
if (First==NULL)
{
Parse_Error_Str("object");
}
return (First);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Parse_Object_Mods (OBJECT *Object)
{
DBL Temp_Water_Level;
DBL V1, V2;
VECTOR Min, Max;
VECTOR Local_Vector;
MATRIX Local_Matrix;
TRANSFORM Local_Trans;
BBOX BBox;
OBJECT *Sib;
TEXTURE *Local_Texture;
#ifdef InteriorTexturePatch
TEXTURE *Local_Int_Texture;
#endif
MATERIAL Local_Material;
OBJECT *Temp1_Object;
OBJECT *Temp2_Object;
COLOUR Local_Colour;
int Tmp_Flag;
EXPECT
#if(0) /*GlowPatch in objects not implemented yet */
CASE(GLOW_TOKEN)
{
if ( Ok_To_Declare ==false)
Error("You can not use glow in a declared object (yet)\n");
GLOW * NewGlow = Create_Glow();
Parse_Glow(NewGlow);
Add_Glow(NewGlow);/*Add glow to Frame*/
/*Add glow to list of glow pointers in object*/
if(Object->glowList == NULL)
Object->glowList = (GLOW**)POV_MALLOC(sizeof(GLOW_PTR), "glow pointer array");
else
{
GLOW_PTR * newGlowList = (GLOW**)POV_MALLOC((Object->numOfGlows+2)*sizeof(GLOW_PTR), "glow pointer array");
memcpy(newGlowList, Object->glowList, (Object->numOfGlows+1)*sizeof(GLOW_PTR));
POV_FREE(Object->glowList);
Object->glowList = newGlowList;
}
Object->glowList[Object->numOfGlows] = NewGlow;
Object->numOfGlows++;
}
END_CASE
#endif
/* NK persist label */
CASE (LABEL_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Get_Token();
/* any valid token is OK as a label */
if (Object->Label!=NULL)
POV_FREE(Object->Label);
Object->Label = POV_STRDUP(Token.Token_String);
/* now with a label, we can't split unions */
if (Object->Methods == &CSG_Union_Methods)
{
((CSG*)Object)->do_split = FALSE;
}
END_CASE
/* NK ---- */
/* NK phmap */
CASE(SPLIT_UNION_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
if (Object->Methods != &CSG_Union_Methods)
{
Error("split_union found in non-union object.\n");
}
((CSG*)Object)->do_split = (int)Parse_Float();
END_CASE
/* NK --- */
/* NK 1998 */
CASE(UV_MAPPING_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
/* if no texture than allow uv_mapping
otherwise, warn user */
if (Object->Texture == NULL)
{
Set_Flag(Object, UV_FLAG);
}
else
{
Error ("uv_mapping must be specified before texture.");
}
END_CASE
/* NK ---- */
/* NK phmap */
CASE(PHOTONS_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Parse_Begin();
EXPECT
CASE(TARGET_TOKEN)
Object->Ph_Density = Allow_Float(1.0);
if (Object->Ph_Density > 0)
{
Object->Ph_Flags |= PH_FLAG_TARGET;
CheckPassThru(Object, PH_FLAG_TARGET);
}
else
{
Object->Ph_Flags &= ~PH_FLAG_TARGET;
}
END_CASE
CASE(REFRACTION_TOKEN)
if((int)Parse_Float())
{
SET_PH_FLAG(Object, PH_FLAG_RFR_ON, PH_FLAG_RFR_OFF);
CheckPassThru(Object, PH_FLAG_RFR_ON);
}
else
{ CLEAR_PH_FLAG(Object, PH_FLAG_RFR_ON, PH_FLAG_RFR_OFF); }
END_CASE
CASE(REFLECTION_TOKEN)
if((int)Parse_Float())
{ SET_PH_FLAG(Object, PH_FLAG_RFL_ON, PH_FLAG_RFL_OFF); }
else
{ CLEAR_PH_FLAG(Object, PH_FLAG_RFL_ON, PH_FLAG_RFL_OFF); }
END_CASE
CASE(PASS_THROUGH_TOKEN)
if((int)Allow_Float(1.0))
{
Object->Ph_Flags |= PH_FLAG_PASSTHRU;
CheckPassThru(Object, PH_FLAG_PASSTHRU);
}
else
{
Object->Ph_Flags &= ~PH_FLAG_PASSTHRU;
}
END_CASE
CASE(IGNORE_PHOTONS_TOKEN)
Object->Ph_Flags |= PH_FLAG_IGNORE_PHOTONS;
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End();
END_CASE
/* NK ---- */
#ifdef MultiTextureCsgPatch
CASE(CUTAWAY_TEXTURES_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(50);
#endif
if (Object->Methods != &CSG_Intersection_Methods)
{
Error("cutaway_textures can only be used with intersection and difference.\n");
}
Set_Flag(Object, MULTITEXTURE_FLAG);
END_CASE
#endif
CASE_COLOUR
Parse_Colour (Local_Colour);
if (opts.Language_Version < 150)
if (Object->Texture != NULL)
if (Object->Texture->Type == PLAIN_PATTERN)
if (opts.Quality_Flags & Q_QUICKC)
{
Assign_Colour(Object->Texture->Pigment->Colour,Local_Colour);
break; /* acts like END_CASE */
}
Warn(0, "Quick color belongs in texture. Color ignored.");
END_CASE
CASE (TRANSLATE_TOKEN)
Parse_Vector (Local_Vector);
Compute_Translation_Transform(&Local_Trans, Local_Vector);
Translate_Object (Object, Local_Vector, &Local_Trans);
END_CASE
CASE (ROTATE_TOKEN)
Parse_Vector (Local_Vector);
Compute_Rotation_Transform(&Local_Trans, Local_Vector);
Rotate_Object (Object, Local_Vector, &Local_Trans);
END_CASE
CASE (SCALE_TOKEN)
Parse_Scale_Vector (Local_Vector);
Compute_Scaling_Transform(&Local_Trans, Local_Vector);
Scale_Object (Object, Local_Vector, &Local_Trans);
END_CASE
CASE (TRANSFORM_TOKEN)
#ifndef TransformPatch /* Chris Huff april 2000 */
GET(TRANSFORM_ID_TOKEN)
Transform_Object (Object, (TRANSFORM *)Token.Data);
#else
{
TRANSFORM * Trans = Parse_Transform();
Transform_Object(Object, Trans);
/*YS sept 17 2000 Memory leak*/
POV_FREE(Trans);
}
#endif
END_CASE
CASE (MATRIX_TOKEN)
Parse_Matrix (Local_Matrix);
Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
Transform_Object (Object, &Local_Trans);
END_CASE
CASE (BOUNDED_BY_TOKEN)
Parse_Begin ();
if (Object->Bound != NULL)
if (Object->Clip == Object->Bound)
Error ("Cannot add bounds after linking bounds and clips.");
EXPECT
CASE (CLIPPED_BY_TOKEN)
if (Object->Bound != NULL)
Error ("Cannot link clips with previous bounds.");
Object->Bound = Object->Clip;
EXIT
END_CASE
OTHERWISE
UNGET
Temp1_Object = Temp2_Object = Parse_Bound_Clip ();
while (Temp2_Object->Sibling != NULL)
Temp2_Object = Temp2_Object->Sibling;
Temp2_Object->Sibling = Object->Bound;
Object->Bound = Temp1_Object;
EXIT
END_CASE
END_EXPECT
Parse_End ();
END_CASE
CASE (CLIPPED_BY_TOKEN)
Parse_Begin ();
if (Object->Clip != NULL)
if (Object->Clip == Object->Bound)
Error ("Cannot add clips after linking bounds and clips.");
EXPECT
CASE (BOUNDED_BY_TOKEN)
if (Object->Clip != NULL)
Error ("Cannot link bounds with previous clips.");
Object->Clip = Object->Bound;
EXIT
END_CASE
OTHERWISE
UNGET
Temp1_Object = Temp2_Object = Parse_Bound_Clip ();
while (Temp2_Object->Sibling != NULL)
Temp2_Object = Temp2_Object->Sibling;
Temp2_Object->Sibling = Object->Clip;
Object->Clip = Temp1_Object;
/* Compute quadric bounding box before transformations. [DB 8/94] */
if (Object->Methods == &Quadric_Methods)
{
Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
Make_Vector(Max, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
Compute_Quadric_BBox((QUADRIC *)Object, Min, Max);
}
EXIT
END_CASE
END_EXPECT
Parse_End ();
END_CASE
CASE (TEXTURE_TOKEN)
Object->Type |= TEXTURED_OBJECT;
Parse_Begin ();
Local_Texture = Parse_Texture ();
Parse_End ();
Link_Textures(&(Object->Texture), Local_Texture);
END_CASE
#ifdef InteriorTexturePatch
CASE (INTERIOR_TEXTURE_TOKEN)/*Chris Huff: Interior Texture patch*/
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Object->Type |= TEXTURED_OBJECT;
Parse_Begin ();
Local_Int_Texture = Parse_Texture ();
Parse_End ();
Link_Textures(&(Object->Interior_Texture), Local_Int_Texture);
END_CASE
#endif
CASE (INTERIOR_TOKEN)
Parse_Interior((INTERIOR **)(&Object->Interior));
END_CASE
CASE (MATERIAL_TOKEN)
Local_Material.Texture = Object->Texture;
#ifdef InteriorTexturePatch
Local_Material.Interior_Texture = Object->Interior_Texture;/*Chris Huff: Interior Texture patch*/
#endif
Local_Material.Interior = Object->Interior;
Parse_Material(&Local_Material);
Object->Texture = Local_Material.Texture;
#ifdef InteriorTexturePatch
Object->Interior_Texture = Local_Material.Interior_Texture;/*Chris Huff: Interior Texture patch*/
#endif
Object->Interior = Local_Material.Interior;
END_CASE
CASE3 (PIGMENT_TOKEN, TNORMAL_TOKEN, FINISH_TOKEN)
Object->Type |= TEXTURED_OBJECT;
if (Object->Texture == NULL)
Object->Texture = Copy_Textures(Default_Texture);
else
if (Object->Texture->Type != PLAIN_PATTERN)
Link_Textures(&(Object->Texture), Copy_Textures(Default_Texture));
UNGET
EXPECT
CASE (PIGMENT_TOKEN)
Parse_Begin ();
Parse_Pigment ( &(Object->Texture->Pigment) );
Parse_End ();
END_CASE
CASE (TNORMAL_TOKEN)
Parse_Begin ();
Parse_Tnormal ( &(Object->Texture->Tnormal) );
Parse_End ();
END_CASE
CASE (FINISH_TOKEN)
Parse_Finish ( &(Object->Texture->Finish) );
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
END_CASE
CASE (INVERSE_TOKEN)
if (Object->Type & PATCH_OBJECT)
Warn (0, "Cannot invert a patch object.");
Invert_Object (Object);
END_CASE
CASE (STURM_TOKEN)
if (!(Object->Type & STURM_OK_OBJECT))
Not_With ("sturm","this object");
Bool_Flag (Object, STURM_FLAG, (Allow_Float(1.0) > 0.0));
END_CASE
CASE (WATER_LEVEL_TOKEN)
if (!(Object->Type & WATER_LEVEL_OK_OBJECT))
Not_With ("water_level","this object");
Temp_Water_Level = Parse_Float();
if (opts.Language_Version < 200)
Temp_Water_Level /=256.0;
((HFIELD *) Object)->bounding_box->bounds[0][Y] = 65536.0 * Temp_Water_Level;
END_CASE
CASE (SMOOTH_TOKEN)
if (!(Object->Type & SMOOTH_OK_OBJECT))
Not_With ("smooth","this object");
/* Modification by Lummox JR, June 1999 */
/*Set_Flag(Object, SMOOTHED_FLAG);*/
((HFIELD *)Object)->smooth_type = (int)Allow_Float(1.0);
if(((HFIELD *)Object)->smooth_type!=0) Set_Flag(Object, SMOOTHED_FLAG);
/* NK 1998 double_illuminate */
/*Object->Type |= DOUBLE_ILLUMINATE;*/
/*Set_Flag(Object, DOUBLE_ILLUMINATE_FLAG);*/
/* NK ---- */
END_CASE
CASE (NO_SHADOW_TOKEN)
/* NK phmap 2000-may-10 */
Object->Ph_Flags |= PH_FLAG_PASSTHRU;
/* NK ---- */
Set_Flag(Object, NO_SHADOW_FLAG);
Object->No_Shadow_Group = ALL_GROUP;
EXPECT
CASE (STRING_LITERAL_TOKEN)
UNGET
{
/*YS sept 17 2000 Memory Leak*/
char *tempstring=Parse_String();
Object->No_Shadow_Group = Get_Light_Group(tempstring,&Tmp_Flag);
POV_FREE(tempstring);
/*YS*/
}
if (Tmp_Flag) Set_Flag(Object,INVERT_NO_SHADOW_GROUP);
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
END_CASE
#ifdef NoImageNoReflectionPatch
/* Object-Ray Options
Do not intersect with camera rays [ENB 9/97] */
CASE (NO_IMAGE_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Set_Flag(Object, NO_IMAGE_FLAG);
if ((Object->Methods == &CSG_Intersection_Methods) ||
(Object->Methods == &CSG_Merge_Methods) ||
(Object->Methods == &CSG_Union_Methods))
{
Set_CSG_Tree_Flag(Object, NO_IMAGE_FLAG);
}
END_CASE
/* Object-Ray Options
Do not intersect with reflection rays [ENB 9/97] */
CASE (NO_REFLECTION_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Set_Flag(Object, NO_REFLECTION_FLAG);
if ((Object->Methods == &CSG_Intersection_Methods) ||
(Object->Methods == &CSG_Merge_Methods) ||
(Object->Methods == &CSG_Union_Methods))
{
Set_CSG_Tree_Flag(Object, NO_REFLECTION_FLAG);
}
END_CASE
#endif
CASE (LIGHT_SOURCE_TOKEN)
Error("Light source must be defined using new syntax.");
END_CASE
CASE (LIGHT_GROUP_TOKEN)
{
/*YS sept 17 2000 Memory leak */
char *tempstring=Parse_String();
Object->Light_Group = Get_Light_Group(tempstring,&Tmp_Flag);
POV_FREE(tempstring); /*YS sept 17 Memory leak */
}
if (Object->Light_Group == NONE_GROUP)
Warn(300,"Light_Group of none is a special case, changed to All.\n");
if (Tmp_Flag) Set_Flag(Object,INVERT_LIGHT_GROUP);
END_CASE
CASE(HIERARCHY_TOKEN)
if (!(Object->Type & HIERARCHY_OK_OBJECT))
Not_With ("hierarchy", "this object");
Bool_Flag (Object, HIERARCHY_FLAG, (Allow_Float(1.0) > 0.0));
END_CASE
CASE(HOLLOW_TOKEN)
Bool_Flag (Object, HOLLOW_FLAG, (Allow_Float(1.0) > 0.0));
Set_Flag (Object, HOLLOW_SET_FLAG);
if ((Object->Methods == &CSG_Intersection_Methods) ||
(Object->Methods == &CSG_Merge_Methods) ||
(Object->Methods == &CSG_Union_Methods))
{
Set_CSG_Children_Flag(Object, Test_Flag(Object, HOLLOW_FLAG), HOLLOW_FLAG, HOLLOW_SET_FLAG);
}
END_CASE
/* NK 1998 double_illuminate */
CASE(DOUBLE_ILLUMINATE_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Set_Flag(Object, DOUBLE_ILLUMINATE_FLAG);
END_CASE
/* NK ---- */
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
/*
* Assign bounding objects' bounding box to object
* if object's bounding box is larger. [DB 9/94]
*/
if (Object->Bound != NULL)
{
/* Get bounding objects bounding box. */
Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
Make_Vector(Max, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
for (Sib = Object->Bound; Sib != NULL; Sib = Sib->Sibling)
{
if (!Test_Flag(Sib, INVERTED_FLAG))
{
Min[X] = max(Min[X], Sib->BBox.Lower_Left[X]);
Min[Y] = max(Min[Y], Sib->BBox.Lower_Left[Y]);
Min[Z] = max(Min[Z], Sib->BBox.Lower_Left[Z]);
Max[X] = min(Max[X], Sib->BBox.Lower_Left[X] + Sib->BBox.Lengths[X]);
Max[Y] = min(Max[Y], Sib->BBox.Lower_Left[Y] + Sib->BBox.Lengths[Y]);
Max[Z] = min(Max[Z], Sib->BBox.Lower_Left[Z] + Sib->BBox.Lengths[Z]);
}
}
Make_BBox_from_min_max(BBox, Min, Max);
/* Get bounding boxes' volumes. */
BOUNDS_VOLUME(V1, BBox);
BOUNDS_VOLUME(V2, Object->BBox);
if (V1 < V2)
{
Object->BBox = BBox;
}
}
/*
* Assign clipping objects' bounding box to object
* if object's bounding box is larger. [DB 9/94]
*/
if (Object->Clip != NULL)
{
/* Get clipping objects bounding box. */
Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
Make_Vector(Max, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
for (Sib = Object->Clip; Sib != NULL; Sib = Sib->Sibling)
{
if (!Test_Flag(Sib, INVERTED_FLAG))
{
Min[X] = max(Min[X], Sib->BBox.Lower_Left[X]);
Min[Y] = max(Min[Y], Sib->BBox.Lower_Left[Y]);
Min[Z] = max(Min[Z], Sib->BBox.Lower_Left[Z]);
Max[X] = min(Max[X], Sib->BBox.Lower_Left[X] + Sib->BBox.Lengths[X]);
Max[Y] = min(Max[Y], Sib->BBox.Lower_Left[Y] + Sib->BBox.Lengths[Y]);
Max[Z] = min(Max[Z], Sib->BBox.Lower_Left[Z] + Sib->BBox.Lengths[Z]);
}
}
Make_BBox_from_min_max(BBox, Min, Max);
/* Get bounding boxes' volumes. */
BOUNDS_VOLUME(V1, BBox);
BOUNDS_VOLUME(V2, Object->BBox);
if (V1 < V2)
{
Object->BBox = BBox;
}
}
#ifdef InteriorTexturePatch
if((Object->Texture ==NULL)&&(Object->Interior_Texture != NULL))
Error("Interior texture given but no exterior texture. You must add an exterior texture for interior_texture to be used.");
#endif
Parse_End ();
}
#ifdef NoImageNoReflectionPatch
/* JG start */
static void Set_CSG_Tree_Flag(OBJECT *Object, unsigned long f)
{
OBJECT *Sib;
for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
{
if ((Sib->Methods == &CSG_Intersection_Methods) ||
(Sib->Methods == &CSG_Merge_Methods) ||
(Sib->Methods == &CSG_Union_Methods))
{
Set_CSG_Tree_Flag(Sib, f);
}
Set_Flag(Sib,f);
}
}
/* JG end */
#endif
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static OBJECT *Parse_Sphere()
{
SPHERE *Object;
Parse_Begin();
if ((Object = (SPHERE *)Parse_Object_Id()) != NULL)
{
return ((OBJECT *) Object);
}
Object = Create_Sphere();
Parse_Vector(Object->Center);
Parse_Comma();
Object->Radius = Parse_Float();
Compute_Sphere_BBox(Object);
Parse_Object_Mods((OBJECT *)Object);
return((OBJECT *)Object);
}
/** poviso: O. & R.S. **/
#ifdef POVISO
/*****************************************************************************
*
* FUNCTION
* Parse_Parametric
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static OBJECT *Parse_Parametric( void )
{
PARAMETRIC *Object;
char flags;
DBL temp;
char PrecompFlag=0;
int PrecompDepth;
Parse_Begin ();
if ( (Object = (PARAMETRIC *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
Object = Create_Parametric();
GET(FUNCTION_TOKEN);
Object->Func[0]= Parse_Function(); Parse_Comma();
flags= Object->Func[0]->Flags;
Object->Func[1]= Parse_Function(); Parse_Comma();
flags|= Object->Func[0]->Flags;
Object->Func[2]= Parse_Function();
flags|= Object->Func[0]->Flags;
if (((flags) & (255- (OK_U|OK_V))) != 0)
Error("Parametric: other variables used than u,v");
GET (LEFT_ANGLE_TOKEN);
Object->umin=Parse_Float(); Parse_Comma();
Object->vmin=Parse_Float();
GET (RIGHT_ANGLE_TOKEN); Parse_Comma();
GET (LEFT_ANGLE_TOKEN);
Object->umax=Parse_Float(); Parse_Comma();
Object->vmax=Parse_Float();
GET (RIGHT_ANGLE_TOKEN);
if (Object->umin>Object->umax) { temp= Object->umin; Object->umin= Object->umax; Object->umax=temp; }
if (Object->vmin>Object->vmax) { temp= Object->vmin; Object->vmin= Object->vmax; Object->vmax=temp; }
EXPECT
CASE(ACCURACY_TOKEN)
Object->accuracy= Parse_Float();
END_CASE
CASE(PRECOMPUTE_TOKEN)
PrecompDepth= Parse_Float();
Parse_Comma();
GET(LEFT_SQUARE_TOKEN)
while (1)
{
Get_Token();
switch (Token.Function_Id)
{
case X_TOKEN: PrecompFlag|= OK_X; break;
case Y_TOKEN: PrecompFlag|= OK_Y; break;
case Z_TOKEN: PrecompFlag|= OK_Z; break;
default:
Error("Precompute: x, y or z expected");
}
Get_Token();
if (Token.Token_Id == RIGHT_SQUARE_TOKEN) break;
if (Token.Token_Id != COMMA_TOKEN) Parse_Error (COMMA_TOKEN);
}
END_CASE
CASE_VECTOR
Parse_Vector((Object->bounds[0])); Parse_Comma();
Parse_Vector((Object->bounds[1]));
if (Object->bounds[0][X] > Object->bounds[1][X]) {
temp = Object->bounds[0][X];
Object->bounds[0][X] = Object->bounds[1][X];
Object->bounds[1][X] = temp;
}
if (Object->bounds[0][Z] > Object->bounds[1][Z]) {
temp = Object->bounds[0][Z];
Object->bounds[0][Z] = Object->bounds[1][Z];
Object->bounds[1][Z] = temp;
}
if (Object->bounds[0][Z] > Object->bounds[1][Z]) {
temp = Object->bounds[0][Z];
Object->bounds[0][Z] = Object->bounds[1][Z];
Object->bounds[1][Z] = temp;
}
END_CASE
#ifdef IsoBlobPatch
/* Lummox JR, July 1999 */
CASE (TNORMAL_TOKEN)
Object->normal_type = (char)(int)Allow_Float(1.0);
END_CASE
/* End Lummox JR's modifications */
#endif
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_Object_Mods ((OBJECT *)Object);
if (PrecompFlag != 0) Object->PData=
Precompute_Parametric_Values(Object, PrecompFlag, PrecompDepth);
return ((OBJECT *) Object);
}
#endif
/** --- **/
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static
OBJECT *Parse_Plane ()
{
DBL len;
PLANE *Object;
Parse_Begin ();
if ( (Object = (PLANE *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
Object = Create_Plane();
Parse_Vector(Object->Normal_Vector); Parse_Comma();
VLength(len, Object->Normal_Vector);
if (len < EPSILON)
{
Error("Degenerate plane normal.");
}
VInverseScaleEq(Object->Normal_Vector, len);
Object->Distance = -Parse_Float();
Compute_Plane_BBox(Object);
Parse_Object_Mods ((OBJECT *)Object);
return ((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static
OBJECT *Parse_HField ()
{
HFIELD *Object;
VECTOR Local_Vector;
IMAGE *Image;
Parse_Begin ();
if ( (Object = (HFIELD *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
Object = Create_HField();
Image = Parse_Image (HF_FILE);
Image->Use_Colour_Flag = FALSE;
Make_Vector(Object->bounding_box->bounds[0], 0.0, 0.0, 0.0);
if (Image->File_Type == POT_FILE)
{
Object->bounding_box->bounds[1][X] = Image->width/2.0 - 1.0;
}
else
{
Object->bounding_box->bounds[1][X] = Image->width - 1.0;
}
Object->bounding_box->bounds[1][Y] = 65536.0;
Object->bounding_box->bounds[1][Z] = Image->height - 1.0;
Make_Vector(Local_Vector,
1.0 / (Object->bounding_box->bounds[1][X]),
1.0 / (Object->bounding_box->bounds[1][Y]),
1.0 / (Object->bounding_box->bounds[1][Z]));
Compute_Scaling_Transform(Object->Trans, Local_Vector);
Parse_Object_Mods ((OBJECT *)Object);
Compute_HField(Object, Image);
Compute_HField_BBox(Object);
Destroy_Image (Image);
return ((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static OBJECT *Parse_Triangle()
{
TRIANGLE *Object;
Parse_Begin();
if ((Object = (TRIANGLE *)Parse_Object_Id()) != NULL)
{
return((OBJECT *) Object);
}
Object = Create_Triangle();
Parse_Vector(Object->P1); Parse_Comma();
Parse_Vector(Object->P2); Parse_Comma();
Parse_Vector(Object->P3);
/* Note that Compute_Triangle also computes the bounding box. */
if (!Compute_Triangle(Object, FALSE))
{
Warn(0, "Degenerate triangle. Please remove.");
}
Parse_Object_Mods((OBJECT *)Object);
return((OBJECT *)Object);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static
OBJECT *Parse_Smooth_Triangle ()
{
SMOOTH_TRIANGLE *Object;
short degen;
DBL vlen;
degen=FALSE;
Parse_Begin ();
if ( (Object = (SMOOTH_TRIANGLE *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
Object = Create_Smooth_Triangle();
Parse_Vector (Object->P1); Parse_Comma();
Parse_Vector (Object->N1); Parse_Comma();
VLength(vlen,Object->N1);
if (vlen == 0.0)
degen=TRUE;
else
VNormalize (Object->N1, Object->N1);
Parse_Vector (Object->P2); Parse_Comma();
Parse_Vector (Object->N2); Parse_Comma();
VLength(vlen,Object->N2);
if (vlen == 0.0)
degen=TRUE;
else
VNormalize (Object->N2, Object->N2);
Parse_Vector (Object->P3); Parse_Comma();
Parse_Vector (Object->N3);
VLength(vlen,Object->N3);
if (vlen == 0.0)
degen=TRUE;
else
VNormalize (Object->N3, Object->N3);
if (!degen)
{
degen=!Compute_Triangle ((TRIANGLE *) Object,TRUE);
}
if (degen)
{
Warn(0, "Degenerate triangle. Please remove.");
}
Compute_Triangle_BBox((TRIANGLE *)Object);
Parse_Object_Mods ((OBJECT *)Object);
return ((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static
OBJECT *Parse_Quadric ()
{
VECTOR Min, Max;
QUADRIC *Object;
Parse_Begin ();
if ( (Object = (QUADRIC *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
Object = Create_Quadric();
Parse_Vector(Object->Square_Terms); Parse_Comma();
Parse_Vector(Object->Mixed_Terms); Parse_Comma();
Parse_Vector(Object->Terms); Parse_Comma();
Object->Constant = Parse_Float();
Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
Make_Vector(Max, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
Compute_Quadric_BBox(Object, Min, Max);
Parse_Object_Mods ((OBJECT *)Object);
return ((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static
OBJECT *Parse_Box ()
{
BOX *Object;
DBL temp;
Parse_Begin ();
if ( (Object = (BOX *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
Object = Create_Box();
Parse_Vector(Object->bounds[0]); Parse_Comma();
Parse_Vector(Object->bounds[1]);
if (Object->bounds[0][X] > Object->bounds[1][X]) {
temp = Object->bounds[0][X];
Object->bounds[0][X] = Object->bounds[1][X];
Object->bounds[1][X] = temp;
}
if (Object->bounds[0][Y] > Object->bounds[1][Y]) {
temp = Object->bounds[0][Y];
Object->bounds[0][Y] = Object->bounds[1][Y];
Object->bounds[1][Y] = temp;
}
if (Object->bounds[0][Z] > Object->bounds[1][Z]) {
temp = Object->bounds[0][Z];
Object->bounds[0][Z] = Object->bounds[1][Z];
Object->bounds[1][Z] = temp;
}
Compute_Box_BBox(Object);
Parse_Object_Mods ((OBJECT *)Object);
return ((OBJECT *) Object);
}
/** poviso: '96 R.S. **/
#ifdef POVISO
/*****************************************************************************
*
* FUNCTION OBJECT *Parse_IsoSurface ( int parse_type)
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR R. Suzuki
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Iso_Parse_Box(ISOSURFACE *Object)
{
DBL temp;
int flag=FALSE;
Get_Token ();
if (Token.Token_Id == LEFT_CURLY_TOKEN) flag=TRUE;
else
UNGET
Parse_Vector(Object->bounds[0]); Parse_Comma();
Parse_Vector(Object->bounds[1]);
if (Object->bounds[0][X] > Object->bounds[1][X])
{
temp = Object->bounds[0][X];
Object->bounds[0][X] = Object->bounds[1][X];
Object->bounds[1][X] = temp;
}
if (Object->bounds[0][Z] > Object->bounds[1][Z])
{
temp = Object->bounds[0][Z];
Object->bounds[0][Z] = Object->bounds[1][Z];
Object->bounds[1][Z] = temp;
}
if (Object->bounds[0][Z] > Object->bounds[1][Z])
{
temp = Object->bounds[0][Z];
Object->bounds[0][Z] = Object->bounds[1][Z];
Object->bounds[1][Z] = temp;
}
if (flag==TRUE)
{
Get_Token ();
if (Token.Token_Id != RIGHT_CURLY_TOKEN)
Error("No matching } in isosurface");
}
Object->container_shape=0;
Compute_Box_BBox((BOX *)Object);
}
void Iso_Parse_Sphere(ISOSURFACE *Object)
{
/*YS DBL temp;*/
int flag=FALSE;
Get_Token ();
if (Token.Token_Id == LEFT_CURLY_TOKEN) flag=TRUE; else UNGET
Parse_Vector(Object->bounds[0]); Parse_Comma();
Object->bounds[1][X]=Parse_Float();
Object->container_shape=1;
if (flag==TRUE)
{
Get_Token ();
if (Token.Token_Id != RIGHT_CURLY_TOKEN)
Error("No matching } in isosurface");
}
Compute_Sphere_BBox((SPHERE *)Object);
}
static OBJECT *Parse_IsoSurface (int parse_type)
{
ISOSURFACE *Object;
int imax;
char *tstr;
char flags= OK_X|OK_Y|OK_Z;
int parsed_contained_by;
parsed_contained_by = FALSE;
Parse_Begin ();
if ( (Object = (ISOSURFACE *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
Object = (ISOSURFACE *)Create_IsoSurface();
EXPECT
CASE(FUNCTION_TOKEN)
Object->Func= Parse_Function();
if (Object->Func->Lib==NULL)
Object->Func->Lib=Object->Lib;/* RS May '97 */
Object->Func->isosf=Object;
Load_Function(Object->Func, Object->Func->func_name);/* RS May '97 */
END_CASE
/* NK switched to contained_by */
CASE (CONTAINED_BY_TOKEN)
parsed_contained_by = TRUE;
/* use "open" or "close" to change the closed flag */
Parse_Begin ();
EXPECT
CASE(BOX_TOKEN)
Iso_Parse_Box(Object);
END_CASE
CASE(SPHERE_TOKEN)
Iso_Parse_Sphere(Object);
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End ();
END_CASE
CASE(THRESHOLD_TOKEN)
if (Object->Func !=NULL)
{
Object->Func->threshold = Parse_Float();
}
else
Error("'function' is not defined \n");
END_CASE
CASE(ACCURACY_TOKEN)
Object->accuracy = Parse_Float();
END_CASE
CASE(SIGN_TOKEN)
Object->Func->sign = Parse_Float();
END_CASE
CASE(MAX_GRADIENT_TOKEN)
if (Object->Func !=NULL)
{
Object->Func->Max_gradient = Parse_Float();
Object->gradient_flag=0;
}
else
Error("'function' is not defined \n");
END_CASE
CASE(MAX_TRACE_TOKEN)
Object->max_trace = (short)Parse_Float();
END_CASE
CASE(NOEVAL_TOKEN)
Object->Eval=0;
END_CASE
CASE(EVAL_TOKEN)
Object->Eval=1;
Get_Token();
if (Token.Token_Id == LEFT_ANGLE_TOKEN)
{
Unget_Token();
Parse_Parm(3, &imax);
memcpy( Object->grad_parm, iso_p, imax *sizeof(DBL));
}
else Unget_Token();
END_CASE
CASE(OPEN_TOKEN)
Object->closed=0;
END_CASE
CASE(CLOSE_TOKEN)
Object->closed=1;
END_CASE
CASE(LIBRARY_TOKEN)
GET (STRING_LITERAL_TOKEN);
tstr = (char*)POV_MALLOC (strlen(Token.Token_String) + 1, "lib_name");
strcpy (tstr, Token.Token_String);
Object->Lib= (LIBRARY*)POV_MALLOC (sizeof(LIBRARY), "library struct");
Get_Token();
Load_Lib(Object->Lib, tstr); /* RS July 18 '96 */
if (Token.Token_Id == COMMA_TOKEN)
{
Get_Token();
if(Token.Token_Id==ARRAY_ID_TOKEN)
{
Object->Lib->pClient=(char*)(*(Token.DataPtr));
Object->Lib->pClientDataSource=PCLIENTDATA_ARRAY;
}
else
{
Unget_Token();
/* .. if its not an array, it should be a filename*/
Object->Lib->pClient =(char*)Parse_String();
Object->Lib->pClientDataSource=PCLIENTDATA_FILE;
}
/*--dfs*/
if (Token.Token_Id == COMMA_TOKEN)
{
Parse_Parm(0, &Object->Lib->pnum);
Object->Lib->parm = (DBL *) POV_MALLOC (Object->Lib->pnum *sizeof(DBL), "isosurface lib_parm");
memcpy( Object->Lib->parm, iso_p, Object->Lib->pnum*sizeof(DBL));
}
else Unget_Token();
}
/* R.S. Sep 96*/
else
{
Unget_Token();Object->Lib->pClientData =0;
}
Init_Lib(Object->Lib);
POV_FREE(tstr);
END_CASE
CASE(METHOD_TOKEN)
Object->method = (int)(15.-Parse_Float()*10.);
END_CASE
CASE(ALL_INTERSECTIONS_TOKEN)
Object->max_trace= ISOSURFACE_MAXTRACE;
END_CASE
#ifdef IsoBlobPatch
/* Lummox JR, July 1999 */
CASE (TNORMAL_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Object->normal_type = (char)(int)Allow_Float(1.0);
END_CASE
/* End Lummox JR's modifications */
#endif
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
if (Object->Func == NULL)
Error("'function' is not defined");
if (Object->accuracy <= 0.)
Error("isosurface component ACCURACY");
if (Object->Func->Max_gradient <= 0.)
Error("isosurface component MAXGRADIENT");
if (Object->max_trace > ISOSURFACE_MAXTRACE)
Error("isosurface component MAXTRACE>(ISOSURFACE_MAXTRACE)");
if (Object->max_trace < 0)
Error("isosurface component MAXTRACE should be >1");
if (!parsed_contained_by)
Error("isosurface requires contained_by");
if (!strcmp(Object->Func->func_name,"imp_func")) Object->method +=2;
if (Object->Func->m_flag==1) Object->method -=3;
Parse_Object_Mods ((OBJECT *)Object);
return ((OBJECT *) Object);
}
#endif
/** --- **/
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
* speed improvements (FastDiscPatch) added April 18 by Dejan Milosavljevic
*
******************************************************************************/
static OBJECT *Parse_Disc (void)
{
DISC *Object;
#ifndef FastDiscPatch
DBL tmpf;
Parse_Begin ();
if ( (Object = (DISC *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
Object = Create_Disc();
Parse_Vector(Object->center); Parse_Comma ();
Parse_Vector(Object->normal); Parse_Comma ();
VNormalize(Object->normal, Object->normal);
tmpf = Parse_Float(); Parse_Comma ();
Object->oradius2 = tmpf * tmpf;
EXPECT
CASE_FLOAT
tmpf = Parse_Float();
Object->iradius2 = tmpf * tmpf;
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
/* Calculate info needed for ray-disc intersections */
VDot(tmpf, Object->center, Object->normal);
Object->d = -tmpf;
Compute_Disc(Object);
Parse_Object_Mods ((OBJECT *)Object);
return ((OBJECT *) Object);
#else
DBL inner_radius, outer_radius;
VECTOR center, normal;
Parse_Begin ();
if ( (Object = (DISC *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
Object = Create_Disc();
Parse_Vector(center); Parse_Comma ();
Parse_Vector(normal); Parse_Comma ();
outer_radius = Parse_Float(); Parse_Comma ();
inner_radius = 0.0;
EXPECT
CASE_FLOAT
inner_radius = Parse_Float();
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
#ifndef FastDiscPatch
/* Calculate info needed for ray-disc intersections */
VDot(Object->d, Object->center, Object->normal);
Object->d = -Object->d;
#endif
Compute_Disc( Object, center, normal, inner_radius, outer_radius );
Parse_Object_Mods ((OBJECT *)Object);
return ((OBJECT *) Object);
#endif
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static
OBJECT *Parse_Cylinder ()
{
CONE *Object;
Parse_Begin ();
if ( (Object = (CONE *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
Object = Create_Cylinder();
Parse_Vector(Object->apex); Parse_Comma ();
Parse_Vector(Object->base); Parse_Comma ();
Object->apex_radius = Parse_Float();
Object->base_radius = Object->apex_radius;
EXPECT
CASE(OPEN_TOKEN)
Clear_Flag(Object, CLOSED_FLAG);
EXIT
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Compute_Cylinder_Data((OBJECT *)Object);
Compute_Cone_BBox(Object);
Parse_Object_Mods ((OBJECT *)Object);
return ((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static
OBJECT *Parse_Cone ()
{
CONE *Object;
Parse_Begin ();
if ( (Object = (CONE *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
Object = Create_Cone();
Parse_Vector(Object->apex); Parse_Comma ();
Object->apex_radius = Parse_Float(); Parse_Comma ();
Parse_Vector(Object->base); Parse_Comma ();
Object->base_radius = Parse_Float();
EXPECT
CASE(OPEN_TOKEN)
Clear_Flag(Object, CLOSED_FLAG);
EXIT
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
/* Compute run-time values for the cone */
Compute_Cone_Data((OBJECT *)Object);
Compute_Cone_BBox(Object);
Parse_Object_Mods ((OBJECT *)Object);
return ((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Blob_Element_Mods
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* Dieter Bayer
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* Sep 1994 : Creation.
*
******************************************************************************/
static void Parse_Blob_Element_Mods(BLOB_ELEMENT *Element)
{
VECTOR Local_Vector;
MATRIX Local_Matrix;
TRANSFORM Local_Trans;
TEXTURE *Local_Texture;
EXPECT
CASE (TRANSLATE_TOKEN)
Parse_Vector (Local_Vector);
Translate_Blob_Element (Element, Local_Vector);
END_CASE
CASE (ROTATE_TOKEN)
Parse_Vector (Local_Vector);
Rotate_Blob_Element (Element, Local_Vector);
END_CASE
CASE (SCALE_TOKEN)
Parse_Scale_Vector (Local_Vector);
Scale_Blob_Element (Element, Local_Vector);
END_CASE
CASE (TRANSFORM_TOKEN)
#ifndef TransformPatch /* Chris Huff april 2000 */
GET(TRANSFORM_ID_TOKEN)
Transform_Blob_Element (Element, (TRANSFORM *)Token.Data);
#else
{
TRANSFORM * Trans = Parse_Transform();
Transform_Blob_Element (Element, Trans);
/*YS sept 17 2000 Memory leak*/
POV_FREE(Trans);
}
#endif
END_CASE
CASE (MATRIX_TOKEN)
Parse_Matrix (Local_Matrix);
Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
Transform_Blob_Element (Element, &Local_Trans);
END_CASE
CASE (TEXTURE_TOKEN)
Parse_Begin ();
Local_Texture = Parse_Texture();
Parse_End ();
Link_Textures(&Element->Texture, Local_Texture);
END_CASE
CASE3 (PIGMENT_TOKEN, TNORMAL_TOKEN, FINISH_TOKEN)
if (Element->Texture == NULL)
{
Element->Texture = Copy_Textures(Default_Texture);
}
else
{
if (Element->Texture->Type != PLAIN_PATTERN)
{
Link_Textures(&Element->Texture, Copy_Textures(Default_Texture));
}
}
UNGET
EXPECT
CASE (PIGMENT_TOKEN)
Parse_Begin ();
Parse_Pigment(&Element->Texture->Pigment);
Parse_End ();
END_CASE
CASE (TNORMAL_TOKEN)
Parse_Begin ();
Parse_Tnormal(&Element->Texture->Tnormal);
Parse_End ();
END_CASE
CASE (FINISH_TOKEN)
Parse_Finish(&Element->Texture->Finish);
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End();
/* Postprocess to make sure that HAS_FILTER will be set correctly. */
Post_Textures(Element->Texture);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Blob
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* Dieter Bayer
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* Jul 1994 : Creation.
*
******************************************************************************/
#ifdef BlobPatternPatch
OBJECT *Parse_Blob( void)
#else
static OBJECT *Parse_Blob()
#endif
{
int npoints;
DBL threshold;
VECTOR Axis, Base, Apex;
BLOB *Object;
BLOB_LIST *blob_components, *blob_component;
Parse_Begin();
if ((Object = (BLOB *)Parse_Object_Id()) != NULL)
{
return ((OBJECT *) Object);
}
Object = Create_Blob();
blob_components = NULL;
npoints = 0;
threshold = 1.0;
EXPECT
CASE (THRESHOLD_TOKEN)
threshold = Parse_Float();
END_CASE
/*************************************************************************
* Read sperical component (old syntax).
*************************************************************************/
CASE (COMPONENT_TOKEN)
blob_component = Create_Blob_List_Element();
blob_component->elem.Type = BLOB_SPHERE;
blob_component->elem.c[2] = Parse_Float();
Parse_Comma();
blob_component->elem.rad2 = Parse_Float();
Parse_Comma();
blob_component->elem.rad2 = Sqr(blob_component->elem.rad2);
Parse_Vector(blob_component->elem.O);
/* Next component. */
blob_component->next = blob_components;
blob_components = blob_component;
npoints++;
END_CASE
/*************************************************************************
* Read sperical component (new syntax).
*************************************************************************/
CASE (SPHERE_TOKEN)
blob_component = Create_Blob_List_Element();
blob_component->elem.Type = BLOB_SPHERE;
Parse_Begin();
Parse_Vector(blob_component->elem.O);
Parse_Comma();
blob_component->elem.rad2 = Parse_Float();
blob_component->elem.rad2 = Sqr(blob_component->elem.rad2);
Parse_Comma();
ALLOW(STRENGTH_TOKEN)
blob_component->elem.c[2] = Parse_Float();
Parse_Blob_Element_Mods(&blob_component->elem);
/* Next component. */
blob_component->next = blob_components;
blob_components = blob_component;
npoints++;
END_CASE
/*************************************************************************
* Read cylindrical component.
*************************************************************************/
CASE (CYLINDER_TOKEN)
blob_component = Create_Blob_List_Element();
blob_component->elem.Type = BLOB_CYLINDER;
blob_component->elem.Trans = Create_Transform();
Parse_Begin();
Parse_Vector(Base);
Parse_Comma();
Parse_Vector(Apex);
Parse_Comma();
blob_component->elem.rad2 = Parse_Float();
blob_component->elem.rad2 = Sqr(blob_component->elem.rad2);
Parse_Comma();
ALLOW(STRENGTH_TOKEN)
blob_component->elem.c[2] = Parse_Float();
/* Calculate cylinder's coordinate system. */
VSub(Axis, Apex, Base);
VLength(blob_component->elem.len, Axis);
if (blob_component->elem.len < EPSILON)
{
Error("Degenerate cylindrical component in blob.\n");
}
VInverseScaleEq(Axis, blob_component->elem.len);
Compute_Coordinate_Transform(blob_component->elem.Trans, Base, Axis, 1.0, 1.0);
Parse_Blob_Element_Mods(&blob_component->elem);
/* Next component. */
blob_component->next = blob_components;
blob_components = blob_component;
npoints++;
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Create_Blob_Element_Texture_List(Object, blob_components, npoints);
Parse_Object_Mods((OBJECT *)Object);
/* The blob's texture has to be processed before Make_Blob() is called. */
Post_Textures(Object->Texture);
/* Finally, process the information */
Make_Blob(Object, threshold, blob_components, npoints);
return((OBJECT *)Object);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Julia_Fractal
*
* INPUT None
*
* OUTPUT Fractal Objecstructure filledt
*
* RETURNS
*
* OBJECT * -
*
* AUTHOR
*
* Pascal Massimino
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* Dec 1994 : Adopted to version 3.0. [DB]
* Sept 1995 : Total rewrite for new syntax [TW]
*
******************************************************************************/
static OBJECT *Parse_Julia_Fractal ()
{
FRACTAL *Object;
DBL P;
Parse_Begin();
if ( (Object = (FRACTAL *)Parse_Object_Id()) != NULL)
return((OBJECT *)Object);
Object = Create_Fractal();
Parse_Vector4D(Object->Julia_Parm);
EXPECT
CASE(MAX_ITERATION_TOKEN)
Object->n = (int)floor(Parse_Float());
if (Object->n <= 0)
{
Object->n = 1;
}
END_CASE
CASE(SLICE_TOKEN)
Parse_Vector4D(Object->Slice);
Parse_Comma();
Object->SliceDist = Parse_Float();
/* normalize slice vector */
V4D_Dot(P,Object->Slice, Object->Slice);
if (fabs(P) < EPSILON)
{
Error("Slice vector is zero.\n");
}
if (fabs(Object->Slice[T]) < EPSILON)
{
Error("Slice t component is zero.\n");
}
P = sqrt(P);
V4D_InverseScaleEq(Object->Slice, P);
END_CASE
CASE(PRECISION_TOKEN)
P = Parse_Float();
if ( P < 1.0 )
{
P = 1.0;
}
Object->Precision = 1.0 / P;
END_CASE
CASE(FLOAT_FUNCT_TOKEN)
switch(Token.Function_Id)
{
case EXP_TOKEN:
Object->Sub_Type = EXP_STYPE;
break;
case LOG_TOKEN:
Object->Sub_Type = LOG_STYPE;
break;
case SIN_TOKEN:
Object->Sub_Type = SIN_STYPE;
break;
case ASIN_TOKEN:
Object->Sub_Type = ASIN_STYPE;
break;
case COS_TOKEN:
Object->Sub_Type = COS_STYPE;
break;
case ACOS_TOKEN:
Object->Sub_Type = ACOS_STYPE;
break;
#ifdef CubeSqrHatPatch
case SQR_TOKEN:/*Chris Huff*/
Object->Sub_Type = SQR_STYPE;
break;
case CUBE_TOKEN:/*Chris Huff*/
Object->Sub_Type = CUBE_STYPE;
break;
#endif
default: Parse_Error_Str ("fractal keyword");
}
END_CASE
/* if any of the next become supported by the expression parser,
* then their handling would need to move above to the FUNC_TOKEN
* case above.
*/
CASE(ATAN_TOKEN)
Object->Sub_Type = ATAN_STYPE;
END_CASE
CASE(COSH_TOKEN)
Object->Sub_Type = COSH_STYPE;
END_CASE
CASE(SINH_TOKEN)
Object->Sub_Type = SINH_STYPE;
END_CASE
CASE(TANH_TOKEN)
Object->Sub_Type = TANH_STYPE;
END_CASE
CASE(ATANH_TOKEN)
Object->Sub_Type = ATANH_STYPE;
END_CASE
CASE(ACOSH_TOKEN)
Object->Sub_Type = ACOSH_STYPE;
END_CASE
CASE(ASINH_TOKEN)
Object->Sub_Type = ASINH_STYPE;
END_CASE
#ifndef CubeSqrHatPatch
CASE(SQR_TOKEN)
Object->Sub_Type = SQR_STYPE;
END_CASE
#endif
CASE(PWR_TOKEN)
Object->Sub_Type = PWR_STYPE;
Parse_Float_Param2(&Object->exponent.x,&Object->exponent.y);
END_CASE
#ifndef CubeSqrHatPatch
CASE(CUBE_TOKEN)
Object->Sub_Type = CUBE_STYPE;
END_CASE
#endif
CASE(RECIPROCAL_TOKEN)
Object->Sub_Type = RECIPROCAL_STYPE;
END_CASE
CASE(HYPERCOMPLEX_TOKEN)
Object->Algebra = HYPERCOMPLEX_TYPE;
END_CASE
CASE(QUATERNION_TOKEN)
Object->Algebra = QUATERNION_TYPE;
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_Object_Mods((OBJECT *)Object);
SetUp_Fractal(Object);
return((OBJECT *)Object);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Polygon
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* OBJECT * -
*
* AUTHOR
*
* Dieter Bayer
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* May 1994 : Creation.
*
* Oct 1994 : Modified to use new polygon data structure. [DB]
*
******************************************************************************/
static OBJECT *Parse_Polygon()
{
int i, closed = FALSE;
int Number;
POLYGON *Object;
VECTOR *Points, P;
Parse_Begin();
if ((Object = (POLYGON *)Parse_Object_Id()) != NULL)
{
return((OBJECT *) Object);
}
Object = Create_Polygon();
Number = (int)Parse_Float();
if (Number < 3)
{
Error("Polygon needs at least three points.");
}
Points = (VECTOR *)POV_MALLOC((Number+1)*sizeof(VECTOR), "temporary polygon points");
for (i = 0; i < Number; i++)
{
Parse_Comma();
Parse_Vector(Points[i]);
}
/* Check for closed polygons. */
Assign_Vector(P, Points[0]);
for (i = 1; i < Number; i++)
{
closed = FALSE;
if ((fabs(P[X] - Points[i][X]) < EPSILON) &&
(fabs(P[Y] - Points[i][Y]) < EPSILON) &&
(fabs(P[Z] - Points[i][Z]) < EPSILON))
{
i++;
if (i < Number)
{
Assign_Vector(P, Points[i]);
}
closed = TRUE;
}
}
if (!closed)
{
Warn(0, "Polygon not closed. Closing it.");
Assign_Vector(Points[Number], P);
Number++;
}
Compute_Polygon(Object, Number, Points);
POV_FREE (Points);
Parse_Object_Mods ((OBJECT *)Object);
return((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Prism
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* OBJECT * -
*
* AUTHOR
*
* Dieter Bayer
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* May 1994 : Creation.
*
******************************************************************************/
static OBJECT *Parse_Prism()
{
int i, closed = FALSE;
DBL h;
PRISM *Object;
UV_VECT *Points, P;
Parse_Begin();
if ((Object = (PRISM *)Parse_Object_Id()) != NULL)
{
return((OBJECT *) Object);
}
Object = Create_Prism();
/*
* Determine kind of spline used (linear, quadratic, cubic)
* and type of sweeping (linear, conic).
*/
EXPECT
CASE(LINEAR_SPLINE_TOKEN)
Object->Spline_Type = LINEAR_SPLINE;
END_CASE
CASE(QUADRATIC_SPLINE_TOKEN)
Object->Spline_Type = QUADRATIC_SPLINE;
END_CASE
CASE(CUBIC_SPLINE_TOKEN)
Object->Spline_Type = CUBIC_SPLINE;
END_CASE
CASE(BEZIER_SPLINE_TOKEN)
Object->Spline_Type = BEZIER_SPLINE;
END_CASE
CASE(LINEAR_SWEEP_TOKEN)
Object->Sweep_Type = LINEAR_SWEEP;
END_CASE
CASE(CONIC_SWEEP_TOKEN)
Object->Sweep_Type = CONIC_SWEEP;
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
/* Read prism heights. */
Object->Height1 = Parse_Float(); Parse_Comma();
Object->Height2 = Parse_Float(); Parse_Comma();
if (Object->Height1 > Object->Height2)
{
h = Object->Height1;
Object->Height1 = Object->Height2;
Object->Height2 = h;
}
/* Get number of points = number of segments. */
Object->Number = (int)Parse_Float();
switch (Object->Spline_Type)
{
case LINEAR_SPLINE :
if (Object->Number < 3)
{
Error("Prism with linear splines must have at least three points.");
}
break;
case QUADRATIC_SPLINE :
if (Object->Number < 5)
{
Error("Prism with quadratic splines must have at least five points.");
}
break;
case CUBIC_SPLINE :
if (Object->Number < 6)
{
Error("Prism with cubic splines must have at least six points.");
}
break;
case BEZIER_SPLINE :
if ((Object->Number & 3) != 0)
{
Error("Prism with Bezier splines must have four points per segment.");
}
break;
}
/* Allocate Object->Number points for the prism. */
Points = (UV_VECT *)POV_MALLOC((Object->Number+1) * sizeof(UV_VECT), "temporary prism points");
/* Read points (x, y : coordinate of 2d point; z : not used). */
for (i = 0; i < Object->Number; i++)
{
Parse_Comma();
Parse_UV_Vect(Points[i]);
}
/* Closed or not closed that's the question. */
EXPECT
CASE(OPEN_TOKEN)
Clear_Flag(Object, CLOSED_FLAG);
EXIT
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
/* Check for closed prism. */
if ((Object->Spline_Type == LINEAR_SPLINE) ||
(Object->Spline_Type == QUADRATIC_SPLINE) ||
(Object->Spline_Type == CUBIC_SPLINE))
{
switch (Object->Spline_Type)
{
case LINEAR_SPLINE :
i = 1;
Assign_UV_Vect(P, Points[0]);
break;
case QUADRATIC_SPLINE :
case CUBIC_SPLINE :
i = 2;
Assign_UV_Vect(P, Points[1]);
break;
}
for ( ; i < Object->Number; i++)
{
closed = FALSE;
if ((fabs(P[X] - Points[i][X]) < EPSILON) &&
(fabs(P[Y] - Points[i][Y]) < EPSILON))
{
switch (Object->Spline_Type)
{
case LINEAR_SPLINE :
i++;
if (i < Object->Number)
{
Assign_UV_Vect(P, Points[i]);
}
break;
case QUADRATIC_SPLINE :
i += 2;
if (i < Object->Number)
{
Assign_UV_Vect(P, Points[i]);
}
break;
case CUBIC_SPLINE :
i += 3;
if (i < Object->Number)
{
Assign_UV_Vect(P, Points[i]);
}
break;
}
closed = TRUE;
}
}
}
else
{
closed = TRUE;
for (i = 0; i < Object->Number; i += 4)
{
if ((fabs(Points[i][X] - Points[(i-1+Object->Number) % Object->Number][X]) > EPSILON) ||
(fabs(Points[i][Y] - Points[(i-1+Object->Number) % Object->Number][Y]) > EPSILON))
{
closed = FALSE;
break;
}
}
}
if (!closed)
{
if (Object->Spline_Type == LINEAR_SPLINE)
{
Assign_UV_Vect(Points[Object->Number], P);
Object->Number++;
Warn(0, "Linear prism not closed. Closing it.");
}
else
{
Set_Flag(Object, DEGENERATE_FLAG);
Warn(0, "Prism not closed. Ignoring it.");
}
}
/* Compute spline segments. */
Compute_Prism(Object, Points);
/* Compute bounding box. */
Compute_Prism_BBox(Object);
/* Parse object's modifiers. */
Parse_Object_Mods((OBJECT *)Object);
/* Destroy temporary points. */
POV_FREE (Points);
return((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Sor
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* OBJECT * -
*
* AUTHOR
*
* Dieter Bayer
*
* DESCRIPTION
*
* Read a surface of revolution primitive.
*
* CHANGES
*
* May 1994 : Creation.
*
******************************************************************************/
static OBJECT *Parse_Sor()
{
int i;
SOR *Object;
UV_VECT *Points;
Parse_Begin();
if ((Object = (SOR *)Parse_Object_Id()) != NULL)
{
return((OBJECT *)Object);
}
Object = Create_Sor();
/* Get number of points. */
Object->Number = (int)Parse_Float();
if (Object->Number <4)
{
Error("Surface of revolution must have at least four points.");
}
/* Get temporary points describing the rotated curve. */
Points = (UV_VECT *)POV_MALLOC(Object->Number*sizeof(UV_VECT), "temporary surface of revolution points");
/* Read points (x : radius; y : height; z : not used). */
for (i = 0; i < Object->Number; i++)
{
Parse_Comma();
Parse_UV_Vect(Points[i]);
if ((Points[i][X] < 0.0) ||
((i > 1 ) && (i < Object->Number - 1) && (Points[i][Y] <= Points[i-1][Y])))
{
Error("Incorrect point in surface of revolution.");
}
}
/* Closed or not closed that's the question. */
EXPECT
CASE(OPEN_TOKEN)
Clear_Flag(Object, CLOSED_FLAG);
EXIT
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
/* There are Number-3 segments! */
Object->Number -= 3;
/* Compute spline segments. */
Compute_Sor(Object, Points);
/* Compute bounding box. */
Compute_Sor_BBox(Object);
/* Parse object's modifiers. */
Parse_Object_Mods((OBJECT *)Object);
/* Destroy temporary points. */
POV_FREE (Points);
return ((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Lathe
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* OBJECT * -
*
* AUTHOR
*
* Dieter Bayer
*
* DESCRIPTION
*
* Read a lathe primitive.
*
* CHANGES
*
* Jun 1994 : Creation.
*
******************************************************************************/
static OBJECT *Parse_Lathe()
{
int i;
LATHE *Object;
UV_VECT *Points;
Parse_Begin();
if ((Object = (LATHE *)Parse_Object_Id()) != NULL)
{
return((OBJECT *)Object);
}
Object = Create_Lathe();
/* Determine kind of spline used and aspect ratio. */
EXPECT
CASE(LINEAR_SPLINE_TOKEN)
Object->Spline_Type = LINEAR_SPLINE;
END_CASE
CASE(QUADRATIC_SPLINE_TOKEN)
Object->Spline_Type = QUADRATIC_SPLINE;
END_CASE
CASE(CUBIC_SPLINE_TOKEN)
Object->Spline_Type = CUBIC_SPLINE;
END_CASE
CASE(BEZIER_SPLINE_TOKEN)
Object->Spline_Type = BEZIER_SPLINE;
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
/* Get number of points. */
Object->Number = (int)Parse_Float();
switch (Object->Spline_Type)
{
case LINEAR_SPLINE :
if (Object->Number < 2)
{
Error("Lathe with linear splines must have at least two points.");
}
break;
case QUADRATIC_SPLINE :
if (Object->Number < 3)
{
Error("Lathe with quadratic splines must have at least three points.");
}
break;
case CUBIC_SPLINE :
if (Object->Number < 4)
{
Error("Prism with cubic splines must have at least four points.");
}
break;
case BEZIER_SPLINE :
if ((Object->Number & 3) != 0)
{
Error("Lathe with Bezier splines must have four points per segment.");
}
break;
}
/* Get temporary points describing the rotated curve. */
Points = (UV_VECT *)POV_MALLOC(Object->Number*sizeof(UV_VECT), "temporary lathe points");
/* Read points (x : radius; y : height; z : not used). */
for (i = 0; i < Object->Number; i++)
{
Parse_Comma();
Parse_UV_Vect(Points[i]);
if ((i > 0) && (i < Object->Number - 1) && (Points[i][X] < 0.0))
{
Error("Incorrect point in lathe.");
}
}
/* Compute spline segments. */
Compute_Lathe(Object, Points);
/* Compute bounding box. */
Compute_Lathe_BBox(Object);
/* Parse object's modifiers. */
Parse_Object_Mods((OBJECT *)Object);
/* Destroy temporary points. */
POV_FREE (Points);
return((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Superellipsoid
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* OBJECT * -
*
* AUTHOR
*
* Dieter Bayer
*
* DESCRIPTION
*
* Read a superellipsoid primitive.
*
* CHANGES
*
* Oct 1994 : Creation.
*
******************************************************************************/
static OBJECT *Parse_Superellipsoid()
{
UV_VECT V1;
SUPERELLIPSOID *Object;
Parse_Begin();
if ((Object = (SUPERELLIPSOID *)Parse_Object_Id()) != NULL)
{
return((OBJECT *)Object);
}
Object = Create_Superellipsoid();
Parse_UV_Vect(V1);
/* The x component is e, the y component is n. */
Object->Power[X] = 2.0 / V1[X];
Object->Power[Y] = V1[X] / V1[Y];
Object->Power[Z] = 2.0 / V1[Y];
/* Compute bounding box. */
Compute_Superellipsoid_BBox(Object);
/* Parse object's modifiers. */
Parse_Object_Mods((OBJECT *)Object);
return((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Torus
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* OBJECT
*
* AUTHOR
*
* Dieter Bayer
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* Jul 1994 : Creation.
*
******************************************************************************/
static OBJECT *Parse_Torus()
{
TORUS *Object;
Parse_Begin();
if ((Object = (TORUS *)Parse_Object_Id()) != NULL)
{
return((OBJECT *)Object);
}
Object = Create_Torus();
/* Read in the two radii. */
Object->R = Parse_Float(); /* Big radius */
Parse_Comma();
Object->r = Parse_Float(); /* Little radius */
Compute_Torus_BBox(Object);
Parse_Object_Mods ((OBJECT *)Object);
return ((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Mesh_Texture
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* OBJECT
*
* AUTHOR
*
* Dieter Bayer
*
* DESCRIPTION
*
* Read an individual triangle mesh texture.
*
* CHANGES
*
* Feb 1995 : Creation.
*
******************************************************************************/
#ifdef ColorTrianglePatch
static TEXTURE *Parse_Mesh_Texture (TEXTURE **t2, TEXTURE **t3)
#else
static TEXTURE *Parse_Mesh_Texture ()
#endif
{
TEXTURE *Texture;
Texture = NULL;
EXPECT
CASE(TEXTURE_TOKEN)
Parse_Begin();
GET(TEXTURE_ID_TOKEN);
Texture = (TEXTURE *)Token.Data;
Parse_End();
END_CASE
#ifdef ColorTrianglePatch
/* NK */
CASE(TEXTURE_LIST_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(40);
#endif
Parse_Begin();
GET(TEXTURE_ID_TOKEN);
Texture = (TEXTURE *)Token.Data;
GET(TEXTURE_ID_TOKEN);
*t2 = (TEXTURE *)Token.Data;
GET(TEXTURE_ID_TOKEN);
*t3 = (TEXTURE *)Token.Data;
Parse_End();
EXIT
END_CASE
#endif
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
return(Texture);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Three_UVCoords
*
* INPUT
*
* OUTPUT
*
* UV1..UV3 are the uv
*
* RETURNS
*
* 1 for successful read, 0 if UV_VECTORS_TOKEN not found
*
* AUTHOR
*
* Nathan Kopp
*
* DESCRIPTION
*
* Look for UV_VECTORS_TOKEN and then read in three UV coordinates
*
******************************************************************************/
int Parse_Three_UVCoords(UV_VECT UV1, UV_VECT UV2, UV_VECT UV3)
{
int Return_Value;
EXPECT
CASE(UV_VECTORS_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Parse_UV_Vect(UV1); Parse_Comma();
Parse_UV_Vect(UV2); Parse_Comma();
Parse_UV_Vect(UV3);
Return_Value = 1;
EXIT
END_CASE
OTHERWISE
Return_Value = 0;
UNGET
EXIT
END_CASE
END_EXPECT
return(Return_Value);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Mesh
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* OBJECT
*
* AUTHOR
*
* Dieter Bayer
*
* DESCRIPTION
*
* Read a triangle mesh.
*
* CHANGES
*
* Feb 1995 : Creation.
*
******************************************************************************/
static OBJECT *Parse_Mesh()
{
/* NK 1998 - added all sorts of uv variables*/
int i;
int number_of_normals, number_of_textures, number_of_triangles, number_of_vertices, number_of_uvcoords;
int max_normals, max_textures, max_triangles, max_vertices, max_uvcoords;
DBL l1, l2, l3;
VECTOR D1, D2, P1, P2, P3, N1, N2, N3, N;
UV_VECT UV1, UV2, UV3;
SNGL_VECT *Normals, *Vertices;
TEXTURE **Textures;
UV_VECT *UVCoords;
MESH *Object;
MESH_TRIANGLE *Triangles;
int fully_textured=TRUE;
/* NK 1998 */
VECTOR Inside_Vect;
#ifdef ColorTrianglePatch
TEXTURE *t2, *t3;
#endif
Make_Vector(Inside_Vect, 0, 0, 0);
/* NK ---- */
Parse_Begin();
if ((Object = (MESH *)Parse_Object_Id()) != NULL)
{
return((OBJECT *)Object);
}
/* Create object. */
Object = Create_Mesh();
/* Allocate temporary normals, textures, triangles and vertices. */
max_normals = 256;
max_vertices = 256;
max_textures = 16;
max_triangles = 256;
Normals = (SNGL_VECT *)POV_MALLOC(max_normals*sizeof(SNGL_VECT), "temporary triangle mesh data");
Textures = (TEXTURE **)POV_MALLOC(max_textures*sizeof(TEXTURE *), "temporary triangle mesh data");
Triangles = (MESH_TRIANGLE *)POV_MALLOC(max_triangles*sizeof(MESH_TRIANGLE), "temporary triangle mesh data");
Vertices = (SNGL_VECT *)POV_MALLOC(max_vertices*sizeof(SNGL_VECT), "temporary triangle mesh data");
/* Read raw triangle file. */
number_of_normals = 0;
number_of_textures = 0;
number_of_triangles = 0;
number_of_vertices = 0;
/* NK 1998 */
max_uvcoords = 256;
UVCoords = (UV_VECT *)POV_MALLOC(max_uvcoords*sizeof(UV_VECT), "temporary triangle mesh data");
number_of_uvcoords = 0;
/* NK ---- */
/* Create hash tables. */
Create_Mesh_Hash_Tables();
EXPECT
CASE(TRIANGLE_TOKEN)
Parse_Begin();
Parse_Vector(P1); Parse_Comma();
Parse_Vector(P2); Parse_Comma();
Parse_Vector(P3);
if (!Mesh_Degenerate(P1, P2, P3))
{
if (number_of_triangles >= max_triangles)
{
if (max_triangles >= INT_MAX/2)
{
Error("Too many triangles in triangle mesh.\n");
}
max_triangles *= 2;
Triangles = (MESH_TRIANGLE *)POV_REALLOC(Triangles, max_triangles*sizeof(MESH_TRIANGLE), "triangle triangle mesh data");
}
/* Init triangle. */
Init_Mesh_Triangle(&Triangles[number_of_triangles]);
Triangles[number_of_triangles].P1 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P1);
Triangles[number_of_triangles].P2 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P2);
Triangles[number_of_triangles].P3 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P3);
/* NK 1998 */
Parse_Three_UVCoords(UV1,UV2,UV3);
Triangles[number_of_triangles].UV1 = Mesh_Hash_UV(&number_of_uvcoords, &max_uvcoords, &UVCoords,UV1);
Triangles[number_of_triangles].UV2 = Mesh_Hash_UV(&number_of_uvcoords, &max_uvcoords, &UVCoords,UV2);
Triangles[number_of_triangles].UV3 = Mesh_Hash_UV(&number_of_uvcoords, &max_uvcoords, &UVCoords,UV3);
/* NK ---- */
#ifdef ColorTrianglePatch
/* NK */
/* read possibly three instead of only one texture */
/* read these before compute!!! */
t2 = t3 = NULL;
Triangles[number_of_triangles].Texture = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, Parse_Mesh_Texture(&t2,&t3));
if (t2) Triangles[number_of_triangles].Texture2 = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, t2);
if (t3) Triangles[number_of_triangles].Texture3 = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, t3);
if (t2 || t3) Triangles[number_of_triangles].ThreeTex = TRUE;
#endif
Compute_Mesh_Triangle(&Triangles[number_of_triangles], FALSE, P1, P2, P3, N);
Triangles[number_of_triangles].Normal_Ind = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N);
#ifndef ColorTrianglePatch
Triangles[number_of_triangles].Texture = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, Parse_Mesh_Texture());
#endif
if (Triangles[number_of_triangles].Texture < 0)
{
fully_textured = FALSE;
}
number_of_triangles++;
}
/* NK degenerate fix */
else
{
/* parse the uv and texture info - even though we'll just throw it
away. why? if not we get a parse error - we should just ignore the
degenerate triangle */
t2=t3=NULL;
Parse_Three_UVCoords(UV1,UV2,UV3);
#ifdef ColorTrianglePatch
Parse_Mesh_Texture(&t2,&t3);
#else
Parse_Mesh_Texture();
#endif
}
Parse_End();
END_CASE
#ifdef ColorTrianglePatch
/* [AP and NK] next CASE */
CASE(SMOOTH_COLOR_TRIANGLE_TOKEN)
Error("smooth_color_triangle discontinued. Use texture_list with three textures instead.\n");
END_CASE
/* [AP and NK] end CASE */
#endif
CASE(SMOOTH_TRIANGLE_TOKEN)
Parse_Begin();
Parse_Vector(P1); Parse_Comma();
Parse_Vector(N1); Parse_Comma();
Parse_Vector(P2); Parse_Comma();
Parse_Vector(N2); Parse_Comma();
Parse_Vector(P3); Parse_Comma();
Parse_Vector(N3);
VLength(l1, N1);
VLength(l2, N2);
VLength(l3, N3);
if ((l1 != 0.0) && (l2 != 0.0) && (l3 != 0.0) && (!Mesh_Degenerate(P1, P2, P3)))
{
if (number_of_triangles >= max_triangles)
{
if (max_triangles >= INT_MAX/2)
{
Error("Too many triangles in triangle mesh.\n");
}
max_triangles *= 2;
Triangles = (MESH_TRIANGLE *)POV_REALLOC(Triangles, max_triangles*sizeof(MESH_TRIANGLE), "triangle triangle mesh data");
}
VInverseScaleEq(N1, l1);
VInverseScaleEq(N2, l2);
VInverseScaleEq(N3, l3);
/* Init triangle. */
Init_Mesh_Triangle(&Triangles[number_of_triangles]);
Triangles[number_of_triangles].P1 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P1);
Triangles[number_of_triangles].P2 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P2);
Triangles[number_of_triangles].P3 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P3);
/* Check for equal normals. */
VSub(D1, N1, N2);
VSub(D2, N1, N3);
VDot(l1, D1, D1);
VDot(l2, D2, D2);
/* NK 1998 */
Parse_Three_UVCoords(UV1,UV2,UV3);
Triangles[number_of_triangles].UV1 = Mesh_Hash_UV(&number_of_uvcoords, &max_uvcoords, &UVCoords,UV1);
Triangles[number_of_triangles].UV2 = Mesh_Hash_UV(&number_of_uvcoords, &max_uvcoords, &UVCoords,UV2);
Triangles[number_of_triangles].UV3 = Mesh_Hash_UV(&number_of_uvcoords, &max_uvcoords, &UVCoords,UV3);
/* NK ---- */
#ifdef ColorTrianglePatch
/* NK */
/* read possibly three instead of only one texture */
/* read these before compute!!! */
t2 = t3 = NULL;
Triangles[number_of_triangles].Texture = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, Parse_Mesh_Texture(&t2,&t3));
if (t2) Triangles[number_of_triangles].Texture2 = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, t2);
if (t3) Triangles[number_of_triangles].Texture3 = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, t3);
if (t2 || t3) Triangles[number_of_triangles].ThreeTex = TRUE;
#endif
if ((fabs(l1) > EPSILON) || (fabs(l2) > EPSILON))
{
/* Smooth triangle. */
Triangles[number_of_triangles].N1 = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N1);
Triangles[number_of_triangles].N2 = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N2);
Triangles[number_of_triangles].N3 = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N3);
Compute_Mesh_Triangle(&Triangles[number_of_triangles], TRUE, P1, P2, P3, N);
}
else
{
/* Flat triangle. */
Compute_Mesh_Triangle(&Triangles[number_of_triangles], FALSE, P1, P2, P3, N);
}
Triangles[number_of_triangles].Normal_Ind = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N);
#ifndef ColorTrianglePatch
Triangles[number_of_triangles].Texture = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, Parse_Mesh_Texture());
#endif
if (Triangles[number_of_triangles].Texture < 0)
{
fully_textured = FALSE;
}
number_of_triangles++;
}
/* NK degenerate fix */
else
{
/* parse the uv and texture info - even though we'll just throw it
away. why? if not we get a parse error - we should just ignore the
degenerate triangle */
t2=t3=NULL;
Parse_Three_UVCoords(UV1,UV2,UV3);
#ifdef ColorTrianglePatch
Parse_Mesh_Texture(&t2,&t3);
#else
Parse_Mesh_Texture();
#endif
}
Parse_End();
END_CASE
/* NK 1998 */
CASE(INSIDE_VECTOR_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Parse_Vector(Inside_Vect);
END_CASE
/* NK ---- */
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
/* Destroy hash tables. */
Destroy_Mesh_Hash_Tables();
/* If there are no triangles something went wrong. */
if (number_of_triangles == 0)
{
Error("No triangles in triangle mesh.\n");
}
/* Init triangle mesh data. */
Object->Data = (MESH_DATA *)POV_MALLOC(sizeof(MESH_DATA), "triangle mesh data");
Object->Data->References = 1;
Object->Data->Tree = NULL;
/* NK 1998 */
/*YS* 31/12/1999 */
if( (fabs(Inside_Vect[X]) < EPSILON) && (fabs(Inside_Vect[Y]) < EPSILON) && (fabs(Inside_Vect[Z]) < EPSILON))
Object->has_inside_vector=FALSE;
else
{
VNormalize(Object->Data->Inside_Vect, Inside_Vect);
Object->has_inside_vector=TRUE;
}
/*YS*/
Object->Data->Normals = NULL;
Object->Textures = NULL;
Object->Data->Triangles = NULL;
Object->Data->Vertices = NULL;
/* Allocate memory for normals, textures, triangles and vertices. */
Object->Data->Number_Of_Normals = number_of_normals;
Object->Number_Of_Textures = number_of_textures;
Object->Data->Number_Of_Triangles = number_of_triangles;
Object->Data->Number_Of_Vertices = number_of_vertices;
Object->Data->Normals = (SNGL_VECT *)POV_MALLOC(number_of_normals*sizeof(SNGL_VECT), "triangle mesh data");
if (number_of_textures)
{
Set_Flag(Object, MULTITEXTURE_FLAG);
Object->Textures = (TEXTURE **)POV_MALLOC(number_of_textures*sizeof(TEXTURE *), "triangle mesh data");
}
Object->Data->Triangles = (MESH_TRIANGLE *)POV_MALLOC(number_of_triangles*sizeof(MESH_TRIANGLE), "triangle mesh data");
Object->Data->Vertices = (SNGL_VECT *)POV_MALLOC(number_of_vertices*sizeof(SNGL_VECT), "triangle mesh data");
/* Copy normals, textures, triangles and vertices into mesh. */
for (i = 0; i < number_of_normals; i++)
{
Assign_SNGL_Vect(Object->Data->Normals[i], Normals[i]);
}
for (i = 0; i < number_of_textures; i++)
{
Object->Textures[i] = Copy_Textures(Textures[i]);
/* now free the texture, in order to decrement the reference count */
Destroy_Textures(Textures[i]);
}
if (fully_textured)
{
Object->Type |= TEXTURED_OBJECT;
}
for (i = 0; i < number_of_triangles; i++)
{
Object->Data->Triangles[i] = Triangles[i];
}
for (i = 0; i < number_of_vertices; i++)
{
Assign_SNGL_Vect(Object->Data->Vertices[i], Vertices[i]);
}
/* NK 1998 */
/* do the four steps above, but for UV coordinates*/
Object->Data->UVCoords = NULL;
Object->Data->Number_Of_UVCoords = number_of_uvcoords;
Object->Data->UVCoords = (UV_VECT *)POV_MALLOC(number_of_uvcoords*sizeof(UV_VECT), "triangle mesh data");
for (i = 0; i < number_of_uvcoords; i++)
{
Assign_UV_Vect(Object->Data->UVCoords[i], UVCoords[i]);
}
POV_FREE(UVCoords);
/* NK ---- */
/* Free temporary memory. */
POV_FREE(Normals);
POV_FREE(Textures);
POV_FREE(Triangles);
POV_FREE(Vertices);
/*
Render_Info("Mesh: %ld bytes: %ld vertices, %ld normals, %ld textures, %ld triangles\n",
Object->Data->Number_Of_Normals*sizeof(SNGL_VECT)+
Object->Data->Number_Of_Textures*sizeof(TEXTURE *)+
Object->Data->Number_Of_Triangles*sizeof(MESH_TRIANGLE)+
Object->Data->Number_Of_Vertices*sizeof(SNGL_VECT),
Object->Data->Number_Of_Vertices,
Object->Data->Number_Of_Normals,
Object->Data->Number_Of_Textures,
Object->Data->Number_Of_Triangles);
*/
/* Create bounding box. */
Compute_Mesh_BBox(Object);
/* Parse object modifiers. */
Parse_Object_Mods((OBJECT *)Object);
/* Create bounding box tree. */
Build_Mesh_BBox_Tree(Object);
return((OBJECT *)Object);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Mesh2
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* OBJECT
*
* AUTHOR
*
* Nathan Kopp
*
* DESCRIPTION
*
* Read a triangle mesh - syntax version 2.
*
* CHANGES
*
* Feb 1998 : Creation.
*
******************************************************************************/
static OBJECT *Parse_Mesh2()
{
int i;
int number_of_normals, number_of_textures, number_of_triangles, number_of_vertices, number_of_uvcoords;
int number_of_normal_indices;
int a,b,c;
int n1, n2, n3;
int found_normal_indices = 0;
int found_uv_indices = 0;
DBL l1, l2;
VECTOR D1, D2, P1, P2, P3, N1, N;
VECTOR Inside_Vect;
UV_VECT UV1;
SNGL_VECT *Normals = NULL;
SNGL_VECT *Vertices = NULL;
TEXTURE **Textures = NULL;
UV_VECT *UVCoords = NULL;
MESH *Object;
MESH_TRIANGLE *Triangles;
Make_Vector(Inside_Vect, 0, 0, 0);
Parse_Begin();
if ((Object = (MESH *)Parse_Object_Id()) != NULL)
return((OBJECT *)Object);
/* Create object. */
Object = Create_Mesh();
/* normals, uvcoords, and textures are optional */
number_of_vertices = 0;
number_of_uvcoords = 0;
number_of_textures = 0;
number_of_normals = 0;
number_of_normal_indices = 0;
/* ----------------- Get the Normals & UV Vectors & Textures ------------ */
EXPECT
/* ------------------- Get the Vertices ------------------- */
CASE(VERTEX_VECTORS_TOKEN)
Parse_Begin();
number_of_vertices = (int)Parse_Float(); Parse_Comma();
if (number_of_vertices<=0)
Error("No vertices in triangle mesh.\n");
/* allocate memory for vertices */
Vertices = (SNGL_VECT *)POV_MALLOC(number_of_vertices*sizeof(SNGL_VECT), "triangle mesh data");
for(i=0; i<number_of_vertices; i++)
{
Parse_Vector(P1); Parse_Comma();
Assign_SNGL_Vect(Vertices[i], P1);
}
Parse_End();
END_CASE
CASE(NORMAL_VECTORS_TOKEN)
Parse_Begin();
number_of_normals = (int)Parse_Float(); Parse_Comma();
if (number_of_normals>0)
{
Normals = (SNGL_VECT *)POV_MALLOC(number_of_normals*sizeof(SNGL_VECT), "triangle mesh data");
/* leave space in the array for the raw triangle normals */
for(i=0; i<number_of_normals; i++)
{
Parse_Vector(N1); Parse_Comma();
VNormalizeEq(N1);
Assign_SNGL_Vect(Normals[i], N1);
}
}
Parse_End();
END_CASE
CASE(UV_VECTORS_TOKEN)
Parse_Begin();
number_of_uvcoords = (int)Parse_Float(); Parse_Comma();
if (number_of_uvcoords>0)
{
UVCoords = (UV_VECT *)POV_MALLOC(number_of_uvcoords*sizeof(UV_VECT), "triangle mesh data");
for(i=0; i<number_of_uvcoords; i++)
{
Parse_UV_Vect(UV1); Parse_Comma();
Assign_UV_Vect(UVCoords[i], UV1);
}
}
Parse_End();
END_CASE
/*OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
EXPECT*/
CASE(TEXTURE_LIST_TOKEN)
Parse_Begin();
number_of_textures = (int)Parse_Float(); Parse_Comma();
if (number_of_textures>0)
{
Textures = (TEXTURE **)POV_MALLOC(number_of_textures*sizeof(TEXTURE *), "triangle mesh data");
for(i=0; i<number_of_textures; i++)
{
/*
GET(TEXTURE_ID_TOKEN)
Textures[i] = Copy_Texture_Pointer((TEXTURE *)Token.Data);
*/
GET(TEXTURE_TOKEN);
Parse_Begin();
Textures[i] = Parse_Texture();
Parse_End();
Parse_Comma();
}
}
Parse_End();
EXIT
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
if (number_of_vertices == 0)
Error("Vertex vectors not found in mesh2\n");
/* first make sure we at least have one UV coordinate */
if (number_of_uvcoords == 0)
{
number_of_uvcoords = 1;
UVCoords = (UV_VECT *)POV_MALLOC(number_of_uvcoords*sizeof(UV_VECT), "triangle mesh data");
UVCoords[0][U] = 0;
UVCoords[0][V] = 0;
}
/* ------------------- Get the Faces ------------------- */
GET(FACE_INDICES_TOKEN)
Parse_Begin();
/* number faces is mandatory, so we ask how many there are */
number_of_triangles = (int)Parse_Float(); Parse_Comma();
if (number_of_triangles == 0)
{
Error("No triangles in triangle mesh.");
}
/* allocate memory for triangles */
Triangles = (MESH_TRIANGLE *)POV_MALLOC(number_of_triangles*sizeof(MESH_TRIANGLE), "triangle mesh data");
/* start reading triangles */
for(i=0; i<number_of_triangles; i++)
{
/* read in the indices vector */
Parse_Vector(P1); Parse_Comma();
/* convert the vector to integers */
a = (int)P1[X];
b = (int)P1[Y];
c = (int)P1[Z];
/* a--;b--;c--; use this to start external stuff at 1 */
if ( a<0 || b<0 || c<0 ||
a>=number_of_vertices || b>=number_of_vertices ||
c>=number_of_vertices)
{
Error("Mesh face index out of range.");
}
/* Init triangle. */
Init_Mesh_Triangle(&Triangles[i]);
/* assign the vertices */
Triangles[i].P1 = a;
Triangles[i].P2 = b;
Triangles[i].P3 = c;
/* look for a texture index */
EXPECT
CASE_FLOAT
Triangles[i].Texture = (int)Parse_Float(); Parse_Comma();
if (Triangles[i].Texture >= number_of_textures ||
Triangles[i].Texture < 0)
Error("Texture index out of range in mesh2.");
EXIT
END_CASE
OTHERWISE
Triangles[i].Texture = -1;
EXIT
UNGET
END_CASE
END_EXPECT
/* look for a texture index */
EXPECT
CASE_FLOAT
Triangles[i].Texture2 = (int)Parse_Float(); Parse_Comma();
if (Triangles[i].Texture2 >= number_of_textures ||
Triangles[i].Texture2 < 0)
Error("Texture index out of range in mesh2.");
Triangles[i].ThreeTex = TRUE;
EXIT
END_CASE
OTHERWISE
Triangles[i].Texture2 = -1;
EXIT
UNGET
END_CASE
END_EXPECT
/* look for a texture index */
EXPECT
CASE_FLOAT
Triangles[i].Texture3 = (int)Parse_Float(); Parse_Comma();
if (Triangles[i].Texture3 >= number_of_textures ||
Triangles[i].Texture3 < 0)
Error("Texture index out of range in mesh2.");
Triangles[i].ThreeTex = TRUE;
EXIT
END_CASE
OTHERWISE
Triangles[i].Texture3 = -1;
EXIT
UNGET
END_CASE
END_EXPECT
}
Parse_End();
/* now we get the uv_indices & normal_indices in either order */
EXPECT
CASE(UV_INDICES_TOKEN)
if (found_uv_indices)
{
Error("Only one uv_indices section is allowed in mesh2\n");
}
found_uv_indices = 1;
Parse_Begin();
if (Parse_Float() != number_of_triangles)
Error("Number of uv indices must equal number of faces.");
Parse_Comma();
for (i=0; i<number_of_triangles; i++)
{
/* read in the indices vector */
Parse_Vector(P1); Parse_Comma();
/* convert the vector to integers */
a = (int)P1[X];
b = (int)P1[Y];
c = (int)P1[Z];
/* a--;b--;c--; use this to start external stuff at 1 */
if ( a<0 || b<0 || c<0 ||
a>=number_of_uvcoords || b>=number_of_uvcoords ||
c>=number_of_uvcoords)
{
Error("Mesh UV index out of range.");
}
/* assign the uv coordinate */
Triangles[i].UV1 = a;
Triangles[i].UV2 = b;
Triangles[i].UV3 = c;
}
Parse_End();
/*EXIT*/
END_CASE
/*
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
EXPECT
*/
CASE(NORMAL_INDICES_TOKEN)
if (found_normal_indices)
{
Error("Only one normal_indices section is allowed in mesh2\n");
}
found_normal_indices = 1;
Parse_Begin();
/*
Change - if fewer normals than triangles, then no problem - the
rest will be flat triangles.
if (Parse_Float() != number_of_triangles)
Error("Number of normal indices must equal number of faces.");
*/
number_of_normal_indices = (int)Parse_Float();
if (number_of_normal_indices > number_of_triangles)
Error("Number of normal indices cannot be more than the number of faces.");
Parse_Comma();
for (i=0; i<number_of_normal_indices; i++)
{
/* read in the indices vector */
Parse_Vector(P1); Parse_Comma();
/* convert the vector to integers */
a = (int)P1[X];
b = (int)P1[Y];
c = (int)P1[Z];
/* a--;b--;c--; use this to start external stuff at 1 */
if ( a<0 || b<0 ||
c<0 ||
a>=number_of_normals || b>=number_of_normals ||
c>=number_of_normals)
{
Error("Mesh normal index out of range.");
}
/* assign the uv coordinate */
Triangles[i].N1 = a;
Triangles[i].N2 = b;
Triangles[i].N3 = c;
}
Parse_End();
/*EXIT*/
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
/* ----------------------------------------------------- */
/* ----------------------------------------------------- */
EXPECT
CASE(INSIDE_VECTOR_TOKEN)
Parse_Vector(Inside_Vect);
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
if (!found_uv_indices)
{
if (number_of_uvcoords==number_of_vertices)
{
for (i=0; i<number_of_triangles; i++)
{
Triangles[i].UV1 = Triangles[i].P1;
Triangles[i].UV2 = Triangles[i].P2;
Triangles[i].UV3 = Triangles[i].P3;
}
}
else if (number_of_uvcoords==1)
{
for (i=0; i<number_of_triangles; i++)
{
Triangles[i].UV1 = 0;
Triangles[i].UV2 = 0;
Triangles[i].UV3 = 0;
}
}
else
{
Error("Missing uv_indicies section in mesh2.");
}
}
if (!found_normal_indices)
{
if (number_of_normals==number_of_vertices)
{
/* If number of normals matches number of vertices, then assume
that the normal_indices are the same as the triangle indices
(left out for file size reasons).
So, we pretend that we read in some normal_indices
*/
number_of_normal_indices = number_of_triangles;
for (i=0; i<number_of_triangles; i++)
{
Triangles[i].N1 = Triangles[i].P1;
Triangles[i].N2 = Triangles[i].P2;
Triangles[i].N3 = Triangles[i].P3;
}
}
else if (number_of_normals)
{
Error("Missing normal_indicies section in mesh2.");
}
}
/* ---------------- Compute Triangle Normals ---------------- */
/* reallocate the normals stuff */
if (!number_of_normals)
Normals = (SNGL_VECT *)POV_MALLOC(number_of_triangles*sizeof(SNGL_VECT), "triangle mesh data");
else
Normals = (SNGL_VECT *)POV_REALLOC(Normals, (number_of_normals+number_of_triangles)*sizeof(SNGL_VECT), "triangle mesh data");
for (i=0; i<number_of_triangles; i++)
{
a = Triangles[i].P1;
b = Triangles[i].P2;
c = Triangles[i].P3;
n1 = Triangles[i].N1;
n2 = Triangles[i].N2;
n3 = Triangles[i].N3;
Assign_SNGL_Vect(P1, Vertices[a]);
Assign_SNGL_Vect(P2, Vertices[b]);
Assign_SNGL_Vect(P3, Vertices[c]);
Triangles[i].Smooth = FALSE;
/* compute the normal (check for smoothness) */
/* if number_of_normal_indices > 0, then the first triangles
are smooth and the rest are flat */
if (i<number_of_normal_indices)
{
/* Check for equal normals. */
VSub(D1, Normals[n1], Normals[n2]);
VSub(D2, Normals[n1], Normals[n3]);
VDot(l1, D1, D1);
VDot(l2, D2, D2);
if ((fabs(l1) > EPSILON) || (fabs(l2) > EPSILON))
{
/* Smooth triangle. */
Compute_Mesh_Triangle(&Triangles[i], TRUE, P1, P2, P3, N);
Triangles[i].Smooth = TRUE;
}
else
{
/* Flat triangle. */
Compute_Mesh_Triangle(&Triangles[i], FALSE, P1, P2, P3, N);
}
}
else
{
/* Flat triangle. */
Compute_Mesh_Triangle(&Triangles[i], FALSE, P1, P2, P3, N);
}
/* assign the triangle normal that we just computed */
Triangles[i].Normal_Ind = i+number_of_normals;
Assign_SNGL_Vect(Normals[i+number_of_normals], N);
}
/* now remember how many normals we really have */
number_of_normals += number_of_triangles;
/* ----------------------------------------------------- */
/* Init triangle mesh data. */
Object->Data = (MESH_DATA*)POV_MALLOC(sizeof(MESH_DATA), "triangle mesh data");
Object->Data->References = 1;
Object->Data->Tree = NULL;
/* NK 1998 */
/*YS* 31/12/1999 */
if( (fabs(Inside_Vect[X]) < EPSILON) && (fabs(Inside_Vect[Y]) < EPSILON) && (fabs(Inside_Vect[Z]) < EPSILON))
Object->has_inside_vector=FALSE;
else
{
VNormalize(Object->Data->Inside_Vect, Inside_Vect);
Object->has_inside_vector=TRUE;
}
/*YS*/
/* copy pointers to normals, triangles, textures, and vertices. */
Object->Data->Normals = Normals;
Object->Data->Triangles = Triangles;
Object->Data->Vertices = Vertices;
Object->Data->UVCoords = UVCoords;
Object->Textures = Textures;
/* copy number of for normals, textures, triangles and vertices. */
Object->Data->Number_Of_Normals = number_of_normals;
Object->Data->Number_Of_Triangles = number_of_triangles;
Object->Data->Number_Of_Vertices = number_of_vertices;
Object->Data->Number_Of_UVCoords = number_of_uvcoords;
Object->Number_Of_Textures = number_of_textures;
if (number_of_textures)
{
Set_Flag(Object, MULTITEXTURE_FLAG);
}
/* Create bounding box. */
Compute_Mesh_BBox(Object);
/* Parse object modifiers. */
Parse_Object_Mods((OBJECT *)Object);
/* Create bounding box tree. */
Build_Mesh_BBox_Tree(Object);
/*
Render_Info("Mesh2: %ld bytes: %ld vertices, %ld normals, %ld textures, %ld triangles\n",
Object->Data->Number_Of_Normals*sizeof(SNGL_VECT)+
Object->Data->Number_Of_Textures*sizeof(TEXTURE *)+
Object->Data->Number_Of_Triangles*sizeof(MESH_TRIANGLE)+
Object->Data->Number_Of_Vertices*sizeof(SNGL_VECT),
Object->Data->Number_Of_Vertices,
Object->Data->Number_Of_Normals,
Object->Data->Number_Of_Textures,
Object->Data->Number_Of_Triangles);
*/
return((OBJECT *)Object);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static
OBJECT *Parse_Poly (int order)
{
POLY *Object;
Parse_Begin ();
if ( (Object = (POLY *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
if (order == 0)
{
order = (int)Parse_Float(); Parse_Comma();
if (order < 2 || order > MAX_ORDER)
Error("Order of poly is out of range.");
}
Object = Create_Poly(order);
Parse_Coeffs(Object->Order, &(Object->Coeffs[0]));
Compute_Poly_BBox(Object);
Parse_Object_Mods ((OBJECT *)Object);
return ((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
#ifdef RBezierPatch
static void bicubic_patch_warning(BICUBIC_PATCH *Object, char flag)
{
if ( flag ^ ((Object->Patch_Type == BEZIER_NSK) || (Object->Patch_Type == RATIONAL_BEZIER_NSK)))
Warn(150, "This parameter is useless with current bicubic type");
}
#endif
static
OBJECT *Parse_Bicubic_Patch ()
{
BICUBIC_PATCH *Object;
#ifdef RBezierPatch
DBL hvector[4];
#endif
int i, j;
Parse_Begin ();
if ( (Object = (BICUBIC_PATCH *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
Object = Create_Bicubic_Patch();
EXPECT
CASE_FLOAT
Warn(150, "Should use keywords for bicubic parameters.");
Object->Patch_Type = (int)Parse_Float();
if (Object->Patch_Type == 2 ||
Object->Patch_Type == 3)
Object->Flatness_Value = Parse_Float();
else
Object->Flatness_Value = 0.1;
Object->U_Steps = (int)Parse_Float();
Object->V_Steps = (int)Parse_Float();
EXIT
END_CASE
CASE (TYPE_TOKEN)
Object->Patch_Type = (int)Parse_Float();
END_CASE
CASE (FLATNESS_TOKEN)
#ifdef RBezierPatch
bicubic_patch_warning( Object, 0 );
#endif
Object->Flatness_Value = Parse_Float();
END_CASE
CASE (V_STEPS_TOKEN)
#ifdef RBezierPatch
bicubic_patch_warning( Object, 0 );
#endif
Object->V_Steps = (int)Parse_Float();
END_CASE
CASE (U_STEPS_TOKEN)
#ifdef RBezierPatch
bicubic_patch_warning( Object, 0 );
#endif
Object->U_Steps = (int)Parse_Float();
END_CASE
#ifdef RBezierPatch
CASE (ACCURACY_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
bicubic_patch_warning( Object, 1 );
Object->accuracy = Parse_Float();
END_CASE
#endif
/*YS Moved parsing of the uv_vectors after parsing of the control points
to be consistent with triangle mesh */
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
#ifdef RBezierPatch
if (Object->Patch_Type >= MAX_PATCH_TYPE)
#else
if (Object->Patch_Type > 1)
#endif
{
Object->Patch_Type = 1;
Warn(0, "Patch type no longer supported. Using type 1.");
}
if ((Object->Patch_Type < 0) || (Object->Patch_Type > MAX_PATCH_TYPE))
Error("Undefined bicubic patch type.");
Parse_Comma();
#ifdef RBezierPatch
if (Object->Patch_Type == RATIONAL_BEZIER_NSK)
{
Object->Weights= (WEIGHTS*)POV_MALLOC( sizeof(WEIGHTS), "bicubic patch");
}
#endif
for (i=0;i<4;i++)
for (j=0;j<4;j++)
{
#ifdef RBezierPatch
if (Object->Patch_Type != RATIONAL_BEZIER_NSK)
#endif
Parse_Vector(Object->Control_Points[i][j]);
#ifdef RBezierPatch
else
{
Parse_RBezierPatchVector4D(hvector);
Object->Control_Points[i][j][X]= hvector[X];
Object->Control_Points[i][j][Y]= hvector[Y];
Object->Control_Points[i][j][Z]= hvector[Z];
(*(Object->Weights))[i][j]= hvector[3];
}
#endif
if (!((i==3)&&(j==3)))
Parse_Comma();
}
/*YS Moved parsing of the uv_vectors to here
to be consistent with triangle mesh */
EXPECT
CASE_FLOAT
/* NK 1998 */
CASE(UV_VECTORS_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
#ifndef UpdatedUVMappingPatch
/* syntax is Start, End but we want to store it as */
/* Start & (End-Start) for speed reasons */
Parse_UV_Vect(Object->UV_Start); Parse_Comma();
Parse_UV_Vect(Object->UV_Diff);
/* right now UV_Diff is holding UV_End, so we need to change that */
Object->UV_Diff[U] = Object->UV_Diff[U] - Object->UV_Start[U];
Object->UV_Diff[V] = Object->UV_Diff[V] - Object->UV_Start[V];
#else
/* altered by MH 2000. Store 4 ST coords for quadrilateral */
Parse_UV_Vect(Object->ST[0]); Parse_Comma();
Parse_UV_Vect(Object->ST[1]); Parse_Comma();
Parse_UV_Vect(Object->ST[2]); Parse_Comma();
Parse_UV_Vect(Object->ST[3]);
/*YS sept 17 2000 Moved MSquareQuad() to here for better error handling
see function MSquareQuad() for more info
/*YS*/
#endif
EXIT
END_CASE
/* NK ---- */
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
/* MH
Might want to skip the following if not using uv mapping
for speed reasons - I put it here to make sure it gets done for now*/
MSquareQuad(Object->ST, Object->Mapping); /* mapping matrix */
/* MH */
Precompute_Patch_Values(Object); /* interpolated mesh coords */
Compute_Bicubic_Patch_BBox(Object);
Parse_Object_Mods ((OBJECT *)Object);
return ((OBJECT *) Object);
}
#ifdef RBezierPatch
/***************************************************
RBezier & Parse_Trims
**************************************************/
static TRIM_SHAPE *Parse_Trim(void)
{
TRIM_SHAPE *trim;
DBL u[TRIM_MAX_CONST], v[TRIM_MAX_CONST], w[TRIM_MAX_CONST];
char ttypes[TRIM_MAX_CONST];
int uvnum=0,
wnum=0,
tnum=0,
tmp, rat, ord;
VECTOR vec;
char skip, copy, ctmp;
Parse_Begin();
Get_Token();
if (Token.Token_Id == TRIMMED_BY_ID_TOKEN)
{
trim= (TRIM_SHAPE *) Token.Data;
copy=0;
EXPECT
CASE (TYPE_TOKEN)
if (copy==0) { copy=1; trim= trim_deep_copy(trim); }
trim-> ttype= ctmp= Parse_Float();
if ((ctmp!=0)&&(ctmp!=1)) Error("Wrong trim type");
END_CASE
CASE (SCALE_TOKEN)
if (copy==0) { copy=1; trim= trim_deep_copy(trim); }
Parse_UV_Vect( vec );
trim_scale_cp( vec, trim->u, trim->v, trim->num_of_cp );
END_CASE
CASE (ROTATE_TOKEN)
if (copy==0) { copy=1; trim= trim_deep_copy(trim); }
vec[0]= Parse_Float();
trim_rotate_cp( vec[0], trim->u, trim->v, trim->num_of_cp );
END_CASE
CASE (TRANSLATE_TOKEN)
if (copy==0) { copy=1; trim= trim_deep_copy(trim); }
Parse_UV_Vect( vec );
trim_translate_cp( vec, trim->u, trim->v, trim->num_of_cp );
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
if (copy==0)
trim= Copy_Trim(trim);
else
trim_compute_bounds( trim );
Parse_End();
return trim;
}
trim=(TRIM_SHAPE*) POV_MALLOC( sizeof(TRIM_SHAPE), "trimmig shape");
trim->refs= 1;
trim->ttype= 0;
if (Token.Token_Id == TYPE_TOKEN)
{
trim->ttype=tmp= Parse_Float();
if ((tmp != 0) && (tmp!=1))
Error("Wrong trim type");
}
else
Unget_Token();
EXPECT
CASE_FLOAT
ord= Parse_Float();
if ((ord < 2)||(ord>4))
Error("Trimming shape: wrong number of control points");
rat= 0;
if (ord != 2)
{
Get_Token();
if (Token.Token_Id == RATIONAL_TOKEN) rat= 1;
else Unget_Token();
}
for (tmp = 0; tmp < ord; tmp ++)
{
skip= 0;
Get_Token();
if ((Token.Token_Id==FIRST_TOKEN) && (uvnum != 0))
{
skip=1; vec[0]= u[0]; vec[1]= v[0];
}
if ((Token.Token_Id==PREVIOUS_TOKEN) && (tmp==0) && (uvnum !=0))
{
skip=1; vec[0]= u[uvnum-1]; vec[1]= v[uvnum-1];
}
if ((skip != 0) && (rat!=0))
{
Parse_Comma();
w[wnum++]= Parse_Float();
}
if (skip==0)
{
Unget_Token();
if (rat)
{
Parse_Vector(vec);
w[wnum++]= vec[2];
}
else
Parse_UV_Vect(vec);
}
if ((tmp != 0) || (uvnum==0))
{
u[uvnum]= vec[0];
v[uvnum]= vec[1];
uvnum++;
}
else
if ((vec[0]!=u[uvnum-1])||(vec[1]!=v[uvnum-1])) /* connect with last point by line */
{
u[uvnum]= vec[0];
v[uvnum]= vec[1];
uvnum++;
ttypes[tnum++]= 2;
}
if (tmp!= ord -1) Parse_Comma();
}
ttypes[tnum++]= ord | ( rat << 4);
END_CASE
CASE (SCALE_TOKEN)
Parse_UV_Vect( vec );
trim_scale_cp( vec, u,v, uvnum );
END_CASE
CASE (ROTATE_TOKEN)
vec[0]= Parse_Float();
trim_rotate_cp( vec[0], u,v,uvnum);
END_CASE
CASE (TRANSLATE_TOKEN)
Parse_UV_Vect( vec );
trim_translate_cp( vec, u,v, uvnum );
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
if ((u[uvnum-1] != u[0])||(v[uvnum-1] != v[0]))
{ /* connect last & first poit */
u[uvnum]= u[0];
v[uvnum]= v[0];
uvnum++;
ttypes[tnum++]= 2;
}
tmp= sizeof(DBL)*(uvnum*2 + wnum) + sizeof(char)*tnum;
trim->v= trim->u= (DBL *) POV_MALLOC( tmp, "trimming shape");
trim->w= trim->v+= uvnum;
trim->w+=uvnum;
trim->ctypes= (char *) (trim->w + wnum);
trim-> num_of_parts= tnum;
trim-> num_of_cp= uvnum;
memcpy (trim->u, u, sizeof(DBL) * uvnum);
memcpy (trim->v, v, sizeof(DBL) * uvnum);
if (wnum)
memcpy(trim->w, w, sizeof(DBL) * wnum);
memcpy(trim->ctypes, ttypes, sizeof(char)*tnum);
trim_compute_bounds( trim );
Parse_End();
return trim;
}
static
OBJECT *Parse_RBezier_Patch(void)
{
RBEZIER_PATCH *Object;
int i, j, rat=0;
DBL hvector[4];
TRIM_SHAPE *(trims[TRIM_MAX_CONST]);
int noft=0;
Parse_Begin();
if ( (Object = (RBEZIER_PATCH *) Parse_Object_Id ()) != NULL)
return ((OBJECT *) Object);
Object = Create_RBezier_Patch();
Object-> u_order= (int) Parse_Float(); Parse_Comma();
Object-> v_order= (int) Parse_Float();
if ((Object-> u_order < 2 ) || (Object-> u_order > 4) ||
(Object-> v_order < 2 ) || (Object-> v_order > 4))
Error("Wrong number of control points");
EXPECT
#ifdef DEBUG_RBEZIER
CASE (DEBUG_TOKEN)
Object->debug=1;
END_CASE
#endif
CASE (RATIONAL_TOKEN)
rat=1;
END_CASE
CASE (ACCURACY_TOKEN)
Object-> accuracy = Parse_Float();
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Object-> Points= (DBL *) POV_MALLOC( sizeof(DBL) * 3 * 4 * (Object->v_order), "bezier patch");
for (i=0; i < 4 * 3 * (Object->v_order); Object->Points[i]=0.0, i++);
Object->pts[X]= Object->Points;
Object->pts[Y]= &(Object->Points[4*Object->v_order]);
Object->pts[Z]= &(Object->Points[2*4*Object->v_order]);
if (rat)
Object-> Weights= (DBL *) POV_MALLOC( sizeof(DBL) * 4 * (Object->v_order), "bezier patch");
for (i=0; i < Object->v_order ; i++)
for (j=0; j < Object->u_order; j++)
{
if (!rat)
{
Parse_Vector( hvector );
Object->Points[ 4*X*(Object->v_order) + 4*i + j] = hvector[X];
Object->Points[ 4*Y*(Object->v_order) + 4*i + j] = hvector[Y];
Object->Points[ 4*Z*(Object->v_order) + 4*i + j] = hvector[Z];
}
else
{
Parse_Vector4D(hvector);
Object->Points[ 4*X*(Object->v_order) + 4*i + j] = hvector[X];
Object->Points[ 4*Y*(Object->v_order) + 4*i + j] = hvector[Y];
Object->Points[ 4*Z*(Object->v_order) + 4*i + j] = hvector[Z];
Object->Weights[4*i+j]= hvector[3];
}
if ((i!= Object->v_order-1) || (j!=Object->u_order))
Parse_Comma();
}
EXPECT
CASE (TRIMMED_BY_TOKEN)
trims[noft]= Parse_Trim();
noft++;
if (noft == TRIM_MAX_CONST)
Error("To many trims");
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
if (noft != 0)
{
Object->trims= (TRIM_SHAPE **) POV_MALLOC( noft * sizeof(TRIM_SHAPE *), "trimming curves");
memcpy( Object->trims, trims, noft * sizeof(TRIM_SHAPE *));
Object-> num_of_trims= noft;
}
Compute_RBezier_Patch_BBox(Object);
Parse_Object_Mods ((OBJECT *) Object);
#ifdef DEBUG_RBEZIER
if (Object->debug)
Warn(0,"You enabled debugging code in RBezier patch. Intersection will be performed only if dirrection of ray is Z");
#endif
return ((OBJECT *) Object);
}
#endif
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static
OBJECT *Parse_TrueType ()
{
OBJECT *Object;
char *filename, *text_string;
DBL depth;
VECTOR offset;
TRANSFORM Local_Trans;
#ifdef FontAnlignmentPatch
int position=0;
#endif
Parse_Begin ();
GET(TTF_TOKEN);
if ( (Object = (OBJECT *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
Object = (OBJECT *)Create_CSG_Union ();
/*** Object = Create_TTF(); */
/* Parse the TrueType font file name */
filename = Parse_String();
Parse_Comma();
/* Parse the text string to be rendered */
text_string = Parse_String();
Parse_Comma();
/* Get the extrusion depth */
depth = Parse_Float(); Parse_Comma ();
/* Get the offset vector */
Parse_Vector(offset);
#ifdef FontAnlignmentPatch
position = 0; /* default to left-justified */
EXPECT
CASE (ALIGN_LEFT_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
position =0;
END_CASE
CASE(ALIGN_RIGHT_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
position = 2;
END_CASE
CASE(ALIGN_CENTER_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
position = 1;
END_CASE
CASE (POSITION_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
position = Parse_Float();
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
/* Process all this good info */
ProcessNewTTF((OBJECT *)Object, filename, text_string, depth, offset, position );
#else
/* Process all this good info */
ProcessNewTTF((OBJECT *)Object, filename, text_string, depth, offset);
#endif
/* Free up the filename and text string memory */
POV_FREE (filename);
POV_FREE (text_string);
/**** Compute_TTF_BBox(Object); */
Compute_CSG_BBox((OBJECT *)Object);
/* This tiny rotation should fix cracks in text that lies along an axis */
Make_Vector(offset, 0.001, 0.001, 0.001);
Compute_Rotation_Transform(&Local_Trans, offset);
Rotate_Object ((OBJECT *)Object, offset, &Local_Trans);
/* Get any rotate/translate or texturing stuff */
Parse_Object_Mods ((OBJECT *)Object);
return ((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Sphere_Sweep
*
* INPUT
*
* -
*
* OUTPUT
*
* -
*
* RETURNS
*
* Object
*
* AUTHOR
*
* Jochen Lippert
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static OBJECT *Parse_Sphere_Sweep()
{
SPHERE_SWEEP *Object;
int i;
Parse_Begin();
if ((Object = (SPHERE_SWEEP *)Parse_Object_Id()) != NULL)
{
return ((OBJECT *) Object);
}
Object = Create_Sphere_Sweep();
/* Get type of interpolation */
EXPECT
CASE(LINEAR_SPHERE_SWEEP_TOKEN)
Object->Interpolation = LINEAR_SPHERE_SWEEP;
EXIT
END_CASE
CASE(CATMULL_ROM_SPLINE_SPHERE_SWEEP_TOKEN)
Object->Interpolation = CATMULL_ROM_SPLINE_SPHERE_SWEEP;
EXIT
END_CASE
CASE(B_SPLINE_SPHERE_SWEEP_TOKEN)
Object->Interpolation = B_SPLINE_SPHERE_SWEEP;
EXIT
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
if (Object->Interpolation == -1)
{
Error("Invalid type of interpolation.");
}
Parse_Comma();
/* Get number of modeling spheres */
Object->Num_Modeling_Spheres = (int)Parse_Float();
Object->Modeling_Sphere =
(SPHSWEEP_SPH *)POV_MALLOC(Object->Num_Modeling_Spheres * sizeof(SPHSWEEP_SPH),
"sphere sweep modeling spheres");
for (i = 0; i < Object->Num_Modeling_Spheres; i++)
{
Parse_Comma();
Parse_Vector(Object->Modeling_Sphere[i].Center);
Parse_Comma();
Object->Modeling_Sphere[i].Radius = Parse_Float();
}
EXPECT
CASE(SPHERE_SWEEP_DEPTH_TOLERANCE_TOKEN)
Object->Depth_Tolerance = Parse_Float();
EXIT
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Compute_Sphere_Sweep(Object);
Compute_Sphere_Sweep_BBox(Object);
Parse_Object_Mods((OBJECT *)Object);
return ((OBJECT *)Object);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static
OBJECT *Parse_CSG (int CSG_Type)
{
CSG *Object;
OBJECT *Local;
int Object_Count = 0;
int Light_Source_Union = TRUE;
Parse_Begin ();
if ( (Object = (CSG *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
if (CSG_Type & CSG_UNION_TYPE)
Object = Create_CSG_Union ();
else
if (CSG_Type & CSG_MERGE_TYPE)
Object = Create_CSG_Merge ();
else
Object = Create_CSG_Intersection ();
Object->Children = NULL;
while ((Local = Parse_Object ()) != NULL)
{
if ((CSG_Type & CSG_INTERSECTION_TYPE) && (Local->Type & PATCH_OBJECT))
Warn(0, "Patch objects not allowed in intersection.");
Object_Count++;
if ((CSG_Type & CSG_DIFFERENCE_TYPE) && (Object_Count > 1))
Invert_Object (Local);
Object->Type |= (Local->Type & CHILDREN_FLAGS);
if (!(Local->Type & LIGHT_SOURCE_OBJECT))
{
Light_Source_Union = FALSE;
}
Local->Type |= IS_CHILD_OBJECT;
Link(Local, &Local->Sibling, &Object->Children);
};
if (Light_Source_Union)
{
Object->Type |= LT_SRC_UNION_OBJECT;
}
if ((Object_Count < 2) && (opts.Language_Version >= 150))
Warn(150, "Should have at least 2 objects in csg.");
Compute_CSG_BBox((OBJECT *)Object);
Parse_Object_Mods ((OBJECT *)Object);
return ((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static OBJECT *Parse_Light_Source ()
{
DBL Len;
VECTOR Local_Vector;
MATRIX Local_Matrix;
TRANSFORM Local_Trans;
LIGHT_SOURCE *Object;
/* NK phmap */
BLEND_MAP *Map;
SNGL Value;
int i;
/* NK ---- */
Parse_Begin ();
if ( (Object = (LIGHT_SOURCE *)Parse_Object_Id()) != NULL)
return ((OBJECT *) Object);
Object = Create_Light_Source ();
Parse_Vector(Object->Center);
Parse_Comma();
Parse_Colour (Object->Colour);
EXPECT
/* NK phmap */
CASE (COLOUR_MAP_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Destroy_Blend_Map(Object->blend_map);
Map = Object->blend_map = Parse_Colour_Map ();
Make_Colour(Object->Colour, 0, 0, 0);
for (i = 0; i < Map->Number_Of_Entries; i++)
{
Value = Map->Blend_Map_Entries[i].value;
VAddScaledEq(Object->Colour,Value,Map->Blend_Map_Entries[i].Vals.Colour);
}
END_CASE
CASE(PHOTONS_TOKEN)
Parse_Begin();
EXPECT
CASE(GLOBAL_TOKEN)
Object->Ph_Density = Allow_Float(1.0);
if (Object->Ph_Density > 0)
{
Object->Ph_Flags |= PH_FLAG_TARGET;
/*CheckPassThru(Object, PH_FLAG_TARGET);*/
}
else
{
Object->Ph_Flags &= ~PH_FLAG_TARGET;
}
END_CASE
CASE(REFRACTION_TOKEN)
if((int)Parse_Float())
{ SET_PH_FLAG(Object, PH_FLAG_RFR_ON, PH_FLAG_RFR_OFF); }
else
{ CLEAR_PH_FLAG(Object, PH_FLAG_RFR_ON, PH_FLAG_RFR_OFF); }
END_CASE
CASE(REFLECTION_TOKEN)
if((int)Parse_Float())
{ SET_PH_FLAG(Object, PH_FLAG_RFL_ON, PH_FLAG_RFL_OFF); }
else
{ CLEAR_PH_FLAG(Object, PH_FLAG_RFL_ON, PH_FLAG_RFL_OFF); }
END_CASE
CASE (AREA_LIGHT_TOKEN)
Object->Photon_Area_Light = TRUE;
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End();
END_CASE
/* NK ---- */
#ifdef GlowPatch
CASE(GLOW_TOKEN)
{
GLOW * NewGlow = NULL;
#ifdef UnofficialBlocking
parseUnofficialFeature(60);
#endif
NewGlow = Create_Glow();
Assign_Colour(NewGlow->Colour, Object->Colour);
Assign_Vector(NewGlow->Center, Object->Center);
Parse_Glow(NewGlow);
Add_Glow(NewGlow);/*Add glow to Frame*/
/*Add glow to list of glow pointers in object*/
if(Object->glowList == NULL)
{ Object->glowList =(GLOW**) POV_MALLOC(sizeof(GLOW_PTR), "glow pointer array");}
else
{
GLOW_PTR * newGlowList =(GLOW**) POV_MALLOC((Object->numOfGlows+2)*sizeof(GLOW_PTR), "glow pointer array");
memcpy(newGlowList, Object->glowList, (Object->numOfGlows+1)*sizeof(GLOW_PTR));
POV_FREE(Object->glowList);
Object->glowList = newGlowList;
}
Object->glowList[Object->numOfGlows] = NewGlow;
Object->numOfGlows++;
}
END_CASE
#endif
CASE (LOOKS_LIKE_TOKEN)
if (Object->Children != NULL)
Error("Only one looks_like allowed per light_source.");
Parse_Begin ();
Object->Type &= ~(int)PATCH_OBJECT;
if ((Object->Children = Parse_Object ()) == NULL)
Parse_Error_Str ("object");
Compute_Translation_Transform(&Local_Trans, Object->Center);
Translate_Object (Object->Children, Object->Center, &Local_Trans);
Parse_Object_Mods (Object->Children);
Set_Flag(Object->Children, NO_SHADOW_FLAG);
Set_Flag(Object, NO_SHADOW_FLAG);
Object->Children->No_Shadow_Group=ALL_GROUP;
Object->Type |= (Object->Children->Type & CHILDREN_FLAGS);
/* NK phmap 2000-may-10 */
Object->Ph_Flags |= PH_FLAG_PASSTHRU;
/* NK ---- */
END_CASE
CASE (PROJECTED_THROUGH_TOKEN)
if (Object->Projected_Through_Object != NULL)
Error("Only one projected through allowed per light_source.");
Parse_Begin ();
Object->Type &= ~(int)PATCH_OBJECT;
if ((Object->Projected_Through_Object = Parse_Object ()) == NULL)
Parse_Error_Str ("object");
Parse_Object_Mods (Object->Projected_Through_Object);
Set_Flag(Object, NO_SHADOW_FLAG);
/* NK phmap 2000-may-10 */
Object->Ph_Flags |= PH_FLAG_PASSTHRU;
/* NK ---- */
END_CASE
CASE (FILL_LIGHT_TOKEN)
Object->Light_Type = FILL_LIGHT_SOURCE;
END_CASE
CASE (GROUPS_TOKEN)
{
/*YS sept 17 2000 Memory leak */
char *tempstring=Parse_String();
Assign_Light_Groups(Object,tempstring);
POV_FREE(tempstring); /*YS sept 17 Memory leak */
}
END_CASE
CASE (PARALLEL_TOKEN)
Object->Parallel= TRUE;
END_CASE
CASE (SPOTLIGHT_TOKEN)
Object->Light_Type = SPOT_SOURCE;
END_CASE
CASE (CYLINDER_TOKEN)
Object->Light_Type = CYLINDER_SOURCE;
END_CASE
CASE (POINT_AT_TOKEN)
if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE)
|| Object->Parallel)
Parse_Vector(Object->Points_At);
else
Not_With ("point_at","standard light source");
END_CASE
CASE (TIGHTNESS_TOKEN)
if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE))
Object->Coeff = Parse_Float();
else
Not_With ("tightness","standard light source");
END_CASE
CASE (RADIUS_TOKEN)
if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE))
Object->Radius = Parse_Float();
else
Not_With ("radius","standard light source");
END_CASE
CASE (FALLOFF_TOKEN)
if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE))
Object->Falloff = Parse_Float();
else
Not_With ("falloff","standard light source");
END_CASE
CASE (FADE_DISTANCE_TOKEN)
Object->Fade_Distance = Parse_Float();
END_CASE
CASE (FADE_POWER_TOKEN)
Object->Fade_Power = Parse_Float();
END_CASE
CASE (AREA_LIGHT_TOKEN)
Object->Area_Light = TRUE;
Parse_Vector (Object->Axis1); Parse_Comma ();
Parse_Vector (Object->Axis2); Parse_Comma ();
Object->Area_Size1 = (int)Parse_Float(); Parse_Comma ();
Object->Area_Size2 = (int)Parse_Float();
Object->Light_Grid = Create_Light_Grid (Object->Area_Size1, Object->Area_Size2);
END_CASE
#ifdef CircularOrientAreaLightPatch
/* Orient area lights to the point [ENB 9/97] */
CASE (AREA_LIGHT_ORIENT_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Object->Orient =Object->CircularOrient= TRUE;
END_CASE
/* Circular area lights [ENB 9/97] */
CASE (AREA_LIGHT_CIRCULAR_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Object->Circular = Object->CircularOrient=TRUE;
END_CASE
#endif
CASE (JITTER_TOKEN)
Object->Jitter = TRUE;
END_CASE
CASE (TRACK_TOKEN)
Object->Track = TRUE;
END_CASE
CASE (ADAPTIVE_TOKEN)
Object->Adaptive_Level = (int)Parse_Float();
END_CASE
CASE (MEDIA_ATTENUATION_TOKEN)
Object->Media_Attenuation = Allow_Float(1.0) > 0.0;
END_CASE
CASE (MEDIA_INTERACTION_TOKEN)
Object->Media_Interaction = Allow_Float(1.0) > 0.0;
END_CASE
CASE (TRANSLATE_TOKEN)
Parse_Vector (Local_Vector);
Compute_Translation_Transform(&Local_Trans, Local_Vector);
Translate_Object ((OBJECT *)Object, Local_Vector, &Local_Trans);
END_CASE
CASE (ROTATE_TOKEN)
Parse_Vector (Local_Vector);
Compute_Rotation_Transform(&Local_Trans, Local_Vector);
Rotate_Object ((OBJECT *)Object, Local_Vector, &Local_Trans);
END_CASE
CASE (SCALE_TOKEN)
Parse_Scale_Vector (Local_Vector);
Compute_Scaling_Transform(&Local_Trans, Local_Vector);
Scale_Object ((OBJECT *)Object, Local_Vector, &Local_Trans);
END_CASE
CASE (TRANSFORM_TOKEN)
#ifndef TransformPatch /* Chris Huff april 2000 */
GET(TRANSFORM_ID_TOKEN)
Transform_Object ((OBJECT *)Object, (TRANSFORM *)Token.Data);
#else
{
TRANSFORM * Trans = Parse_Transform();
Transform_Object((OBJECT *)Object, Trans);
/*YS sept 17 2000 Memory leak*/
POV_FREE(Trans);
}
#endif
END_CASE
CASE (MATRIX_TOKEN)
Parse_Matrix (Local_Matrix);
Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
Transform_Object ((OBJECT *)Object, &Local_Trans);
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End ();
if (Object->Light_Type == SPOT_SOURCE)
{
Object->Radius = cos(Object->Radius * M_PI_180);
Object->Falloff = cos(Object->Falloff * M_PI_180);
}
VSub(Object->Direction, Object->Points_At, Object->Center);
VLength(Len, Object->Direction);
if (Len > EPSILON)
{
VInverseScaleEq(Object->Direction, Len);
}
return ((OBJECT *)Object);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
#ifdef CreateLabelPatch
/* NK persist create */
char* createObjectName;
/* NK ---- */
#endif
OBJECT *Parse_Object ()
{
#ifdef CreateLabelPatch
/* NK persist create Nov 1999 */
char *localObjectName;
/* ---- */
#endif
OBJECT *Object = NULL;
#ifdef CreateLabelPatch
/* NK persist create Nov 1999 */
localObjectName = createObjectName;
createObjectName = NULL;
/* ---- */
#endif
EXPECT
CASE (JULIA_FRACTAL_TOKEN)
Object = Parse_Julia_Fractal ();
EXIT
END_CASE
CASE (SPHERE_TOKEN)
Object = Parse_Sphere ();
EXIT
END_CASE
/** poviso: '96 O. & R.S. **/
#ifdef POVISO
CASE (PARAMETRIC_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(10);
#endif
Object = Parse_Parametric();
EXIT
END_CASE
CASE (ISOSURFACE_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(10);
#endif
Object = Parse_IsoSurface (PARSE_IMPFUN);
EXIT
END_CASE
#endif
/** --- **/
/* Sphere sweep support */
CASE (SPHERE_SWEEP_TOKEN)
Object = Parse_Sphere_Sweep ();
EXIT
END_CASE
CASE (PLANE_TOKEN)
Object = Parse_Plane ();
EXIT
END_CASE
CASE (CONE_TOKEN)
Object = Parse_Cone ();
EXIT
END_CASE
CASE (CYLINDER_TOKEN)
Object = Parse_Cylinder ();
EXIT
END_CASE
CASE (DISC_TOKEN)
Object = Parse_Disc ();
EXIT
END_CASE
CASE (QUADRIC_TOKEN)
Object = Parse_Quadric ();
EXIT
END_CASE
CASE (CUBIC_TOKEN)
Object = Parse_Poly (3);
EXIT
END_CASE
CASE (QUARTIC_TOKEN)
Object = Parse_Poly (4);
EXIT
END_CASE
CASE (POLY_TOKEN)
Object = Parse_Poly (0);
EXIT
END_CASE
CASE (TORUS_TOKEN)
Object = Parse_Torus ();
EXIT
END_CASE
/* Parse lathe primitive. [DB 8/94] */
CASE (LATHE_TOKEN)
Object = Parse_Lathe();
EXIT
END_CASE
/* Parse polygon primitive. [DB 8/94] */
CASE (POLYGON_TOKEN)
Object = Parse_Polygon();
EXIT
END_CASE
/* Parse prism primitive. [DB 8/94] */
CASE (PRISM_TOKEN)
Object = Parse_Prism();
EXIT
END_CASE
/* Parse surface of revolution primitive. [DB 8/94] */
CASE (SOR_TOKEN)
Object = Parse_Sor();
EXIT
END_CASE
/* Parse superellipsoid primitive. [DB 11/94] */
CASE (SUPERELLIPSOID_TOKEN)
Object = Parse_Superellipsoid();
EXIT
END_CASE
/* Parse triangle mesh primitive. [DB 2/95] */
CASE (MESH_TOKEN)
Object = Parse_Mesh();
EXIT
END_CASE
/* NK 1998 Parse triangle mesh primitive - syntax version 2. */
CASE (MESH2_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Object = Parse_Mesh2();
EXIT
END_CASE
/* NK ---- */
CASE (TEXT_TOKEN)
Object = Parse_TrueType ();
EXIT
END_CASE
CASE (OBJECT_ID_TOKEN)
Object = Copy_Object((OBJECT *) Token.Data);
EXIT
END_CASE
CASE (UNION_TOKEN)
Object = Parse_CSG (CSG_UNION_TYPE);
EXIT
END_CASE
CASE (COMPOSITE_TOKEN)
Warn(150, "Use union instead of composite.");
Object = Parse_CSG (CSG_UNION_TYPE);
EXIT
END_CASE
CASE (MERGE_TOKEN)
Object = Parse_CSG (CSG_MERGE_TYPE);
EXIT
END_CASE
CASE (INTERSECTION_TOKEN)
Object = Parse_CSG (CSG_INTERSECTION_TYPE);
EXIT
END_CASE
CASE (DIFFERENCE_TOKEN)
Object = Parse_CSG (CSG_DIFFERENCE_TYPE+CSG_INTERSECTION_TYPE);
EXIT
END_CASE
CASE (BICUBIC_PATCH_TOKEN)
Object = Parse_Bicubic_Patch ();
EXIT
END_CASE
#ifdef RBezierPatch
CASE (BEZIER_PATCH_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Object = Parse_RBezier_Patch ();
EXIT
END_CASE
#endif
CASE (TRIANGLE_TOKEN)
Object = Parse_Triangle ();
EXIT
END_CASE
CASE (SMOOTH_TRIANGLE_TOKEN)
Object = Parse_Smooth_Triangle ();
EXIT
END_CASE
CASE (HEIGHT_FIELD_TOKEN)
Object = Parse_HField ();
EXIT
END_CASE
CASE (BOX_TOKEN)
Object = Parse_Box ();
EXIT
END_CASE
CASE (BLOB_TOKEN)
#ifdef BlobPatternPatch
Object = Parse_Blob ();
#else
Object = Parse_Blob ();
#endif
EXIT
END_CASE
#ifdef IsoBlobPatch
/* Lummox JR, July 1999 */
CASE (ISOBLOB_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Object = Parse_Isoblob ();
EXIT
END_CASE
/* end Lummox JR's additions */
#endif
CASE (LIGHT_SOURCE_TOKEN)
Object = Parse_Light_Source ();
EXIT
END_CASE
#ifdef MotionBlurPatch
CASE (MOTION_BLUR_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Object = Parse_Motion_Blur();
parsedMotionBlurObject = TRUE;
EXIT
END_CASE
#endif
CASE (OBJECT_TOKEN)
Parse_Begin ();
Object = Parse_Object ();
if (!Object)
Parse_Error_Str ("object");
Parse_Object_Mods ((OBJECT *)Object);
EXIT
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
#ifdef CreateLabelPatch
/* NK persist create Nov 1999 */
if(Object!=NULL && localObjectName!=NULL)
{
if((OBJECT *)Object->Label!=NULL)
POV_FREE(((OBJECT *)Object)->Label);
((OBJECT *)Object)->Label = localObjectName;
}
/* ---- */
#endif
return ((OBJECT *) Object);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Parse_Default ()
{
TEXTURE *Local_Texture;
PIGMENT *Local_Pigment;
TNORMAL *Local_Tnormal;
FINISH *Local_Finish;
Not_In_Default = FALSE;
Parse_Begin();
EXPECT
CASE (TEXTURE_TOKEN)
Local_Texture = Default_Texture;
Parse_Begin ();
Default_Texture = Parse_Texture();
Parse_End ();
if (Default_Texture->Type != PLAIN_PATTERN)
Error("Default texture cannot be material map or tiles.");
if (Default_Texture->Next != NULL)
Error("Default texture cannot be layered.");
Destroy_Textures(Local_Texture);
END_CASE
CASE (PIGMENT_TOKEN)
Local_Pigment = Copy_Pigment((Default_Texture->Pigment));
Parse_Begin ();
Parse_Pigment (&Local_Pigment);
Parse_End ();
Destroy_Pigment(Default_Texture->Pigment);
Default_Texture->Pigment = Local_Pigment;
END_CASE
CASE (TNORMAL_TOKEN)
Local_Tnormal = Copy_Tnormal((Default_Texture->Tnormal));
Parse_Begin ();
Parse_Tnormal (&Local_Tnormal);
Parse_End ();
Destroy_Tnormal(Default_Texture->Tnormal);
Default_Texture->Tnormal = Local_Tnormal;
END_CASE
CASE (FINISH_TOKEN)
Local_Finish = Copy_Finish((Default_Texture->Finish));
Parse_Finish (&Local_Finish);
Destroy_Finish(Default_Texture->Finish);
Default_Texture->Finish = Local_Finish;
END_CASE
CASE (CAMERA_TOKEN)
Parse_Camera (&Default_Camera);
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End();
Not_In_Default = TRUE;
}
#ifdef BsplinePatch
/*****************************************************************************
*
* FUNCTION
*
* Parse_Init_Spline
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* Daniel Fenner
*
* DESCRIPTION
*
* Parse a new spline and compute the coefficients
*
* CHANGES
*
* 3-98 Creation
*
******************************************************************************/
void Parse_Init_Spline()
{
char *name;
DBL tv1,tv2;
VECTOR tv;
int is_first=TRUE,nr_of_knots=0,type=NATURAL_SPLINE,does_exist=FALSE;
DBL last_knot;
SPLINE *help;
SPLINE_STACK_1D *base=NULL,*New=NULL,*New1=NULL;
Parse_Begin ();
name = Parse_String();
/* does already exist ??? */
if (The_Splines!=NULL)
{
help=The_Splines;
if (strcmp(help->name,name)==0) does_exist=TRUE;
while (help->next!=NULL)
{
help=(SPLINE*)help->next;
if (strcmp(help->name,name)==0) does_exist=TRUE;
}
if (does_exist) Error("Spline named %s does already exist.",name);
}
Parse_Comma();
EXPECT
CASE (SPLINE_CLOSED_TOKEN)
type = CLOSED_SPLINE;
GET (EQUALS_TOKEN);
tv1 = Parse_Float();
Parse_Comma();
END_CASE
CASE (SPLINE_DIRECTION_TOKEN)
type = DIRECTION_SPLINE;
GET (EQUALS_TOKEN);
tv1 = Parse_Float();
Parse_Comma();
tv2 = Parse_Float();
Parse_Comma();
END_CASE
CASE (SPLINE_NATURAL_TOKEN)
type = NATURAL_SPLINE;
Parse_Comma();
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
EXPECT
CASE_VECTOR
Parse_Vector2D(tv);
if (is_first)
is_first=FALSE;
else
if (tv[X] <= last_knot) Error("Knot values have to be sorted in ascending way.");
last_knot = tv[X];
nr_of_knots ++;
/* Put the knot in a list */
New = (SPLINE_STACK_1D *)POV_MALLOC(sizeof(SPLINE_STACK_1D), NULL);
New->t = tv[X];
New->y = tv[Y];
New->next = NULL;
if (base==NULL) base=New;
else
{
New1=base;
while (New1->next!=NULL) New1 = (SPLINE_STACK_1D *)New1->next;
New1->next = New;
}
Parse_Comma();
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
if (nr_of_knots<2) Error("At least two knots per spline.");
if ((type==CLOSED_SPLINE)&&(tv1<=tv[X]))
Error("Last knot of closed spline must be the biggest.");
Parse_End();
Create_Spline_1D(base,nr_of_knots,name,type,tv1,tv2);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Init_3D_Spline
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* Daniel Fenner
*
* DESCRIPTION
*
* Parse a new spline and compute the coefficients
*
* CHANGES
*
* 3-98 Creation
*
******************************************************************************/
void Parse_Init_3D_Spline()
{
char *name;
VECTOR temp1,temp2,tv;
int nr_of_knots=0,type=NATURAL_SPLINE,does_exist=FALSE;
SPLINE_3D *help;
SPLINE_STACK_3D *base=NULL,*New=NULL,*New1=NULL;
Parse_Begin ();
name = Parse_String();
/* does already exist ??? */
if (The_3D_Splines!=NULL)
{
help=The_3D_Splines;
if (strcmp(help->name,name)==0) does_exist=TRUE;
while (help->next!=NULL)
{
help=(SPLINE_3D*)help->next;
if (strcmp(help->name,name)==0) does_exist=TRUE;
}
if (does_exist) Error("Spline named %s does already exist.",name);
}
Parse_Comma();
EXPECT
CASE (SPLINE_CLOSED_TOKEN)
type = CLOSED_SPLINE;
Parse_Comma();
END_CASE
CASE (SPLINE_DIRECTION_TOKEN)
type = DIRECTION_SPLINE;
GET (EQUALS_TOKEN);
Parse_Vector(temp1);
Parse_Comma();
Parse_Vector(temp2);
Parse_Comma();
END_CASE
CASE (SPLINE_NATURAL_TOKEN)
type = NATURAL_SPLINE;
Parse_Comma();
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
EXPECT
CASE_VECTOR
Parse_Vector(tv);
nr_of_knots ++;
/* Put the knot in a list */
New = (SPLINE_STACK_3D *)POV_MALLOC(sizeof(SPLINE_STACK_3D), NULL);
New->Knot[X]=tv[X];
New->Knot[Y]=tv[Y];
New->Knot[Z]=tv[Z];
New->next = NULL;
if (base==NULL) base=New;
else
{
New1=base;
while (New1->next!=NULL) New1 =(SPLINE_STACK_3D *) New1->next;
New1->next = New;
}
Parse_Comma();
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
if (nr_of_knots<2) Error("At least two knots per spline.");
Parse_End();
Create_Spline_3D(base,nr_of_knots,name,type,temp1,temp2);
}
#endif
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static void Parse_Frame ()
{
OBJECT *Object;
RAINBOW *Local_Rainbow;
FOG *Local_Fog;
SKYSPHERE *Local_Skysphere;
int i;
EXPECT
CASE (RAINBOW_TOKEN)
Local_Rainbow = Parse_Rainbow();
Local_Rainbow->Next = Frame.Rainbow;
Frame.Rainbow = Local_Rainbow;
END_CASE
CASE (SKYSPHERE_TOKEN)
Local_Skysphere = Parse_Skysphere();
if (Frame.Skysphere != NULL)
{
Warn(0, "Only one sky-sphere allowed (last one will be used).");
Destroy_Skysphere(Frame.Skysphere);
}
Frame.Skysphere = Local_Skysphere;
for (i=0; i<Local_Skysphere->Count; i++)
{
Post_Pigment(Local_Skysphere->Pigments[i]);
}
END_CASE
CASE (FOG_TOKEN)
Local_Fog = Parse_Fog();
Local_Fog->Next = Frame.Fog;
Frame.Fog = Local_Fog;
END_CASE
CASE (MEDIA_TOKEN)
Parse_Media(&Frame.Atmosphere);
END_CASE
CASE (BACKGROUND_TOKEN)
Parse_Begin();
Parse_Colour (Frame.Background_Colour);
Parse_End();
END_CASE
CASE (CAMERA_TOKEN)
Parse_Camera (&Frame.Camera);
END_CASE
CASE (DECLARE_TOKEN)
UNGET
Warn(299,"Should have '#' before 'declare'.");
Parse_Directive (FALSE);
END_CASE
CASE (INCLUDE_TOKEN)
UNGET
Warn(299,"Should have '#' before 'include'.");
Parse_Directive (FALSE);
END_CASE
CASE (FLOAT_FUNCT_TOKEN)
switch(Token.Function_Id)
{
case VERSION_TOKEN:
UNGET
Parse_Directive (FALSE);
UNGET
break;
default:
UNGET
Parse_Error_Str ("object or directive");
break;
}
END_CASE
CASE (MAX_TRACE_LEVEL_TOKEN)
Global_Setting_Warn();
Max_Trace_Level = (int) Parse_Float ();
END_CASE
CASE (MAX_INTERSECTIONS)
Global_Setting_Warn();
Max_Intersections = (int)Parse_Float ();
END_CASE
CASE (DEFAULT_TOKEN)
Parse_Default();
END_CASE
CASE (END_OF_FILE_TOKEN)
EXIT
END_CASE
CASE (GLOBAL_SETTINGS_TOKEN)
Parse_Global_Settings();
END_CASE
/* NK persist - Nov 1999 */
CASE (MODIFY_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Parse_Modify_Object();
END_CASE
CASE (DESTROY_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Parse_Destroy_Object();
END_CASE
/* NK ---- */
#ifdef GlowPatch
/*YS sept 18 2000
added this here too to allow
for a scene with only glow */
CASE(GLOW_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(60);
#endif
{
GLOW * NewGlow = Create_Glow();
Parse_Glow(NewGlow);
Add_Glow(NewGlow);
}
END_CASE
#endif
OTHERWISE
UNGET
Object = Parse_Object();
if (Object == NULL)
Parse_Error_Str ("object or directive");
Post_Process (Object, NULL);
Link_To_Frame (Object);
END_CASE
END_EXPECT
}
/* NK persist */
int findObjectsByLabel(OBJECT **objHandle, OBJECT* parent, char **objectNames, int nameCount,
int (*function)(OBJECT **objHandle, OBJECT* parent, void *handle), void *handle,
int (*functionParent)(OBJECT **objHandle, OBJECT* parent, void *handle), void *handle2 )
{
int found=FALSE;
int go_next;
/* go through objects, but we're always using the pointer to the pointer to
the object */
while( *objHandle != NULL )
{
if((*objHandle)->Label)
{
if(strcmp((*objHandle)->Label,objectNames[0])==0)
{
/* match */
if (nameCount==1)
{
/* call the function */
go_next = function(objHandle, parent, handle);
found = TRUE;
}
else
{
/* should check this first, make sure it really is a CSG */
if (findObjectsByLabel(&(((CSG *)*objHandle)->Children), *objHandle, &objectNames[1],
nameCount-1, function, handle, functionParent, handle2 ))
{
found = TRUE;
go_next = functionParent(objHandle, parent, handle2);
}
}
if(go_next)
{
objHandle=&((*objHandle)->Sibling);
}
}
else
{
objHandle=&((*objHandle)->Sibling);
}
}
else
{
objHandle=&((*objHandle)->Sibling);
}
}
return found;
}
extern int CS_Index;
static int beginCS_Index;
static int beginBrace_Index;
int modifyObjectCallback(OBJECT **objHandle, OBJECT* parent, void *handle)
{
restoreFilePos();
Brace_Index = beginBrace_Index;
Parse_Object_Mods(*objHandle);
Post_Process (*objHandle, parent);
if (CS_Index != beginCS_Index)
{
Error("close brace for modify cannot be enclosed in an #if, #case, or #while block.\n");
}
return TRUE; /* continue to next */
}
int modifyObjectParentCallback(OBJECT **objHandle, OBJECT *parent, void *handle)
{
/* if this is a parent then we know it is a compound object */
Compute_CSG_BBox(*objHandle);
Post_Process (*objHandle, parent);
return TRUE; /* continue to next */
}
int destroyObjectCallback(OBJECT **objHandle, OBJECT* parent, void *handle)
{
OBJECT *obj = *objHandle;
*objHandle = (*objHandle)->Sibling;
POV_FREE(obj);
return FALSE; /* don't go to next */
}
int destroyObjectParentCallback(OBJECT **objHandle, OBJECT *parent, void *handle)
{
/* if this is a parent then we know it is a compound object */
Compute_CSG_BBox(*objHandle);
Post_Process (*objHandle, parent);
return TRUE; /* continue to next */
}
/*****************************************************************************
*
* FUNCTION
* Parse_Modify_Object()
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* This allows a persistent object (named with #create) to be modified.
* It will parse object modifiers and apply them to all objects that
* match the name.
*
* The syntax would look like this:
* #create mySph=sphere{...}
* modify{
* mySph
* translate 10*x
* }
*
*
* CHANGES
*
******************************************************************************/
static void Parse_Modify_Object(void)
{
/*OBJECT *o;*/
char **objectNames;
int done;
int i;
/*int level;*/
int numLevels;
Parse_Begin();
/* first, count levels */
saveFilePos();
numLevels = 0;
done = FALSE;
while (!done)
{
numLevels++;
Get_Token();
Get_Token();
if(Token.Token_Id!=PERIOD_TOKEN)
done=TRUE;
}
restoreFilePos();
objectNames =(char**) POV_MALLOC(sizeof(OBJECT*)*numLevels,"object names");
for(i=0; i<numLevels; i++)
{
if (i>0) Get_Token(); /* parse the period */
Get_Token(); /* parse the name */
objectNames[i] = POV_STRDUP(Token.Token_String);
}
saveFilePos();
beginCS_Index = CS_Index;
beginBrace_Index = Brace_Index;
if (!findObjectsByLabel(&Frame.Objects, NULL, objectNames, numLevels,
modifyObjectCallback, NULL,
modifyObjectParentCallback, NULL))
{
Error("No objects match this label.\n");
}
for(i=0; i<numLevels; i++)
{
POV_FREE(objectNames[i]);
}
POV_FREE(objectNames);
}
/*****************************************************************************
*
* FUNCTION
* Parse_Destroy_Object()
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
*
*
* CHANGES
*
******************************************************************************/
static void Parse_Destroy_Object(void)
{
char **objectNames;
int done;
int i;
int numLevels;
Parse_Begin();
/* first, count levels */
saveFilePos();
numLevels = 0;
done = FALSE;
while (!done)
{
numLevels++;
Get_Token();
Get_Token();
if(Token.Token_Id!=PERIOD_TOKEN)
done=TRUE;
}
restoreFilePos();
objectNames =(char**) POV_MALLOC(sizeof(OBJECT*)*numLevels,"object names");
for(i=0; i<numLevels; i++)
{
if (i>0) Get_Token(); /* parse the period */
Get_Token(); /* parse the name */
objectNames[i] = POV_STRDUP(Token.Token_String);
}
if (!findObjectsByLabel(&Frame.Objects, NULL, objectNames, numLevels,
destroyObjectCallback, NULL,
destroyObjectParentCallback, NULL))
{
Error("No objects match this label.\n");
}
Parse_End();
for(i=0; i<numLevels; i++)
{
POV_FREE(objectNames[i]);
}
POV_FREE(objectNames);
}
/* NK ---- */
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
* Mar 1996 : Add line number info to warning message [AED]
*
******************************************************************************/
static void Global_Setting_Warn()
{
if (opts.Language_Version >= 300)
{
Warning(0, "%s:%d: warning: '%s' should be in 'global_settings{...}' statement.\n",
Token.Filename, Token.Token_Line_No+1, Token.Token_String);
}
}
#ifdef PostProcessPatch
#define Add_PP(pp) {\
PP_TASK *pp_task;\
if(!opts.postProcess)\
{ opts.postProcess = (void*)pp;}\
else\
{\
for(pp_task = (PP_TASK*)opts.postProcess; pp_task->next != NULL; pp_task = pp_task->next){;}\
pp_task->next = (PP_TASK*)pp;\
}\
}
#ifdef PostProcessCurvesPatch
SPLINE2 *Process_Spline_Syntax(void);
SPLINE2 *Process_Spline_Syntax(void)
{
SPLINE2 *Spline=NULL;
EXPECT
CASE(SPLINE_TOKEN)
Parse_Begin();
Spline= Parse_Spline();
Parse_End();
EXIT
END_CASE
OTHERWISE
UNGET
Spline= Parse_Spline();
EXIT
END_CASE
END_EXPECT
return Spline;
}
#endif
void Parse_Post_Process(void)
{
PP_TASK *pp_task;
if(!(opts.Options & DISKWRITE))
{
Error("Post-processing requires an output file.\n");
}
Parse_Begin();
EXPECT
CASE(OVERWRITE_FILE_TOKEN)
opts.postProcessOverwriteOriginal = TRUE;
END_CASE
#ifdef PostProcessKeepDataPatch
CASE(KEEP_DATA_FILE_TOKEN)
opts.keep_post_process_data_file = TRUE;
END_CASE
#endif
#ifdef PostProcessLimitBrightnessPatch
CASE(LIMIT_BRIGHTNESS_TOKEN)
{
PP_LIMIT_BRIGHTNESS * new_pp = createPostLimitBrightness();
#ifdef UnofficialBlocking
parseUnofficialFeature(70);
#endif
new_pp->max_brightness = Allow_Float(1);
Add_PP(new_pp)
opts.postProcessFlags |= PP_LIMIT_BRIGHTNESS_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessRawImagePatch
CASE(RAW_IMAGE_TOKEN)
{
PP_RAW_IMAGE * new_pp = createPostRawImage();
#ifdef UnofficialBlocking
parseUnofficialFeature(70);
#endif
if(!opts.postProcess)
{ opts.postProcess = (void*)new_pp;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_pp;
}
opts.postProcessFlags |= PP_RAW_IMAGE_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessCurvesPatch
CASE(CURVES_TOKEN)
{
PP_CURVES * new_pp = createPostCurves();;
#ifdef UnofficialBlocking
parseUnofficialFeature(70);
#endif
Parse_Begin();
EXPECT
CASE(COLOUR_KEY_TOKEN)
switch(Token.Function_Id)
{
case RGB_TOKEN:
Parse_Comma();
new_pp->type = 0;/*rgb type*/
new_pp->rCurve = Process_Spline_Syntax();
Parse_Comma();
new_pp->gCurve = Process_Spline_Syntax();
Parse_Comma();
new_pp->bCurve = Process_Spline_Syntax();
EXIT
break;
case RED_TOKEN:
Parse_Comma();
new_pp->type = 0;/*red channel only*/
new_pp->rCurve = Process_Spline_Syntax();
EXIT
break;
case GREEN_TOKEN:
Parse_Comma();
new_pp->type = 0;/*green channel only*/
new_pp->gCurve = Process_Spline_Syntax();
EXIT
break;
case BLUE_TOKEN:
Parse_Comma();
new_pp->type = 0;/*blue channel only*/
new_pp->bCurve = Process_Spline_Syntax();
EXIT
break;
}
END_CASE
CASE (ALL_TOKEN)
Parse_Comma();
new_pp->type = 1;/*grayscale*/
new_pp->rCurve = Process_Spline_Syntax();
EXIT
END_CASE
OTHERWISE
Error("Expected rgb, red, green, blue, or all.");
END_CASE
END_EXPECT
Parse_End();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_pp;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_pp;
}
opts.postProcessFlags |= PP_CURVES_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessPatternBlurPatch
CASE(PATTERN_BLUR_TOKEN)
{
PP_PATTERN_BLUR *new_pattern_blur;
#ifdef UnofficialBlocking
parseUnofficialFeature(50);
#endif
new_pattern_blur = createPostPatternBlur();
Parse_Begin();
new_pattern_blur->Radius = Parse_Float();
Parse_Comma();
new_pattern_blur->Div = Parse_Float();
Parse_Comma();
new_pattern_blur->Levelling = Parse_Float();
Parse_Comma();
Parse_Pigment(&new_pattern_blur->Pig);
Parse_End();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_pattern_blur; }
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_pattern_blur;
}
opts.postProcessFlags |= PP_PATTERN_BLUR_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessStarsPatch
CASE(STARS_TOKEN)
{
PP_STARS *new_stars;
#ifdef UnofficialBlocking
parseUnofficialFeature(50);
#endif
new_stars = createPostStars();
Parse_Begin();
new_stars->Density = Parse_Float();
Parse_Comma();
Parse_Colour(new_stars->colRangeMin);
Parse_Comma();
Parse_Colour(new_stars->colRangeMax);
Parse_End();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_stars;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_stars;
}
opts.postProcessFlags |= PP_STARS_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessStepsPatch
CASE(POSTERIZE_TOKEN)
{
PP_STEPS *new_steps;
#ifdef UnofficialBlocking
parseUnofficialFeature(50);
#endif
new_steps = createPostSteps();
Parse_Begin();
Parse_Colour(new_steps->numSteps);
Parse_End();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_steps;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_steps;
}
opts.postProcessFlags |= PP_STEPS_FLAGS;
}
END_CASE
#endif
#ifdef PostProcesNormalPatch
CASE(TNORMAL_TOKEN)
{
PP_NORMAL *new_normal;
#ifdef UnofficialBlocking
parseUnofficialFeature(50);
#endif
new_normal = createPostNormal();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_normal;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_normal;
}
opts.postProcessFlags |= PP_NORMAL_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessMinPatch
CASE(POST_MIN_TOKEN)
{
PP_MATH *new_proc;
#ifdef UnofficialBlocking
parseUnofficialFeature(60);
#endif
new_proc = createPostMath();
new_proc->doPostProcess = doPostMin;
Parse_Begin();
Parse_Pigment(&new_proc->Pig);
Parse_End();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_proc;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_proc;
}
opts.postProcessFlags |= PP_MATH_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessMaxPatch
CASE(POST_MAX_TOKEN)
{
PP_MATH *new_proc;
#ifdef UnofficialBlocking
parseUnofficialFeature(60);
#endif
new_proc = createPostMath();
new_proc->doPostProcess = doPostMax;
Parse_Begin();
Parse_Pigment(&new_proc->Pig);
Parse_End();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_proc;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_proc;
}
opts.postProcessFlags |= PP_MATH_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessAddPatch
CASE(ADD_TOKEN)
{
PP_MATH *new_proc;
#ifdef UnofficialBlocking
parseUnofficialFeature(50);
#endif
new_proc = createPostMath();
new_proc->doPostProcess = doPostAdd;
Parse_Begin();
Parse_Pigment(&new_proc->Pig);
Parse_End();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_proc;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_proc;
}
opts.postProcessFlags |= PP_MATH_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessSubtractPatch
CASE(SUBTRACT_TOKEN)
{
PP_MATH *new_proc;
#ifdef UnofficialBlocking
parseUnofficialFeature(60);
#endif
new_proc = createPostMath();
new_proc->doPostProcess = doPostSub;
Parse_Begin();
Parse_Pigment(&new_proc->Pig);
Parse_End();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_proc;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_proc;
}
opts.postProcessFlags |= PP_MATH_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessMultiplyPatch
CASE(MULTIPLY_TOKEN)
{
PP_MATH *new_proc;
#ifdef UnofficialBlocking
parseUnofficialFeature(50);
#endif
new_proc = createPostMath();
new_proc->doPostProcess = doPostMult;
Parse_Begin();
Parse_Pigment(&new_proc->Pig);
Parse_End();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_proc;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_proc;
}
opts.postProcessFlags |= PP_MATH_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessDividePatch
CASE(DIVIDE_TOKEN)
{
PP_MATH *new_proc;
#ifdef UnofficialBlocking
parseUnofficialFeature(60);
#endif
new_proc = createPostMath();
new_proc->doPostProcess = doPostDiv;
Parse_Begin();
Parse_Pigment(&new_proc->Pig);
Parse_End();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_proc;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_proc;
}
opts.postProcessFlags |= PP_MATH_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessExponentPatch
CASE(EXPONENT_TOKEN)
{
PP_MATH *new_proc;
#ifdef UnofficialBlocking
parseUnofficialFeature(50);
#endif
new_proc = createPostMath();
new_proc->doPostProcess = doPostExp;
Parse_Begin();
Parse_Pigment(&new_proc->Pig);
Parse_End();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_proc;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_proc;
}
opts.postProcessFlags |= PP_MATH_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessInvertPatch
CASE(INVERT_TOKEN)
{
PP_INVERT *new_invert;
#ifdef UnofficialBlocking
parseUnofficialFeature(50);
#endif
new_invert = createPostInvert();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_invert;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_invert;
}
opts.postProcessFlags |= PP_INVERT_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessClipColorsPatch
CASE(CLIP_COLORS_TOKEN)
{
PP_CLIP_COLORS *new_clip_colors;
#ifdef UnofficialBlocking
parseUnofficialFeature(50);
#endif
new_clip_colors = createPostClipColors();
Parse_Begin();
Parse_Colour(new_clip_colors->ClipMin);
Parse_Comma();
Parse_Colour(new_clip_colors->ClipMax);
Parse_End();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_clip_colors;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_clip_colors;
}
opts.postProcessFlags |= PP_CLIP_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessFindEdgesPatch
CASE(FIND_EDGES_TOKEN)
{
PP_EDGES *new_edges;
#ifdef UnofficialBlocking
parseUnofficialFeature(50);
#endif
Parse_Begin();
new_edges = createPostEdges();
new_edges->ThreshDepthMax = Parse_Float();
Parse_Comma();
new_edges->ThreshNormMax = Parse_Float();
Parse_Comma();
new_edges->ThreshColMax = Parse_Float();
Parse_Comma();
new_edges->Radius = Parse_Float();
Parse_Comma();
new_edges->Sharpness = Parse_Float();
Parse_Comma();
/*Parse_Colour(new_edges->LineCol);*/
Parse_Pigment(&(new_edges->LinePig));
Post_Pigment(new_edges->LinePig);
Parse_End();
if(!opts.postProcess)
{ opts.postProcess = (void*)new_edges;}
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_edges;
}
opts.postProcessFlags |= PP_EDGES_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessColorMatrixPatch
CASE(COLOR_MATRIX_TOKEN)
{
PP_COLOR_MATRIX *new_color_matrix;
int i = 0;
int j = 0;
#ifdef UnofficialBlocking
parseUnofficialFeature(50);
#endif
new_color_matrix = createPostColor_Matrix();
Parse_Begin();
GET (LEFT_ANGLE_TOKEN);
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
new_color_matrix->Matrix[j][i] = Parse_Float();
if(!(i==2 && j==2))
{ Parse_Comma();}
}
}
GET (RIGHT_ANGLE_TOKEN);
Parse_End();
if(!opts.postProcess) opts.postProcess = (void*)new_color_matrix;
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_color_matrix;
}
opts.postProcessFlags |= PP_COLOR_MATRIX_FLAGS;
}
END_CASE
#endif
#ifdef PostProcessBlurMatrixPatch
CASE(CONVOLUTION_MATRIX_TOKEN)
{
PP_BLUR_MATRIX *new_blur_matrix;
int i = 0;
int j = 0;
int k = 0;
#ifdef UnofficialBlocking
parseUnofficialFeature(50);
#endif
Parse_Begin();
new_blur_matrix = createPostBlur_Matrix();
new_blur_matrix->xSize = (int)Parse_Float();
Parse_Comma();
new_blur_matrix->ySize = (int)Parse_Float();
Parse_Comma();
new_blur_matrix->Div = Parse_Float();
Parse_Comma();
new_blur_matrix->Levelling = Parse_Float();
Parse_Comma();
new_blur_matrix->Matrix = (DBL *)POV_MALLOC(new_blur_matrix->xSize*new_blur_matrix->ySize*sizeof(DBL),"blur_matrix data");
GET (LEFT_ANGLE_TOKEN);
for (i = 0; i < new_blur_matrix->ySize; i++)
{
for (j = 0; j < new_blur_matrix->xSize; j++)
{
new_blur_matrix->Matrix[k] = Parse_Float();
if(!(i==new_blur_matrix->ySize-1 && j==new_blur_matrix->xSize-1))
{ Parse_Comma();}
k++;
}
}
GET (RIGHT_ANGLE_TOKEN);
Parse_End();
if(!opts.postProcess) opts.postProcess = (void*)new_blur_matrix;
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next){;}
pp_task->next = (PP_TASK*)new_blur_matrix;
}
opts.postProcessFlags |= PP_BLUR_MATRIX_FLAGS;
}
END_CASE
#endif
CASE(FOCAL_BLUR_TOKEN)
{
PP_FOCAL_BLUR *new_focal;
Parse_Begin();
new_focal = createPostFocalBlur();
new_focal->fieldStart = Parse_Float(); Parse_Comma();
new_focal->fieldDepth = Parse_Float(); Parse_Comma();
new_focal->maxPixelBlur = (int)Parse_Float(); Parse_Comma();
new_focal->keepAA = Parse_Float();
Parse_End();
if(!opts.postProcess) opts.postProcess = (void*)new_focal;
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next);
pp_task->next = (PP_TASK*)new_focal;
}
opts.postProcessFlags |= PP_FOCAL_BLUR_FLAGS;
}
END_CASE
CASE(DEPTH_TOKEN)
{
PP_DEPTH *new_depth;
Parse_Begin();
new_depth = createPostDepth();
new_depth->fieldStart = Parse_Float(); Parse_Comma();
new_depth->fieldDepth = Parse_Float();
Parse_End();
if(!opts.postProcess) opts.postProcess = (void*)new_depth;
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next);
pp_task->next = (PP_TASK*)new_depth;
}
opts.postProcessFlags |= PP_DEPTH_FLAGS;
}
END_CASE
CASE(SOFT_GLOW_TOKEN)
{
PP_SOFT_GLOW *new_soft_glow;
Parse_Begin();
new_soft_glow = createPostSoftGlow();
new_soft_glow->glowAmount = Parse_Float(); Parse_Comma();
new_soft_glow->blurAmount = Parse_Float();
Parse_End();
if(!opts.postProcess) opts.postProcess = (void*)new_soft_glow;
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next);
pp_task->next = (PP_TASK*)new_soft_glow;
}
opts.postProcessFlags |= PP_SOFT_GLOW_FLAGS;
}
END_CASE
#ifdef PostCartoonPatch
CASE(CARTOON_TOKEN)
{
PP_CARTOON *new_cartoon;
Parse_Begin();
new_cartoon = createPostCartoon();
new_cartoon->blurAmount = Parse_Float(); Parse_Comma();
new_cartoon->hueThreshold = Parse_Float(); Parse_Comma();
new_cartoon->lumThreshold = Parse_Float(); Parse_Comma();
/*new_cartoon->lineWidth = Parse_Float(); Parse_Comma();
new_cartoon->lineHueThreshold = Parse_Float(); Parse_Comma();
Parse_Colour(new_cartoon->lineColour);*/
Parse_End();
if(!opts.postProcess) opts.postProcess = (void*)new_cartoon;
else
{
for(pp_task=(PP_TASK*)opts.postProcess; pp_task->next!=NULL; pp_task=pp_task->next);
pp_task->next = (PP_TASK*)new_cartoon;
}
opts.postProcessFlags |= PP_CARTOON_FLAGS;
}
END_CASE
#endif
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End();
}
#endif
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static void Parse_Global_Settings()
{
char *optsString;
Parse_Begin();
EXPECT
#ifdef PostProcessPatch
CASE (POST_PROCESS_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(40);
#endif
Parse_Post_Process();
END_CASE
#endif
#ifdef MotionBlurPatch
CASE (MOTION_BLUR_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
if (parsedMotionBlurObject)
Error("motion_blur in global_settings must preceed all motion_blur objects.\n");
opts.motionBlurCount = (int)Parse_Float();
Parse_Comma();
opts.blurClockDelta = Parse_Float();
if(opts.motionBlurCount<=1)
Error("motion blur count must be greater than 1.\n");
if(opts.blurClockDelta<=0)
Error("blur clock delta must be greater than zero.\n");
END_CASE
#endif
CASE (IRID_WAVELENGTH_TOKEN)
Parse_Colour (Frame.Irid_Wavelengths);
END_CASE
CASE (ASSUMED_GAMMA_TOKEN)
{
DBL AssumedGamma;
AssumedGamma = Parse_Float ();
if (fabs(AssumedGamma - opts.DisplayGamma) < 0.1)
{
opts.GammaFactor = 1.0;
opts.Options &= ~GAMMA_CORRECT; /* turn off gamma correction */
}
else
{
opts.GammaFactor = AssumedGamma/opts.DisplayGamma;
opts.Options |= GAMMA_CORRECT; /* turn on gamma correction */
}
}
END_CASE
CASE (MAX_TRACE_LEVEL_TOKEN)
Max_Trace_Level = (int) Parse_Float ();
END_CASE
CASE (ADC_BAILOUT_TOKEN)
ADC_Bailout = Parse_Float ();
END_CASE
CASE (NUMBER_OF_WAVES_TOKEN)
Number_Of_Waves = (int) Parse_Float ();
if(Number_Of_Waves == 0)
{
Warn(0, "Illegal Value: Number_Of_Waves = 0. Changed to 1.");
Number_Of_Waves = 1;
}
END_CASE
CASE (MAX_INTERSECTIONS)
Max_Intersections = (int)Parse_Float ();
END_CASE
CASE (AMBIENT_LIGHT_TOKEN)
Parse_Colour (Frame.Ambient_Light);
END_CASE
/* NK opts 1999 - adding options to parser */
CASE (INI_OPTION_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
optsString = Parse_String();
parse_option_line(optsString);
POV_FREE(optsString);
END_CASE
/* NK ---- */
/* NK phmap */
CASE (PHOTONS_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Parse_Begin();
EXPECT
CASE(RADIUS_TOKEN)
photonOptions.photonMap.minGatherRad = Parse_Float();
END_CASE
CASE(SPACING_TOKEN)
photonOptions.surfaceSeparation = Parse_Float();
END_CASE
CASE(GLOBAL_TOKEN)
photonOptions.globalCount = (int)Parse_Float();
END_CASE
CASE (REFLECTION_BLUR_TOKEN)
photonOptions.photonReflectionBlur = (int)Parse_Float();
END_CASE
CASE (EXPAND_THRESHOLDS_TOKEN)
photonOptions.expandTolerance = Parse_Float(); Parse_Comma();
photonOptions.minExpandCount = Parse_Float();
if (photonOptions.expandTolerance<0.0)
{
Warning(100,"The first parameter of expand_thresholds must be greater than or equal to 0. Setting it to 0 now.\n");
photonOptions.expandTolerance = 0.0;
}
if (photonOptions.minExpandCount<0)
{
Warning(100,"The second parameter of expand_thresholds must be greater than or equal to 0. Setting it to 0 now.\n");
photonOptions.minExpandCount = 0;
}
END_CASE
CASE (RANGE_DIVIDER_TOKEN)
photonOptions.photonMap.rangeSelector = Parse_Float();
END_CASE
CASE (GATHER_TOKEN)
photonOptions.minGatherCount = (int)Parse_Float();
Parse_Comma();
photonOptions.maxGatherCount = (int)Parse_Float();
END_CASE
CASE (JITTER_TOKEN)
photonOptions.jitter = Parse_Float();
END_CASE
CASE (COUNT_TOKEN)
photonOptions.surfaceCount = (int)Parse_Float();
END_CASE
CASE (AUTOSTOP_TOKEN)
photonOptions.autoStopPercent = Parse_Float();
END_CASE
CASE (ADC_BAILOUT_TOKEN)
photonOptions.ADC_Bailout = Parse_Float ();
END_CASE
CASE (MAX_TRACE_LEVEL_TOKEN)
photonOptions.Max_Trace_Level = Parse_Float();
END_CASE
CASE(LOAD_FILE_TOKEN)
if(photonOptions.fileName)
{
if(photonOptions.loadFile)
Warn(100,"Filename already given, using new name\n");
else
Warn(100,"Cannot both load and save photon map. Now switching to load mode.\n");
POV_FREE(photonOptions.fileName);
}
photonOptions.fileName = Parse_String();
photonOptions.loadFile = TRUE;
END_CASE
CASE(SAVE_FILE_TOKEN)
if(photonOptions.fileName)
{
if(!photonOptions.loadFile)
Warn(100,"Filename already given, using new name\n");
else
Warn(100,"Cannot both load and save photon map. Now switching to save mode.\n");
POV_FREE(photonOptions.fileName);
}
photonOptions.fileName = Parse_String();
photonOptions.loadFile = FALSE;
END_CASE
CASE(MEDIA_TOKEN)
photonOptions.maxMediaSteps = (int)Parse_Float(); Parse_Comma();
if (photonOptions.maxMediaSteps<0)
Error("max_media_steps must be non-negative.\n");
photonOptions.mediaSpacingFactor = Allow_Float(1.0);
if (photonOptions.mediaSpacingFactor <= 0.0)
Error("media_spacing_factor must be greater than zero.\n");
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
/* max_gather_count = 0 means no photon maps */
if (photonOptions.maxGatherCount > 0)
photonOptions.photonsEnabled = TRUE;
else
photonOptions.photonsEnabled = FALSE;
if(photonOptions.photonsEnabled)
{
/* apply defaults if minimums are not specified */
if (photonOptions.minGatherCount == 0)
photonOptions.minGatherCount = 20;
/* check for range errors */
if (photonOptions.minGatherCount < 0)
Error("min_gather_count cannot be negative.\n");
if (photonOptions.maxGatherCount < 0)
Error("max_gather_count cannot be negative.\n");
if (photonOptions.minGatherCount > photonOptions.maxGatherCount)
Error("min_gather_count must be less than max_gather_count.\n");
}
Parse_End();
END_CASE
/* NK ---- */
CASE (RADIOSITY_TOKEN)
Experimental_Flag |= EF_RADIOS;
/* NK rad */
opts.Radiosity_Enabled = TRUE;
/* NK ---- */
Parse_Begin();
EXPECT
CASE(LOAD_FILE_TOKEN)
if(opts.Radiosity_Load_File_Name)
{
Warn(100,"Filename already given, using new name\n");
POV_FREE(opts.Radiosity_Load_File_Name);
}
opts.Radiosity_Load_File_Name = Parse_String();
END_CASE
CASE(SAVE_FILE_TOKEN)
if(opts.Radiosity_Save_File_Name)
{
Warn(100,"Filename already given, using new name\n");
POV_FREE(opts.Radiosity_Save_File_Name);
}
opts.Radiosity_Save_File_Name = Parse_String();
END_CASE
CASE(ALWAYS_SAMPLE_TOKEN)
opts.Radiosity_Add_On_Final_Trace = (int)Parse_Float();
END_CASE
CASE (PRETRACE_START_TOKEN)
opts.radPretraceStart = Parse_Float();
END_CASE
CASE (PRETRACE_END_TOKEN)
opts.radPretraceEnd = Parse_Float();
END_CASE
CASE (BRIGHTNESS_TOKEN)
if ((opts.Radiosity_Brightness = Parse_Float()) <= 0.0)
{
Error("Radiosity brightness must be a positive number.");
}
END_CASE
CASE (COUNT_TOKEN)
if (( opts.Radiosity_Count = (int)Parse_Float()) <= 0)
{
Error("Radiosity count must be a positive number.");
}
if ( opts.Radiosity_Count > 1600)
{
Error("Radiosity count can not be more than 1600.");
opts.Radiosity_Count = 1600;
}
END_CASE
CASE (DISTANCE_MAXIMUM_TOKEN)
if (( opts.Radiosity_Dist_Max = Parse_Float()) < 0.0)
{
Error("Radiosity distance maximum must be a positive number.");
}
END_CASE
CASE (ERROR_BOUND_TOKEN)
if (( opts.Radiosity_Error_Bound = Parse_Float()) <= 0.0)
{
Error("Radiosity error bound must be a positive number.");
}
END_CASE
CASE (GRAY_THRESHOLD_TOKEN)
opts.Radiosity_Gray = Parse_Float();
if (( opts.Radiosity_Gray < 0.0) || ( opts.Radiosity_Gray > 1.0))
{
Error("Radiosity gray threshold must be from 0.0 to 1.0.");
}
END_CASE
CASE (LOW_ERROR_FACTOR_TOKEN)
if (( opts.Radiosity_Low_Error_Factor = Parse_Float()) <= 0.0)
{
Error("Radiosity low error factor must be a positive number.");
}
END_CASE
CASE (MINIMUM_REUSE_TOKEN)
if (( opts.Radiosity_Min_Reuse = Parse_Float()) < 0.0)
{
Error("Radiosity min reuse can not be a negative number.");
}
END_CASE
CASE (NEAREST_COUNT_TOKEN)
opts.Radiosity_Nearest_Count = (int)Parse_Float();
if (( opts.Radiosity_Nearest_Count < 1) ||
( opts.Radiosity_Nearest_Count > MAX_NEAREST_COUNT))
{
Error("Radiosity nearest count must be a value from 1 to %ld.", (long)MAX_NEAREST_COUNT);
}
END_CASE
CASE (RECURSION_LIMIT_TOKEN)
if (( opts.Radiosity_Recursion_Limit = (int)Parse_Float()) <= 0)
{
Error("Radiosity recursion limit must be a positive number.");
}
END_CASE
/* NK radiosity */
CASE (MAX_SAMPLE_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
opts.Maximum_Sample_Brightness = Parse_Float();
END_CASE
CASE (ADC_BAILOUT_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
if (( opts.Radiosity_ADC_Bailout = Parse_Float()) <= 0)
{
Error("ADC Bailout must be a positive number.");
}
END_CASE
CASE (TNORMAL_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
opts.Radiosity_Use_Normal = (int)Parse_Float();
END_CASE
CASE (MEDIA_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
opts.Radiosity_Use_Media = (int)Parse_Float();
END_CASE
#ifdef MotionBlurPatch
CASE (MOTION_BLUR_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
opts.Radiosity_Use_Motion_Blur = (int)Parse_Float();
END_CASE
/* NK ---- */
#endif
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End();
END_CASE
CASE (STRING_ENCODING_TOKEN)
{
/*YS sept 17 2000 Memory leak */
char *tempstring=Parse_String();
String_Encoding = uniGetEncodingByName( tempstring );
POV_FREE(tempstring); /*YS sept 17 Memory leak */
}
if ( !uniIsEncodingValid( String_Encoding ) ) {
Error( "Invalid value for string_encoding." );
}
END_CASE
CASE (HF_GRAY_16_TOKEN)
if (Allow_Float(1.0)>EPSILON)
{
opts.Options |= HF_GRAY_16;
opts.PaletteOption = GREY; /* Force gray scale preview */
Output_File_Handle->file_type = HF_FTYPE;
}
END_CASE
/* Added by MBP to support reflection-blur */
CASE (REFLECTION_SAMPLES_TOKEN)
Default_Texture->Finish->Reflection_Samples = (int) Parse_Float();
END_CASE
/* Added by MBP 6/27/98 */
CASE (REFLECTION_BLUR_MAX_TOKEN)
opts.Reflection_Blur_Max = (int) Parse_Float();
END_CASE
CASE (REFLECTION_BLUR_MAX_ADC_TOKEN)
opts.Reflection_Blur_Max_ADC = Parse_Float();
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End();
}
#ifdef GlowPatch
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Parse_Glow(GLOW * Glow)
{
MATRIX Matrix;
int Warped = FALSE;
TRANSFORM * Trans = Create_Transform();
TRANSFORM * Temp_Trans = Create_Transform();
TRANSFORM * Trans2;
TURB * Local_Turb = NULL;
VECTOR Local_Vector;
TPATTERN * Warps = (TPATTERN *)POV_MALLOC(sizeof(TPATTERN), "TPATTERN");
Init_TPat_Fields(Warps);
Warps->Type = BOZO_PATTERN;/*Set it to a pattern type to allow turbulence*/
Parse_Begin();
EXPECT
CASE(SIZE_TOKEN)
Glow->Size = Parse_Float();
END_CASE
CASE(RADIUS_TOKEN)
Glow->Cutoff_Radius = Parse_Float();
END_CASE
CASE(FADE_POWER_TOKEN)
Glow->fade_pow = Parse_Float();
END_CASE
CASE(TYPE_TOKEN)
Glow->Glow_Type = (int)Parse_Float();
/*YS sept 22 2000 added type checking*/
if(Glow->Glow_Type < 0 || Glow->Glow_Type > 3)
Error("\nUnknown glow type.\n");
/*YS*/
END_CASE
CASE(LOCATION_TOKEN)
Parse_Vector(Glow->Center);
END_CASE
CASE(COLOUR_TOKEN)
Parse_Colour(Glow->Colour);
END_CASE
CASE (WARP_TOKEN)
Warped = TRUE;
Parse_Begin();
Parse_Warp(&(Warps->Warps));
Parse_End();
END_CASE
CASE (TRANSLATE_TOKEN)
Parse_Vector(Local_Vector);
Compute_Translation_Transform(Temp_Trans, Local_Vector);
Compose_Transforms(Trans, Temp_Trans);
END_CASE
CASE (ROTATE_TOKEN)
Parse_Vector(Local_Vector);
Compute_Rotation_Transform(Temp_Trans, Local_Vector);
Compose_Transforms(Trans, Temp_Trans);
END_CASE
CASE (SCALE_TOKEN)
Parse_Scale_Vector(Local_Vector);
Compute_Scaling_Transform(Trans, Local_Vector);
Compose_Transforms(Trans, Temp_Trans);
END_CASE
CASE (MATRIX_TOKEN)
Parse_Matrix(Matrix);
Compute_Matrix_Transform(Temp_Trans, Matrix);
Compose_Transforms(Trans, Temp_Trans);
END_CASE
CASE (TRANSFORM_TOKEN)
Trans2 = Parse_Transform();
Compose_Transforms(Trans, Trans2);
Destroy_Transform(Trans2);
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End();
if(Warped == TRUE)
{
Glow->Warps = Warps;
}
else
{
Destroy_TPat_Fields(Warps);
POV_FREE(Warps);
}
Transform_Glow(Glow, Trans);
Destroy_Transform(Trans);
Destroy_Transform(Temp_Trans);
}
#endif
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Destroy_Single_Object (OBJECT **ObjectPtr);
/* NK persist - added destroyAllObjects */
void Destroy_Frame(int destroyAllObjects)
{
FOG *Fog, *Next_Fog;
RAINBOW *Rainbow, *Next_Rainbow;
/* can the camera have a name? */
Destroy_Camera (Frame.Camera); Frame.Camera=NULL;
/* Destroy fogs. [DB 12/94] */
for (Fog = Frame.Fog; Fog != NULL;)
{
Next_Fog = Fog->Next;
Destroy_Fog(Fog);
Fog = Next_Fog;
}
Frame.Fog = NULL;
/* Destroy rainbows. [DB 12/94] */
for (Rainbow = Frame.Rainbow; Rainbow != NULL;)
{
Next_Rainbow = Rainbow->Next;
Destroy_Rainbow(Rainbow);
Rainbow = Next_Rainbow;
}
Frame.Rainbow = NULL;
/* Destroy skysphere. [DB 12/94] */
Destroy_Skysphere(Frame.Skysphere);
Frame.Skysphere = NULL;
/* Destroy atmosphere. [DB 1/95] */
Destroy_Media(Frame.Atmosphere);
Frame.Atmosphere = NULL;
#ifdef GlowPatch
if(Frame.NumOfGlows > 0)
{
Destroy_Glow_List(Frame.Glows);
Frame.Glows = NULL;
Frame.NumOfGlows = 0;
}
#endif
/* NK persist */
if(destroyAllObjects)
{
if (Frame.Objects != NULL) {
Destroy_Object (Frame.Objects);
Frame.Objects = NULL;
Frame.Light_Sources = NULL;
}
}
else
{
OBJECT *obj;
while(Frame.Objects != NULL)
{
if (Frame.Objects->Label == NULL)
Destroy_Single_Object(&Frame.Objects);
else
break;
}
obj = Frame.Objects;
while(obj!=NULL && obj->Sibling != NULL)
{
if (obj->Sibling->Label == NULL)
Destroy_Single_Object(&(obj->Sibling));
else
obj=obj->Sibling;
}
}
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static void Parse_Camera (CAMERA **Camera_Ptr)
{
int i;
DBL Direction_Length = 1.0, Up_Length, Right_Length, Handedness;
DBL k1, k2, k3;
VECTOR Local_Vector;
MATRIX Local_Matrix;
TRANSFORM Local_Trans;
CAMERA *New;
Parse_Begin ();
EXPECT
CASE (CAMERA_ID_TOKEN)
Destroy_Camera(*Camera_Ptr);
*Camera_Ptr = Copy_Camera ((CAMERA *) Token.Data);
EXIT
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
New = *Camera_Ptr;
EXPECT
/* Get camera type. [DB 7/94] */
CASE (PERSPECTIVE_TOKEN)
New->Type = PERSPECTIVE_CAMERA;
END_CASE
CASE (ORTHOGRAPHIC_TOKEN)
New->Type = ORTHOGRAPHIC_CAMERA;
/*
* Resize right and up vector to get the same image
* area as we get with the perspective camera.
*/
VSub(Local_Vector, New->Look_At, New->Location);
VLength(k1, Local_Vector);
VLength(k2, New->Direction);
if ((k1 > EPSILON) && (k2 > EPSILON))
{
VScaleEq(New->Right, k1 / k2);
VScaleEq(New->Up, k1 / k2);
}
END_CASE
CASE (FISHEYE_TOKEN)
New->Type = FISHEYE_CAMERA;
END_CASE
CASE (ULTRA_WIDE_ANGLE_TOKEN)
New->Type = ULTRA_WIDE_ANGLE_CAMERA;
END_CASE
CASE (OMNIMAX_TOKEN)
New->Type = OMNIMAX_CAMERA;
END_CASE
CASE (PANORAMIC_TOKEN)
New->Type = PANORAMIC_CAMERA;
END_CASE
CASE (CYLINDER_TOKEN)
i = (int)Parse_Float();
switch (i)
{
case 1: New->Type = CYL_1_CAMERA; break;
case 2: New->Type = CYL_2_CAMERA; break;
case 3: New->Type = CYL_3_CAMERA; break;
case 4: New->Type = CYL_4_CAMERA; break;
}
END_CASE
/* Spherical camera [MH 6/99] */
CASE2 (SPHERICAL_CAMERA_TOKEN,SPHERICAL_TOKEN)
New->Type = SPHERICAL_CAMERA;
END_CASE
CASE (V_ANGLE_TOKEN)
New->V_Angle = Parse_Float();
if (New->V_Angle < 0.0)
{
Error("Negative v_angle.");
}
END_CASE
CASE (H_ANGLE_TOKEN)
New->H_Angle = Parse_Float();
if (New->H_Angle < 0.0)
{
Error("Negative h_angle.");
}
END_CASE
/* Read viewing angle. Scale direction vector if necessary. [DB 7/94] */
CASE (ANGLE_TOKEN)
New->Angle = Parse_Float();
if (New->Angle < 0.0)
{
Error("Negative viewing angle.");
}
if (New->Type == PERSPECTIVE_CAMERA)
{
if (New->Angle >= 180.0)
{
Error("Viewing angle has to be smaller than 180 degrees.");
}
VNormalize(New->Direction, New->Direction);
VLength (Right_Length, New->Right);
Direction_Length = Right_Length / tan(New->Angle * M_PI_360)/2.0;
VScaleEq(New->Direction, Direction_Length);
}
END_CASE
/* Read primary ray pertubation. [DB 7/94] */
CASE (TNORMAL_TOKEN)
Parse_Begin ();
Parse_Tnormal(&(New->Tnormal));
Parse_End ();
END_CASE
CASE (LOCATION_TOKEN)
Parse_Vector(New->Location);
END_CASE
CASE (DIRECTION_TOKEN)
Parse_Vector(New->Direction);
END_CASE
CASE (UP_TOKEN)
Parse_Vector(New->Up);
END_CASE
CASE (RIGHT_TOKEN)
Parse_Vector(New->Right);
END_CASE
CASE (SKY_TOKEN)
Parse_Vector(New->Sky);
END_CASE
CASE (LOOK_AT_TOKEN)
VLength (Direction_Length, New->Direction);
VLength (Up_Length, New->Up);
VLength (Right_Length, New->Right);
VCross (Local_Vector, New->Up, New->Direction);
VDot (Handedness, Local_Vector, New->Right);
Parse_Vector (New->Direction);
Assign_Vector(New->Look_At, New->Direction);
VSub (New->Direction, New->Direction, New->Location);
/* Check for zero length direction vector. */
if (VSumSqr(New->Direction) < EPSILON)
{
Error("Camera location and look_at point must be different.\n");
}
VNormalize (New->Direction, New->Direction);
/* Save Right vector */
Assign_Vector (Local_Vector, New->Right);
VCross (New->Right, New->Sky, New->Direction);
/* Avoid DOMAIN error (from Terry Kanakis) */
if((fabs(New->Right[X]) < EPSILON) &&
(fabs(New->Right[Y]) < EPSILON) &&
(fabs(New->Right[Z]) < EPSILON))
{
/* Restore Right vector*/
Assign_Vector (New->Right, Local_Vector);
}
VNormalize (New->Right, New->Right);
VCross (New->Up, New->Direction, New->Right);
VScale (New->Direction, New->Direction, Direction_Length);
if (Handedness > 0.0)
VScaleEq (New->Right, Right_Length)
else
VScaleEq (New->Right, -Right_Length);
VScaleEq(New->Up, Up_Length);
END_CASE
CASE (TRANSLATE_TOKEN)
Parse_Vector (Local_Vector);
Translate_Camera (New, Local_Vector);
END_CASE
CASE (ROTATE_TOKEN)
Parse_Vector (Local_Vector);
Rotate_Camera (New, Local_Vector);
END_CASE
CASE (SCALE_TOKEN)
Parse_Scale_Vector (Local_Vector);
Scale_Camera (New, Local_Vector);
END_CASE
CASE (TRANSFORM_TOKEN)
#ifndef TransformPatch /* Chris Huff april 2000 */
GET(TRANSFORM_ID_TOKEN)
Transform_Camera (New, (TRANSFORM *)Token.Data);
#else
{
TRANSFORM * Trans = Parse_Transform();
Transform_Camera(New, Trans);
/*YS sept 17 2000 Memory leak*/
POV_FREE(Trans);
}
#endif
END_CASE
CASE (MATRIX_TOKEN)
Parse_Matrix (Local_Matrix);
Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
Transform_Camera (New, &Local_Trans);
END_CASE
#ifdef PostProcessInCameraPatch /*Chris Huff post_process in camera patch*/
CASE (POST_PROCESS_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(50);
#endif
Parse_Post_Process();
END_CASE
#endif
/* Parse focal blur stuff. */
CASE (BLUR_SAMPLES_TOKEN)
New->Blur_Samples = Parse_Float();
if (New->Blur_Samples <= 0)
{
Error("Illegal number of focal blur samples.\n");
}
END_CASE
CASE (CONFIDENCE_TOKEN)
k1 = Parse_Float();
if ((k1 > 0.0) && (k1 < 1.0))
{
New->Confidence = k1;
}
else
{
Warn(0, "Illegal confidence value. Default is used.");
}
END_CASE
CASE (VARIANCE_TOKEN)
k1 = Parse_Float();
if ((k1 >= 0.0) && (k1 <= 1.0))
{
New->Variance = k1;
}
else
{
Warn(0, "Illegal variance value. Default is used.");
}
END_CASE
CASE (APERTURE_TOKEN)
New->Aperture = Parse_Float();
END_CASE
CASE (FOCAL_POINT_TOKEN)
Parse_Vector(Local_Vector);
VSubEq(Local_Vector, New->Location);
VLength (New->Focal_Distance, Local_Vector);
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End ();
/* Make sure the focal distance hasn't been explicitly given */
if ( New->Focal_Distance < 0.0 )
New->Focal_Distance = Direction_Length;
if ( New->Focal_Distance == 0.0 )
New->Focal_Distance = 1.0;
/* Print a warning message if vectors are not perpendicular. [DB 10/94] */
VDot(k1, New->Right, New->Up);
VDot(k2, New->Right, New->Direction);
VDot(k3, New->Up, New->Direction);
if ((fabs(k1) > EPSILON) || (fabs(k2) > EPSILON) || (fabs(k3) > EPSILON))
{
Warn(0, "Camera vectors are not perpendicular. "
"Making look_at the last statement may help.");
}
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Parse_Matrix(MATRIX Matrix)
{
int i, j;
EXPECT
CASE (LEFT_ANGLE_TOKEN)
Matrix[0][0] = Parse_Float();
for (i = 0; i < 4; i++)
{
for (j = !i ? 1 : 0; j < 3; j++)
{
Parse_Comma();
Matrix[i][j] = Parse_Float();
}
Matrix[i][3] = (i != 3 ? 0.0 : 1.0);
}
GET (RIGHT_ANGLE_TOKEN);
/* Check to see that we aren't scaling any dimension by zero */
for (i = 0; i < 3; i++)
{
if (fabs(Matrix[0][i]) < EPSILON && fabs(Matrix[1][i]) < EPSILON &&
fabs(Matrix[2][i]) < EPSILON)
{
Warn(0,"Illegal matrix column: Scale by 0.0. Changed to 1.0.");
Matrix[i][i] = 1.0;
}
}
EXIT
END_CASE
OTHERWISE
Parse_Error (LEFT_ANGLE_TOKEN);
END_CASE
END_EXPECT
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
#ifndef TransformPatch /* Chris Huff april 2000 */
static
TRANSFORM *Parse_Transform ()
{
MATRIX Local_Matrix;
TRANSFORM *New, Local_Trans;
VECTOR Local_Vector;
#ifdef InverseTransformsPatch /*Chris Huff arpil 2000 */
int isInverse = FALSE;
#endif
Parse_Begin ();
New = Create_Transform ();
EXPECT
#ifdef InverseTransformsPatch /*Chris Huff arpil 2000 */
CASE(INVERSE_TOKEN)
isInverse = TRUE;
END_CASE
#endif
CASE(TRANSFORM_ID_TOKEN)
Compose_Transforms (New, (TRANSFORM *)Token.Data);
END_CASE
CASE (TRANSFORM_TOKEN)
GET(TRANSFORM_ID_TOKEN)
Compose_Transforms(New, (TRANSFORM *)Token.Data);
END_CASE
CASE (TRANSLATE_TOKEN)
Parse_Vector (Local_Vector);
Compute_Translation_Transform(&Local_Trans, Local_Vector);
Compose_Transforms (New, &Local_Trans);
END_CASE
CASE (ROTATE_TOKEN)
Parse_Vector (Local_Vector);
Compute_Rotation_Transform(&Local_Trans, Local_Vector);
Compose_Transforms (New, &Local_Trans);
END_CASE
CASE (SCALE_TOKEN)
Parse_Scale_Vector (Local_Vector);
Compute_Scaling_Transform(&Local_Trans, Local_Vector);
Compose_Transforms (New, &Local_Trans);
END_CASE
CASE (MATRIX_TOKEN)
Parse_Matrix(Local_Matrix);
Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
Compose_Transforms (New, &Local_Trans);
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End ();
#ifdef InverseTransformsPatch /*Chris Huff arpil 2000 */
if(isInverse == TRUE)
{
MInvers(New->matrix, New->matrix);
MInvers(New->inverse, New->inverse);
}
#endif
return (New);
}
#else
/*Chris Huff transform patch*/
TRANSFORM *Parse_Transform ()
{
TRANSFORM * Trans = NULL;
Get_Token();
if(Token.Token_Id == TRANSFORM_ID_TOKEN)
{
/*using old "transform TRANS_IDENT" syntax*/
Trans=Create_Transform();
Compose_Transforms(Trans, (TRANSFORM *)Token.Data);
}
else
{
/*using new "transform {TRANS}" syntax*/
Unget_Token();
Trans = Parse_Transform_Block();
}
return Trans;
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static/*Chris Huff transform patch*/
TRANSFORM *Parse_Transform_Block ()
{
MATRIX Local_Matrix;
TRANSFORM *New, Local_Trans;
VECTOR Local_Vector;
#ifdef InverseTransformsPatch /*Chris Huff arpil 2000 */
int isInverse = FALSE;
#endif
Parse_Begin ();
New = Create_Transform ();
EXPECT
#ifdef InverseTransformsPatch /*Chris Huff arpil 2000 */
CASE(INVERSE_TOKEN)
isInverse = TRUE;
END_CASE
#endif
CASE(TRANSFORM_ID_TOKEN)
Compose_Transforms (New, (TRANSFORM *)Token.Data);
END_CASE
CASE (TRANSFORM_TOKEN)
{
TRANSFORM * Trans = Parse_Transform();
Compose_Transforms(New, Trans);
}
END_CASE
CASE (TRANSLATE_TOKEN)
Parse_Vector (Local_Vector);
Compute_Translation_Transform(&Local_Trans, Local_Vector);
Compose_Transforms (New, &Local_Trans);
END_CASE
CASE (ROTATE_TOKEN)
Parse_Vector (Local_Vector);
Compute_Rotation_Transform(&Local_Trans, Local_Vector);
Compose_Transforms (New, &Local_Trans);
END_CASE
CASE (SCALE_TOKEN)
Parse_Scale_Vector (Local_Vector);
Compute_Scaling_Transform(&Local_Trans, Local_Vector);
Compose_Transforms (New, &Local_Trans);
END_CASE
CASE (MATRIX_TOKEN)
Parse_Matrix(Local_Matrix);
Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
Compose_Transforms (New, &Local_Trans);
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End ();
#ifdef InverseTransformsPatch /*Chris Huff arpil 2000 */
if(isInverse == TRUE)
{
MInvers(New->matrix, New->matrix);
MInvers(New->inverse, New->inverse);
}
#endif
return (New);
}
#endif
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
#ifdef SetPatch
void Parse_Declare(int Modify_Only)
#else
void Parse_Declare ()
#endif
{
int Previous=-1; /* tw */
int Local_Index,Local_Flag;
SYM_ENTRY *Temp_Entry;
char local=0;
/* NK 1999 - use $ for #declare - added PERCENT_TOKEN */
/*Chris Huff 2000.8.30 - added #set */
#ifdef SetPatch
Local_Flag = (Token.Token_Id==LOCAL_TOKEN || Token.Token_Id==PERCENT_TOKEN);
if(Local_Flag)
{
Local_Index=Table_Index;
}
else
{
if(Token.Token_Id==SET_TOKEN || Modify_Only == TRUE)
{
/*Search for most recent table with an identifier with this name
Parts copied from Read_Symbol*/
int Idx;
int Found = FALSE;
Get_Token();
/* Search tables from newest to oldest */
for(Idx=Table_Index; Idx > 0; Idx--)
{
if(Find_Symbol(Idx, Token.Token_String) != NULL)
{
Local_Index = Idx;
Found = TRUE;
break;
}
}
if(Found != TRUE)
{
Error("#set cannot assign to uninitialized identifier %s.\n", Token.Token_String);
}
Unget_Token();
}
else
{
Local_Index=1;
}
}
#else
if (Local_Flag=(Token.Token_Id==LOCAL_TOKEN || Token.Token_Id==PERCENT_TOKEN))
{
Local_Index=Table_Index;
}
else
{
Local_Index=1;
}
#endif
LValue_Ok = TRUE;
EXPECT
CASE (IDENTIFIER_TOKEN)
Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
Token.NumberPtr = &(Temp_Entry->Token_Number);
Token.DataPtr = &(Temp_Entry->Data);
Previous = Token.Token_Id;
EXIT
END_CASE
/*YS*/
#ifdef POVISO
CASE (FUNC_ID_TOKEN)
#endif
#ifdef SplinePatch
CASE(SPLINE_ID_TOKEN )
#endif
#ifdef RBezierPatch
CASE(TRIMMED_BY_ID_TOKEN )
#endif
/*YS*/
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
CASE4 (TNORMAL_ID_TOKEN, FINISH_ID_TOKEN, TEXTURE_ID_TOKEN, OBJECT_ID_TOKEN)
CASE4 (COLOUR_MAP_ID_TOKEN, TRANSFORM_ID_TOKEN, CAMERA_ID_TOKEN, PIGMENT_ID_TOKEN)
CASE4 (SLOPE_MAP_ID_TOKEN,NORMAL_MAP_ID_TOKEN,TEXTURE_MAP_ID_TOKEN,COLOUR_ID_TOKEN)
CASE4 (PIGMENT_MAP_ID_TOKEN, MEDIA_ID_TOKEN,STRING_ID_TOKEN,INTERIOR_ID_TOKEN)
CASE5 (DENSITY_MAP_ID_TOKEN, ARRAY_ID_TOKEN, DENSITY_ID_TOKEN,UV_ID_TOKEN,VECTOR_4D_ID_TOKEN)
CASE4 (RAINBOW_ID_TOKEN, FOG_ID_TOKEN, SKYSPHERE_ID_TOKEN,MATERIAL_ID_TOKEN)
if (Local_Flag && (Token.Table_Index != Table_Index))
{
Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
Token.NumberPtr = &(Temp_Entry->Token_Number);
Token.DataPtr = &(Temp_Entry->Data);
Previous = IDENTIFIER_TOKEN;
}
else
{
Previous = Token.Token_Id;
}
EXIT
END_CASE
CASE (EMPTY_ARRAY_TOKEN)
Previous = Token.Token_Id;
EXIT
END_CASE
CASE2 (VECTOR_FUNCT_TOKEN, FLOAT_FUNCT_TOKEN)
switch(Token.Function_Id)
{
case VECTOR_ID_TOKEN:
case FLOAT_ID_TOKEN:
if (Local_Flag && (Token.Table_Index != Table_Index))
{
Temp_Entry = Add_Symbol (Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
Token.NumberPtr = &(Temp_Entry->Token_Number);
Token.DataPtr = &(Temp_Entry->Data);
}
Previous = Token.Function_Id;
break;
default:
Parse_Error(IDENTIFIER_TOKEN);
break;
}
EXIT
END_CASE
OTHERWISE
Parse_Error(IDENTIFIER_TOKEN);
END_CASE
END_EXPECT
LValue_Ok = FALSE;
GET (EQUALS_TOKEN);
if (!Parse_RValue (Previous,Token.NumberPtr,Token.DataPtr, FALSE,TRUE))
{
Parse_Error_Str("RValue to declare");
}
}
int Parse_RValue (int Previous, int *NumberPtr, void **DataPtr, int ParFlag, int SemiFlag)
{
EXPRESS Local_Express;
COLOUR *Local_Colour;
PIGMENT *Local_Pigment;
TNORMAL *Local_Tnormal;
FINISH *Local_Finish;
TEXTURE *Local_Texture, *Temp_Texture;
TRANSFORM *Local_Trans;
OBJECT *Local_Object;
CAMERA *Local_Camera;
IMEDIA *Local_Media;
PIGMENT *Local_Density;
INTERIOR *Local_Interior;
MATERIAL *Local_Material;
void *Temp_Data;
POV_PARAM *New_Par;
int Found=TRUE;
int Temp_Count=30000;
int Old_Ok=Ok_To_Declare;
int Terms;
#ifdef RBezierPatch
TRIM_SHAPE *Local_Trim;
#endif
EXPECT
CASE4 (TNORMAL_ID_TOKEN, FINISH_ID_TOKEN, TEXTURE_ID_TOKEN, OBJECT_ID_TOKEN)
CASE4 (COLOUR_MAP_ID_TOKEN, TRANSFORM_ID_TOKEN, CAMERA_ID_TOKEN, PIGMENT_ID_TOKEN)
CASE4 (SLOPE_MAP_ID_TOKEN,NORMAL_MAP_ID_TOKEN,TEXTURE_MAP_ID_TOKEN,ARRAY_ID_TOKEN)
CASE4 (PIGMENT_MAP_ID_TOKEN, MEDIA_ID_TOKEN,INTERIOR_ID_TOKEN,DENSITY_ID_TOKEN)
CASE4 (DENSITY_MAP_ID_TOKEN, RAINBOW_ID_TOKEN, FOG_ID_TOKEN, SKYSPHERE_ID_TOKEN)
/* bugfix by Mark Wagner sept 2000*/
CASE2 (MATERIAL_ID_TOKEN, SPLINE_ID_TOKEN)
if (ParFlag)
{
New_Par = (POV_PARAM *)POV_MALLOC(sizeof(POV_PARAM),"parameter");
New_Par->NumberPtr = Token.NumberPtr;
New_Par->DataPtr = Token.DataPtr;
*NumberPtr = PARAMETER_ID_TOKEN;
*DataPtr = (void *)New_Par;
}
else
{
Temp_Data = (void *) Copy_Identifier((void *)*Token.DataPtr,*Token.NumberPtr);
*NumberPtr = *Token.NumberPtr;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
}
EXIT
END_CASE
CASE (IDENTIFIER_TOKEN)
if (ParFlag)
{
Error("Cannot pass uninitialized identifier as macro parameter.\nInitialize first.\n");
}
else
{
Error("Cannot assign uninitialized identifier.\n");
}
EXIT
END_CASE
CASE_COLOUR
Local_Colour = Create_Colour();
Ok_To_Declare = FALSE;
Parse_Colour (*Local_Colour);
if (SemiFlag)
{
Parse_Semi_Colon();
}
Ok_To_Declare = TRUE;
*NumberPtr = COLOUR_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = (void *) Local_Colour;
EXIT
END_CASE
CASE_VECTOR
Ok_To_Declare = FALSE;
if (ParFlag &&
( ( (Token.Token_Id==FLOAT_FUNCT_TOKEN) &&
(Token.Function_Id==FLOAT_ID_TOKEN)
) ||
( (Token.Token_Id==VECTOR_FUNCT_TOKEN) &&
(Token.Function_Id==VECTOR_ID_TOKEN)
) ||
(Token.Token_Id==VECTOR_4D_ID_TOKEN)
||
(Token.Token_Id==UV_ID_TOKEN)
)
)
{
Temp_Count=token_count;
}
Terms = Parse_Unknown_Vector (Local_Express);
if (SemiFlag)
{
Parse_Semi_Colon();
}
Temp_Count -= token_count;
if ((Temp_Count==-1) || (Temp_Count==1000))
{
New_Par = (POV_PARAM *)POV_MALLOC(sizeof(POV_PARAM),"parameter");
New_Par->NumberPtr = Token.NumberPtr;
New_Par->DataPtr = Token.DataPtr;
*NumberPtr = PARAMETER_ID_TOKEN;
*DataPtr = (void *)New_Par;
}
else
{
switch(Terms)
{
case 1:
*NumberPtr = FLOAT_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = (void *) Create_Float();
*((DBL *)*DataPtr) = Local_Express[X];
break;
case 2:
*NumberPtr = UV_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = (void *) Create_UV_Vect();
Assign_UV_Vect(*DataPtr, Local_Express);
break;
case 3:
*NumberPtr = VECTOR_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = (void *) Create_Vector();
Assign_Vector(*DataPtr ,Local_Express);
break;
case 4:
*NumberPtr = VECTOR_4D_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = (void *) Create_Vector_4D();
Assign_Vector_4D(*DataPtr, Local_Express);
break;
case 5:
*NumberPtr = COLOUR_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = (void *) Create_Colour();
Assign_Colour_Express((COLC*)(*DataPtr), Local_Express); /* NK fix assign_colour bug */
break;
}
}
Ok_To_Declare = TRUE;
EXIT
END_CASE
CASE (PIGMENT_TOKEN)
Local_Pigment = Copy_Pigment((Default_Texture->Pigment));
Parse_Begin ();
Parse_Pigment (&Local_Pigment);
Parse_End ();
*NumberPtr = PIGMENT_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = (void *)Local_Pigment;
EXIT
END_CASE
CASE (TNORMAL_TOKEN)
Local_Tnormal = Copy_Tnormal((Default_Texture->Tnormal));
Parse_Begin ();
Parse_Tnormal (&Local_Tnormal);
Parse_End ();
*NumberPtr = TNORMAL_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = (void *) Local_Tnormal;
EXIT
END_CASE
CASE (FINISH_TOKEN)
Local_Finish = Copy_Finish((Default_Texture->Finish));
Parse_Finish (&Local_Finish);
*NumberPtr = FINISH_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = (void *) Local_Finish;
EXIT
END_CASE
CASE (CAMERA_TOKEN)
Local_Camera = Copy_Camera(Default_Camera);
Parse_Camera (&Local_Camera);
*NumberPtr = CAMERA_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = (void *) Local_Camera;
EXIT
END_CASE
#ifdef RBezierPatch
CASE (TRIMMED_BY_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Local_Trim= Parse_Trim();
*NumberPtr = TRIMMED_BY_ID_TOKEN;
Test_Redefine(Previous, NumberPtr, *DataPtr);
*DataPtr = (void *)(Local_Trim);
EXIT
END_CASE
#endif
CASE (TEXTURE_TOKEN)
Parse_Begin ();
Local_Texture = Parse_Texture ();
Parse_End ();
Temp_Texture=NULL;
Link_Textures(&Temp_Texture, Local_Texture);
Ok_To_Declare = FALSE;
EXPECT
CASE (TEXTURE_TOKEN)
Parse_Begin ();
Local_Texture = Parse_Texture ();
Parse_End ();
Link_Textures(&Temp_Texture, Local_Texture);
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
*NumberPtr = TEXTURE_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = (void *)Temp_Texture;
Ok_To_Declare = TRUE;
EXIT
END_CASE
CASE (COLOUR_MAP_TOKEN)
Temp_Data=(void *) Parse_Colour_Map ();
*NumberPtr = COLOUR_MAP_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
CASE (PIGMENT_MAP_TOKEN)
Temp_Data = (void *) Parse_Blend_Map (PIGMENT_TYPE,NO_PATTERN);
*NumberPtr = PIGMENT_MAP_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
#ifdef SplinePatch
CASE (SPLINE_TOKEN)
#ifdef UnofficialBlocking
parseUnofficialFeature(30);
#endif
Parse_Begin();
Temp_Data=(char *) Parse_Spline();
Parse_End();
*NumberPtr = SPLINE_ID_TOKEN;
Test_Redefine( Previous, NumberPtr, *DataPtr );
*DataPtr = (void *)Temp_Data;
EXIT
END_CASE
#endif
CASE (DENSITY_MAP_TOKEN)
Temp_Data = (void *) Parse_Blend_Map (DENSITY_TYPE,NO_PATTERN);
*NumberPtr = DENSITY_MAP_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
CASE (SLOPE_MAP_TOKEN)
Temp_Data = (void *) Parse_Blend_Map (SLOPE_TYPE,NO_PATTERN);
*NumberPtr = SLOPE_MAP_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
CASE (TEXTURE_MAP_TOKEN)
Temp_Data = (void *) Parse_Blend_Map (TEXTURE_TYPE,NO_PATTERN);
*NumberPtr = TEXTURE_MAP_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
CASE (NORMAL_MAP_TOKEN)
Temp_Data = (void *) Parse_Blend_Map (NORMAL_TYPE,NO_PATTERN);
*NumberPtr = NORMAL_MAP_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
CASE (RAINBOW_TOKEN)
Temp_Data = (void *) Parse_Rainbow();
*NumberPtr = RAINBOW_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
CASE (FOG_TOKEN)
Temp_Data = (void *) Parse_Fog();
*NumberPtr = FOG_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
CASE (MEDIA_TOKEN)
Local_Media = NULL;
Parse_Media(&Local_Media);
Temp_Data = (void *)Local_Media;
*NumberPtr = MEDIA_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
CASE (DENSITY_TOKEN)
Local_Density = NULL;
Parse_Begin ();
Parse_Media_Density_Pattern (&Local_Density);
Parse_End ();
*NumberPtr = DENSITY_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = (void *)Local_Density;
EXIT
END_CASE
CASE (INTERIOR_TOKEN)
Local_Interior = NULL;
Parse_Interior(&Local_Interior);
Temp_Data = (void *)Local_Interior;
*NumberPtr = INTERIOR_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
CASE (MATERIAL_TOKEN)
Local_Material = Create_Material();
Parse_Material(Local_Material);
Temp_Data = (void *)Local_Material;
*NumberPtr = MATERIAL_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
CASE (SKYSPHERE_TOKEN)
Temp_Data = (void *) Parse_Skysphere();
*NumberPtr = SKYSPHERE_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
CASE (TRANSFORM_TOKEN)
#ifndef TransformPatch /* Chris Huff april 2000 */
Local_Trans = Parse_Transform ();
#else
Local_Trans = Parse_Transform_Block ();
#endif
*NumberPtr = TRANSFORM_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = (void *) Local_Trans;
EXIT
END_CASE
/** poviso: May 97, Mar 99 for v3.1 R.S. **/
#ifdef POVISO
CASE (FUNCTION_TOKEN)
Temp_Data = (char *)Parse_Function ();
*NumberPtr = FUNC_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
#endif
/** --- **/
#ifdef TimeDatePatch
CASE(GET_DATE_TOKEN) /*YS get date and time string*/
#endif
CASE4 (STRING_LITERAL_TOKEN,CHR_TOKEN,SUBSTR_TOKEN,STR_TOKEN)
CASE4 (CONCAT_TOKEN,STRUPR_TOKEN,STRLWR_TOKEN,STRING_ID_TOKEN)
UNGET
Temp_Data = Parse_String();
*NumberPtr = STRING_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
CASE (ARRAY_TOKEN)
Temp_Data = (void *) Parse_Array_Declare();
*NumberPtr = ARRAY_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = Temp_Data;
EXIT
END_CASE
OTHERWISE
UNGET
Local_Object = Parse_Object ();
Found=(Local_Object!=NULL);
*NumberPtr = OBJECT_ID_TOKEN;
Test_Redefine(Previous,NumberPtr,*DataPtr);
*DataPtr = (void *) Local_Object;
EXIT
END_CASE
END_EXPECT
Ok_To_Declare=Old_Ok;
return(Found);
}
void Destroy_Ident_Data (void *Data, int Type)
{
int i;
POV_ARRAY *a;
DATA_FILE *Temp_File;
if (Data==NULL)
{
return;
}
switch (Type)
{
case COLOUR_ID_TOKEN:
Destroy_Colour((COLOUR *)Data);
break;
case VECTOR_ID_TOKEN:
Destroy_Vector((VECTOR *)Data);
break;
case UV_ID_TOKEN:
Destroy_UV_Vect((UV_VECT *)Data);
break;
case VECTOR_4D_ID_TOKEN:
Destroy_Vector((VECTOR_4D *)Data);
break;
case FLOAT_ID_TOKEN:
Destroy_Float((DBL *)Data);
break;
case PIGMENT_ID_TOKEN:
case DENSITY_ID_TOKEN:
Destroy_Pigment((PIGMENT *)Data);
break;
case TNORMAL_ID_TOKEN:
Destroy_Tnormal((TNORMAL *)Data);
break;
case FINISH_ID_TOKEN:
Destroy_Finish((FINISH *)Data);
break;
case MEDIA_ID_TOKEN:
Destroy_Media((IMEDIA *)Data);
break;
case INTERIOR_ID_TOKEN:
Destroy_Interior((INTERIOR *)Data);
break;
case MATERIAL_ID_TOKEN:
Destroy_Material((MATERIAL *)Data);
break;
case TEXTURE_ID_TOKEN:
Destroy_Textures((TEXTURE *)Data);
break;
case OBJECT_ID_TOKEN:
Destroy_Object((OBJECT *)Data);
break;
case COLOUR_MAP_ID_TOKEN:
case PIGMENT_MAP_ID_TOKEN:
case SLOPE_MAP_ID_TOKEN:
case TEXTURE_MAP_ID_TOKEN:
case NORMAL_MAP_ID_TOKEN:
case DENSITY_MAP_ID_TOKEN:
Destroy_Blend_Map((BLEND_MAP *)Data);
break;
case TRANSFORM_ID_TOKEN:
Destroy_Transform((TRANSFORM *)Data);
break;
case CAMERA_ID_TOKEN:
Destroy_Camera((CAMERA *)Data);
break;
case RAINBOW_ID_TOKEN:
Destroy_Rainbow((RAINBOW *)Data);
break;
case FOG_ID_TOKEN:
Destroy_Fog((FOG *)Data);
break;
case SKYSPHERE_ID_TOKEN:
Destroy_Skysphere((SKYSPHERE *)Data);
break;
case MACRO_ID_TOKEN:
Destroy_Macro((POV_MACRO *)Data);
break;
case STRING_ID_TOKEN:
POV_FREE((char *)Data);
break;
case ARRAY_ID_TOKEN:
a=(POV_ARRAY *)Data;
for (i=0; i<a->Total; i++)
{
Destroy_Ident_Data (a->DataPtrs[i],a->Type);
}
POV_FREE(a->DataPtrs);
POV_FREE(a);
break;
case PARAMETER_ID_TOKEN:
POV_FREE(Data);
break;
case FILE_ID_TOKEN:
Temp_File=(DATA_FILE *)Data;
#ifdef FastMacroPatch
if (Temp_File->Close!=NULL)
{
Data_File_Close(Temp_File);
}
#else
if (Temp_File->File!=NULL)
{
fflush(Temp_File->File);
fclose(Temp_File->File);
}
#endif
if (Temp_File->Filename!=NULL)
{
POV_FREE(Temp_File->Filename);
}
POV_FREE(Data);
break;
case SPLINE_ID_TOKEN:
Destroy_Spline((SPLINE2 *)Data);
break;
}
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static void Link (OBJECT *New_Object, OBJECT **Field, OBJECT **Old_Object_List)
{
*Field = *Old_Object_List;
*Old_Object_List = New_Object;
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Link_Textures (TEXTURE **Old_Textures, TEXTURE *New_Textures)
{
TEXTURE *Layer;
if (New_Textures == NULL)
return;
if ((*Old_Textures) != NULL)
{
if ((*Old_Textures)->Type != PLAIN_PATTERN)
{
Error("Cannot layer over a patterned texture.\n");
}
}
for (Layer = New_Textures;
Layer->Next != NULL;
Layer = (TEXTURE *)Layer->Next)
{
/* NK layers - 1999 June 10 - for backwards compatiblity with layered textures */
#ifdef UnofficialBlocking
if(opts.unofficialVersion<0)
#else
if(opts.Language_Version<=310)
#endif
Convert_Filter_To_Transmit(Layer->Pigment);
/* NK ---- */
}
/* NK layers - 1999 Nov 16 - for backwards compatiblity with layered textures */
if ((opts.Language_Version<=310) && (*Old_Textures!=NULL))
Convert_Filter_To_Transmit(Layer->Pigment);
/* NK ---- */
Layer->Next = (TPATTERN *)*Old_Textures;
*Old_Textures = New_Textures;
if ((New_Textures->Type != PLAIN_PATTERN) && (New_Textures->Next != NULL))
{
Error("Cannot layer a patterned texture over another.\n");
}
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
char *Get_Token_String (TOKEN Token_Id)
{
register int i;
for (i = 0 ; i < LAST_TOKEN ; i++)
if (Reserved_Words[i].Token_Number == Token_Id)
return (Reserved_Words[i].Token_Name);
return ("");
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Test_Redefine(TOKEN Previous, TOKEN *NumberPtr, void *Data)
{
/*char *oldt, *newt;*/
if ((Previous == IDENTIFIER_TOKEN) || (Previous == EMPTY_ARRAY_TOKEN))
{
return;
}
/* NK 1998 - allow user to redefine all identifiers! */
#define ALLOW_REDEFINE
#ifdef ALLOW_REDEFINE
if (getUnofficialVersion() > 0)
{
Destroy_Ident_Data(Data,Previous);
}
else
{
#endif
if (Previous == *NumberPtr)
{
Destroy_Ident_Data(Data,*NumberPtr);
}
else
{
char *oldt, *newt;
oldt = Get_Token_String (Previous);
newt = Get_Token_String (*NumberPtr);
*NumberPtr = Previous;
Error ("Attempted to redefine %s as %s.", oldt, newt);
}
#ifdef ALLOW_REDEFINE
}
#endif
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Parse_Error (TOKEN Token_Id)
{
char *expected;
expected = Get_Token_String (Token_Id);
Parse_Error_Str(expected);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Parse_Error_Str (char *str)
{
Where_Error ();
Error_Line("%s expected but", str);
Found_Instead ();
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static void Found_Instead ()
{
char *found;
Stage=STAGE_FOUND_INSTEAD;
switch(Token.Token_Id)
{
case IDENTIFIER_TOKEN:
Error (" undeclared identifier '%s' found instead.\n", Token.Token_String);
break;
case VECTOR_FUNCT_TOKEN:
found = Get_Token_String (Token.Function_Id);
Error (" vector function '%s' found instead.\n", found);
break;
case FLOAT_FUNCT_TOKEN:
found = Get_Token_String (Token.Function_Id);
Error (" float function '%s' found instead.\n", found);
break;
case COLOUR_KEY_TOKEN:
found = Get_Token_String (Token.Function_Id);
Error (" color keyword '%s' found instead.\n", found);
break;
default:
found = Get_Token_String (Token.Token_Id);
Error (" %s found instead.\n", found);
}
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Warn_State (TOKEN Token_Id,TOKEN Type)
{
char *found;
char *should;
found = Get_Token_String (Token_Id);
should = Get_Token_String (Type);
Warning (150, "%s:%d: warning: Found %s that should be in %s statement.\n",
Token.Filename, Token.Token_Line_No+1, found, should);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Warn (int Level, char *str)
{
if (opts.Language_Version < Level)
return;
Warning(Level, "%s:%d: warning: %s\n", Token.Filename, Token.Token_Line_No+1, str);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void MAError (char *str,size_t size)
{
Error ("Out of memory. Cannot allocate %ld bytes for %s.\n",size,str);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static void Post_Process (OBJECT *Object,OBJECT *Parent)
{
DBL Volume;
OBJECT *Sib;
FINISH *Finish;
if (Object == NULL)
{
return;
}
if (Object->Type & LT_SRC_UNION_OBJECT)
{
for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
{
Post_Process(Sib, Object);
}
return;
}
Post_Light_Groups(Object);
/* Promote texture etc. from parent to children. */
if (Parent != NULL)
{
if (Object->Texture == NULL)
{
Object->Texture = Copy_Texture_Pointer(Parent->Texture);
/* NK 1998 copy uv_mapping flag if and only if we copy the texture */
if (Test_Flag(Parent, UV_FLAG))
Set_Flag(Object, UV_FLAG);
/* NK ---- */
}
#ifdef InteriorTexturePatch /* fix from Nicolas Calimet july 2000 */
if (Object->Interior_Texture == NULL)
{
Object->Interior_Texture = Copy_Texture_Pointer(Parent->Interior_Texture);
if (Test_Flag(Parent, UV_FLAG))
Set_Flag(Object, UV_FLAG);
}
#endif
if (Object->Interior == NULL)
{
Object->Interior = Copy_Interior_Pointer(Parent->Interior);
}
if (Test_Flag(Parent, NO_SHADOW_FLAG))
{
Set_Flag(Object, NO_SHADOW_FLAG);
}
/* NK phmap */
/* promote photon mapping flags to child */
if (Parent->Ph_Flags & PH_FLAG_TARGET)
{
Object->Ph_Flags |= PH_FLAG_TARGET;
Object->Ph_Density = Parent->Ph_Density;
CheckPassThru(Object, PH_FLAG_TARGET);
}
if(Parent->Ph_Flags & PH_FLAG_PASSTHRU)
{
Object->Ph_Flags |= PH_FLAG_PASSTHRU;
CheckPassThru(Object, PH_FLAG_PASSTHRU);
}
if (Parent->Ph_Flags & PH_FLAG_RFL_ON)
{
SET_PH_FLAG(Object, PH_FLAG_RFL_ON, PH_FLAG_RFL_OFF);
}
else if (Parent->Ph_Flags & PH_FLAG_RFL_OFF)
{
SET_PH_FLAG(Object, PH_FLAG_RFL_OFF, PH_FLAG_RFL_ON);
}
if (Parent->Ph_Flags & PH_FLAG_RFR_ON)
{
SET_PH_FLAG(Object, PH_FLAG_RFR_ON, PH_FLAG_RFR_OFF);
CheckPassThru(Object, PH_FLAG_RFR_ON);
}
else if (Parent->Ph_Flags & PH_FLAG_RFR_OFF)
{
SET_PH_FLAG(Object, PH_FLAG_RFR_OFF, PH_FLAG_RFR_ON);
}
if(Parent->Ph_Flags & PH_FLAG_IGNORE_PHOTONS)
{
Object->Ph_Flags |= PH_FLAG_IGNORE_PHOTONS;
}
/* NK ---- */
#ifdef MotionBlurPatch
if(Parent->TimeStamp)
{
Object->TimeStamp = Parent->TimeStamp;
}
#endif
}
if (Object->Interior != NULL)
{
Post_Media(Object->Interior->IMedia);
}
if ((Object->Texture == NULL) &&
!(Object->Type & TEXTURED_OBJECT) &&
!(Object->Type & LIGHT_SOURCE_OBJECT))
{
#ifdef MultiTextureCsgPatch
if (Parent)
{
if(Parent->Methods != &CSG_Intersection_Methods ||
!Test_Flag(Parent, MULTITEXTURE_FLAG))
{
Object->Texture = Copy_Textures(Default_Texture);
}
}
else
#endif
Object->Texture = Copy_Textures(Default_Texture);
}
Post_Textures(Object->Texture); /*moved cey 6/97*/
if (Object->Type & LIGHT_SOURCE_OBJECT)
{
((LIGHT_SOURCE *)Object)->Next_Light_Source = Frame.Light_Sources;
if (((LIGHT_SOURCE *)Object)->Projected_Through_Object != NULL) {
if (((LIGHT_SOURCE *)Object)->Projected_Through_Object->Interior != NULL){
Destroy_Interior(((LIGHT_SOURCE *)Object)->Projected_Through_Object->Interior);
((LIGHT_SOURCE *)Object)->Projected_Through_Object->Interior=NULL;
Warn(400,"Projected through objects can not have interior, interior removed.\n");
}
if (((LIGHT_SOURCE *)Object)->Projected_Through_Object->Texture != NULL) {
Destroy_Textures(((LIGHT_SOURCE *)Object)->Projected_Through_Object->Texture);
((LIGHT_SOURCE *)Object)->Projected_Through_Object->Texture = NULL;
Warn(400,"Projected through objects can not have texture, texture removed.\n");
}
}
Frame.Light_Sources = (LIGHT_SOURCE *)Object;
Frame.Number_Of_Light_Sources++;
}
else
{
/* If there is no interior create one. */
if (Object->Interior == NULL)
{
Object->Interior = Create_Interior();
}
/* Promote hollow flag to interior. */
Object->Interior->hollow = (Test_Flag(Object, HOLLOW_FLAG) != FALSE);
/* Promote finish's IOR to interior IOR. */
if (Object->Texture != NULL)
{
if (Object->Texture->Type == PLAIN_PATTERN)
{
if ((Finish = Object->Texture->Finish) != NULL)
{
if (Finish->Temp_IOR >= 0.0)
{
Object->Interior->IOR = Finish->Temp_IOR;
Object->Interior->Dispersion = Finish->Temp_Dispersion;
}
if (Finish->Temp_Caustics >= 0.0)
{
Object->Interior->Caustics = Finish->Temp_Caustics;
}
Object->Interior->Old_Refract = Finish->Temp_Refract;
}
}
}
/* If there is no IOR specified use the atmopshere ior. */
if (Object->Interior->IOR == 0.0)
{
Object->Interior->IOR = Frame.Atmosphere_IOR;
Object->Interior->Dispersion = Frame.Atmosphere_Dispersion;
}
}
if (Object->Type & COMPOUND_OBJECT)
{
for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
{
Post_Process(Sib, Object);
}
}
#define PUT_DOUBLE_ILL_ON_PLAIN_PATTERNS 0
#if(PUT_DOUBLE_ILL_ON_PLAIN_PATTERNS)
else
{
if (Object->Texture != NULL)
{
if (Object->Texture->Type == PLAIN_PATTERN)
{
if (Object->Texture->Tnormal != NULL)
{
/* NK 1998 double_illuminate */
/*Object->Type |= DOUBLE_ILLUMINATE;*/
Set_Flag(Object, DOUBLE_ILLUMINATE_FLAG);
/* NK ---- */
}
}
}
}
#endif
/* Test wether the object is finite or infinite. [DB 9/94] */
BOUNDS_VOLUME(Volume, Object->BBox);
if (Volume > INFINITE_VOLUME)
{
Set_Flag(Object, INFINITE_FLAG);
}
/* Test wether the object is opaque or not. [DB 8/94] */
if ((Object->Methods != &Blob_Methods) &&
(Object->Methods != &Mesh_Methods) &&
(Test_Opacity(Object->Texture))
#ifdef InteriorTexturePatch
&&
(
(!Object->Interior_Texture) ||
Test_Opacity(Object->Interior_Texture)
)
#endif
)
{
Set_Flag(Object, OPAQUE_FLAG);
}
else
{
/* Objects with multiple textures have to be handled separately. */
if (Object->Methods == &Blob_Methods)
{
Test_Blob_Opacity((BLOB *)Object);
}
if (Object->Methods == &Mesh_Methods)
{
Test_Mesh_Opacity((MESH *)Object);
}
}
}
/*****************************************************************************
*
* FUNCTION
*
* Link_To_Frame
*
* INPUT
*
* Object - Pointer to object
*
* OUTPUT
*
* Object
*
* RETURNS
*
* AUTHOR
*
* POV-Ray Team
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* Sep 1994 : Added optional splitting of bounded unions if children are
* finite. Added removing of unnecessary bounding. [DB]
*
******************************************************************************/
static void Link_To_Frame(OBJECT *Object)
{
int finite;
DBL Volume;
OBJECT *This_Sib, *Next_Sib;
if (Object == NULL) /* patches a memory addressing error jdm mar/95 */
return;
/* Remove bounding object if object is cheap to intersect. [DB 8/94] */
if ((opts.Options & REMOVE_BOUNDS) && (Object->Bound != NULL))
{
if ((Object->Methods != &CSG_Union_Methods) &&
(Object->Methods != &CSG_Intersection_Methods) &&
(Object->Methods != &CSG_Merge_Methods) &&
(Object->Methods != &Poly_Methods) &&
(Object->Methods != &TTF_Methods))
{
/* Destroy only, if bounding object is not used as clipping object. */
if (Object->Bound != Object->Clip)
{
Destroy_Object(Object->Bound);
}
Object->Bound = NULL;
Warn(0, "Unnecessary bounding object removed.");
}
}
/*
* Link the object to the frame if it's not a CSG union object,
* if it's clipped or if bounding slabs aren't used.
*/
if ((Object->Methods != &CSG_Union_Methods) ||
(Object->Clip != NULL) ||
(!opts.Use_Slabs))
{
Link(Object, &(Object->Sibling), &(Frame.Objects));
return;
}
/*
* [DB 8/94]
*
* The object is a CSG union object. It will be split if all siblings are
* finite, i.e. the volume of the bounding box doesn't exceed a threshold.
*/
/* NK phmap - added code so union is not split up if it is
flagged for hi-density photon mapping...
maybe we SHOULD split it anyways... do speed tests later */
if(!((CSG *)Object)->do_split)
{
Link(Object, &(Object->Sibling), &(Frame.Objects));
return;
}
/* NK ---- */
if (Object->Bound != NULL)
{
/* Test if all siblings are finite. */
finite = TRUE;
for (This_Sib = ((CSG *)Object)->Children; This_Sib != NULL; This_Sib = This_Sib->Sibling)
{
BOUNDS_VOLUME(Volume, This_Sib->BBox);
if (Volume > BOUND_HUGE)
{
finite = FALSE;
break;
}
}
/*
* If the union has infinite children or splitting is not used link
* the union to the frame.
*/
if ((!finite) || !(opts.Options & SPLIT_UNION))
{
if (finite)
{
Warn(0, "CSG union unnecessarily bounded.");
}
Link(Object, &(Object->Sibling), &(Frame.Objects));
return;
}
Warn(0, "Bounded CSG union split.");
}
/* Link all siblings of a union to the frame. */
for (This_Sib = ((CSG *)Object)->Children; This_Sib != NULL; This_Sib = Next_Sib)
{
/* Link_To_Frame() changes Sibling so save it */
Next_Sib = This_Sib->Sibling;
/* Sibling is no longer inside a CSG object. */
This_Sib->Type &= ~IS_CHILD_OBJECT;
Link_To_Frame (This_Sib);
}
/*
Object->Texture = NULL;
*/
Object->Sibling = NULL;
((CSG *)Object)->Children = NULL;
Destroy_Object (Object);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Only_In(char *s1,char *s2)
{
Error("Keyword '%s' can only be used in a %s statement.",s1,s2);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
void Not_With(char *s1,char *s2)
{
Error("Keyword '%s' cannot be used with %s.",s1,s2);
}
void Warn_Compat(int f)
{
Warning(0,"Use of this syntax ");
if (f)
{
Warning(0,"is not");
}
else
{
Warning(0,"may not be");
}
Warning(0," backwards compatable with earlier versions\n%s",
"of POV-Ray. The #version directive or +MV switch will not help.\n\n");
}
#ifdef BsplinePatch
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static void Create_Spline_1D (SPLINE_STACK_1D *base,int nr,char *name,int type,DBL p1,DBL p2)
{
SPLINE *New,*help1;
KNOT *New_Knots;
COEFF_1D *New_Coeffs;
SPLINE_STACK_1D *help;
int i,t,j;
DBL *a,*b,*c,*rs,*l,*r,*y,*s_j,koeff2,koeff3;
New = (SPLINE *)POV_MALLOC(sizeof(SPLINE), NULL);
New->name = name;
New->type = type;
New->res = nr-1;
if (New->type==CLOSED_SPLINE) New->res++;
New->next=NULL;
New_Knots = (KNOT *)POV_MALLOC(sizeof(KNOT)*(New->res+1), NULL);
/* copy knots from list to array */
help=base;
New_Knots[0].t = help->t;
New_Knots[0].y = help->y;
i=1;
while (help->next !=NULL)
{
help=(SPLINE_STACK_1D*)help->next;
New_Knots[i].t=help->t;
New_Knots[i].y=help->y;
i++;
}
if (type==CLOSED_SPLINE) { New_Knots[i].t=p1; New_Knots[i].y=New_Knots[0].y; }
New->Knots = New_Knots;
/* the Coefficients ... */
New_Coeffs = (COEFF_1D *)POV_MALLOC(sizeof(COEFF_1D)*New->res, NULL);
s_j = (DBL *)POV_MALLOC (sizeof(DBL)*(New->res+1), "Spline Stuff (sj's)");
a = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (a)");
b = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (b)");
c = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (c)");
rs = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (rs)");
l = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (l)");
r = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (r)");
y = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (y)");
/* Compute Coeffs ... */
if (type==DIRECTION_SPLINE || type==NATURAL_SPLINE)
{
/* first and last row of the matrix */
if (type==NATURAL_SPLINE)
{
a[0] = -4/(New_Knots[1].t-New_Knots[0].t);
b[0] = -2/((New_Knots[1].t-New_Knots[0].t));
c[0] = 0;
rs[0] = -6*( (New_Knots[1].y-New_Knots[0].y)/
( (New_Knots[1].t-New_Knots[0].t)*(New_Knots[1].t-New_Knots[0].t) ) );
c[nr-1] = 2/(New_Knots[nr-1].t-New_Knots[nr-2].t);
a[nr-1] = 4/(New_Knots[nr-1].t-New_Knots[nr-2].t);
b[nr-1] = 0;
rs[nr-1] = 6*( (New_Knots[nr-1].y-New_Knots[nr-2].y)/
( (New_Knots[nr-1].t-New_Knots[nr-2].t)*(New_Knots[nr-1].t-New_Knots[nr-2].t) ) );
}
if (type==DIRECTION_SPLINE)
{
a[0] = 1;
b[0] = 0;
rs[0] = p1;
a[nr-1] = 1;
c[nr-1] = 0;
rs[nr-1] = p2;
}
/* the other rows */
for (t=1;t<nr-1;t++)
{
c[t] = New_Knots[t+1].t-New_Knots[t].t;
a[t] = 2*((New_Knots[t+1].t-New_Knots[t].t)+(New_Knots[t].t-New_Knots[t-1].t));
b[t] = New_Knots[t].t-New_Knots[t-1].t;
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) );
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) );
}
Jacobi(a,b,c,rs,s_j,nr);
/* Compute coefficients */
for(j=0;j<nr-1;j++)
{
/* der 3. und 4. Eintrag im Schema der dividierten Differenzen... */
koeff2 = ( ( (New_Knots[j+1].y-New_Knots[j].y)/
(New_Knots[j+1].t-New_Knots[j].t) ) - s_j[j] )/(New_Knots[j+1].t-New_Knots[j].t);
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) );
koeff3 = koeff3/( (New_Knots[j+1].t-New_Knots[j].t)*(New_Knots[j+1].t-New_Knots[j].t) );
/* die Koeffizienten der Rj von 1, x, x*x, x*x*x ... */
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);
New_Coeffs[j].c[0] = New_Coeffs[j].c[0] - (New_Knots[j].t*New_Knots[j].t*New_Knots[j+1].t*koeff3);
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 );
New_Coeffs[j].c[2] = koeff2 - (2*New_Knots[j].t + New_Knots[j+1].t)*koeff3;
New_Coeffs[j].c[3] = koeff3;
}
}
else
{
/* first and last row */
c[0] = New_Knots[1].t-New_Knots[0].t; /* Coeff of s(nr-1) ! */
a[0] = 2*(New_Knots[1].t-New_Knots[0].t+New_Knots[nr].t-New_Knots[nr-1].t);
b[0] = New_Knots[nr].t-New_Knots[nr-1].t;
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) );
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) );
/* smooth at t(nr-1) */
c[nr-1] = New_Knots[nr].t-New_Knots[nr-1].t;
a[nr-1] = 2*(New_Knots[nr].t-New_Knots[nr-2].t);
b[nr-1] = New_Knots[nr-1].t-New_Knots[nr-2].t; /* Coeff of s(0) */
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) );
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) );
/* the other rows */
for (t=1;t<nr-1;t++)
{
c[t] = New_Knots[t+1].t-New_Knots[t].t;
a[t] = 2*((New_Knots[t+1].t-New_Knots[t].t)+(New_Knots[t].t-New_Knots[t-1].t));
b[t] = New_Knots[t].t-New_Knots[t-1].t;
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) );
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) );
}
/* solve the equivalations with Jacobi process */
Jacobi(a,b,c,rs,s_j,nr);
s_j[nr] = s_j[0];
/* Compute coefficients */
for(j=0;j<nr;j++)
{
/* der 3. und 4. Eintrag im Schema der dividierten Differenzen... */
koeff2 = ( ( (New_Knots[j+1].y-New_Knots[j].y)/
(New_Knots[j+1].t-New_Knots[j].t) ) - s_j[j] )/(New_Knots[j+1].t-New_Knots[j].t);
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) );
koeff3 = koeff3/( (New_Knots[j+1].t-New_Knots[j].t)*(New_Knots[j+1].t-New_Knots[j].t) );
/* die Koeffizienten der Rj von 1, x, x*x, x*x*x ... */
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);
New_Coeffs[j].c[0] = New_Coeffs[j].c[0] - (New_Knots[j].t*New_Knots[j].t*New_Knots[j+1].t*koeff3);
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 );
New_Coeffs[j].c[2] = koeff2 - (2*New_Knots[j].t + New_Knots[j+1].t)*koeff3;
New_Coeffs[j].c[3] = koeff3;
}
}
New->Coeffs = New_Coeffs;
/* destroy the list */
while (base != NULL)
{
help=(SPLINE_STACK_1D*)base->next;
POV_FREE(base);
base=help;
}
/* put the new spline in the list */
if (The_Splines==NULL) The_Splines=New;
else
{
help1=The_Splines;
while(help1->next != NULL)
help1=(SPLINE*)help1->next;
help1->next=New;
}
/* ... und weg damit .... */
POV_FREE (s_j);
POV_FREE (a);
POV_FREE (b);
POV_FREE (c);
POV_FREE (rs);
POV_FREE (l);
POV_FREE (r);
POV_FREE (y);
}
#endif
/*****************************************************************************
*
* FUNCTION
*
* Set_CSG_Children_Hollow
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static void Set_CSG_Children_Flag(OBJECT *Object, unsigned long f, unsigned long flag, unsigned long set_flag)
{
OBJECT *Sib;
for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
{
if (!Test_Flag(Sib, set_flag))
{
if ((Sib->Methods == &CSG_Intersection_Methods) ||
(Sib->Methods == &CSG_Merge_Methods) ||
(Sib->Methods == &CSG_Union_Methods))
{
Set_CSG_Children_Flag(Sib, f, flag, set_flag);
}
else
{
Sib->Flags = (Sib->Flags & (~flag)) | f;
}
}
}
}
static void *Copy_Identifier (void *Data, int Type)
{
int i;
POV_ARRAY *a, *na;
VECTOR *vp;
DBL *dp;
UV_VECT *uvp;
VECTOR_4D *v4p;
void *New;
if (Data==NULL)
{
return(NULL);
}
switch (Type)
{
case COLOUR_ID_TOKEN:
New = (void *)Copy_Colour(*(COLOUR *)Data);
break;
case VECTOR_ID_TOKEN:
vp = Create_Vector();
Assign_Vector((*vp),(*((VECTOR *)Data)));
New=vp;
break;
case UV_ID_TOKEN:
uvp = Create_UV_Vect();
Assign_Vector((*uvp),(*((UV_VECT *)Data)));
New=uvp;
break;
case VECTOR_4D_ID_TOKEN:
v4p = Create_Vector_4D();
Assign_Vector_4D((*v4p),(*((VECTOR_4D *)Data)));
New=v4p;
break;
case FLOAT_ID_TOKEN:
dp = Create_Float();
*dp = *((DBL *)Data);
New = dp;
break;
case PIGMENT_ID_TOKEN:
case DENSITY_ID_TOKEN:
New = (void *)Copy_Pigment((PIGMENT *)Data);
break;
case TNORMAL_ID_TOKEN:
New = (void *)Copy_Tnormal((TNORMAL *)Data);
break;
case FINISH_ID_TOKEN:
New = (void *)Copy_Finish((FINISH *)Data);
break;
case MEDIA_ID_TOKEN:
New = (void *)Copy_Media((IMEDIA *)Data);
break;
case INTERIOR_ID_TOKEN:
New = (void *)Copy_Interior((INTERIOR *)Data);
break;
case MATERIAL_ID_TOKEN:
New = (void *)Copy_Material((MATERIAL *)Data);
break;
case TEXTURE_ID_TOKEN:
New = (void *)Copy_Textures((TEXTURE *)Data);
break;
case OBJECT_ID_TOKEN:
New = (void *)Copy_Object((OBJECT *)Data);
break;
case COLOUR_MAP_ID_TOKEN:
case PIGMENT_MAP_ID_TOKEN:
case SLOPE_MAP_ID_TOKEN:
case TEXTURE_MAP_ID_TOKEN:
case NORMAL_MAP_ID_TOKEN:
case DENSITY_MAP_ID_TOKEN:
New = (void *)Copy_Blend_Map((BLEND_MAP *)Data);
break;
case TRANSFORM_ID_TOKEN:
New = (void *)Copy_Transform((TRANSFORM *)Data);
break;
case CAMERA_ID_TOKEN:
New = (void *)Copy_Camera((CAMERA *)Data);
break;
case RAINBOW_ID_TOKEN:
New = (void *)Copy_Rainbow((RAINBOW *)Data);
break;
case FOG_ID_TOKEN:
New = (void *)Copy_Fog((FOG *)Data);
break;
case SKYSPHERE_ID_TOKEN:
New = (void *)Copy_Skysphere((SKYSPHERE *)Data);
break;
case STRING_ID_TOKEN:
New = (void *)POV_STRDUP((char *)Data);
break;
case ARRAY_ID_TOKEN:
a=(POV_ARRAY *)Data;
na=(POV_ARRAY *)POV_MALLOC(sizeof(POV_ARRAY),"array");
*na=*a;
na->DataPtrs = (void **)POV_MALLOC(sizeof(void *)*(a->Total),"array");
for (i=0; i<a->Total; i++)
{
na->DataPtrs[i] = (void *)Copy_Identifier (a->DataPtrs[i],a->Type);
}
New = (void *)na;
break;
default:
Error("Cannot copy identifier");
New = NULL; /* tw */
}
return(New);
}
#ifdef BsplinePatch
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static void Create_Spline_3D (SPLINE_STACK_3D *base,int nr,char *name,int type,VECTOR temp1,VECTOR temp2)
{
SPLINE_3D *New,*help1;
KNOT3D *New_Knots;
SPLINE_STACK_3D *help;
DBL sp_len=0,delta_len;
int i,s,t,j;
COEFF_3D *New_Coeffs;
DBL *a,*b,*c,*rs,*l,*r,*y,*s_j,koeff2,koeff3;
New = (SPLINE_3D *)POV_MALLOC(sizeof(SPLINE_3D), NULL);
New->name = name;
New->type = type;
New->res = nr-1;
if (New->type==CLOSED_SPLINE) New->res++;
New->next=NULL;
New_Knots = (KNOT3D *)POV_MALLOC(sizeof(KNOT3D)*(New->res+1), NULL);
/* copy knots from list to array */
help=base;
New_Knots[0].y[X] = help->Knot[X];
New_Knots[0].y[Y] = help->Knot[Y];
New_Knots[0].y[Z] = help->Knot[Z];
i=1;
while (help->next !=NULL)
{
help=(SPLINE_STACK_3D*)help->next;
New_Knots[i].y[X] = help->Knot[X];
New_Knots[i].y[Y] = help->Knot[Y];
New_Knots[i].y[Z] = help->Knot[Z];
i++;
}
if (type==CLOSED_SPLINE)
{
New_Knots[i].y[X]=New_Knots[0].y[X];
New_Knots[i].y[Y]=New_Knots[0].y[Y];
New_Knots[i].y[Z]=New_Knots[0].y[Z];
}
New->Knots = New_Knots;
/* get t's from distance of control points */
/* compute splines lenghth first */
for (i=0;i<New->res;i++)
{
VDist(delta_len,New_Knots[i+1].y,New_Knots[i].y);
sp_len = sp_len + delta_len;
}
/* knots from 0 to 1 ... */
New_Knots[0].t=0;
New_Knots[New->res].t=1;
for (i=1;i<New->res;i++)
{
VDist(delta_len,New_Knots[i].y,New_Knots[i-1].y);
New_Knots[i].t = New_Knots[i-1].t+delta_len/sp_len;
}
/* destroy the list */
while (base != NULL)
{
help=(SPLINE_STACK_3D*)base->next;
POV_FREE(base);
base=help;
}
/* the Coefficients ... */
New_Coeffs = (COEFF_3D *)POV_MALLOC(sizeof(COEFF_3D)*New->res, NULL);
s_j = (DBL *)POV_MALLOC (sizeof(DBL)*(New->res+1), "Spline Stuff (sj's)");
a = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (a)");
b = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (b)");
c = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (c)");
rs = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (rs)");
l = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (l)");
r = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (r)");
y = (DBL *)POV_MALLOC (sizeof(DBL)*(nr), "Spline Stuff (y)");
/* Compute Coeffs ... */
for (s=0;s<3;s++) /* for each coordinate */
{
if (type==DIRECTION_SPLINE || type==NATURAL_SPLINE)
{
/* first and last row of the matrix */
if (type==NATURAL_SPLINE)
{
a[0] = -4/(New_Knots[1].t-New_Knots[0].t);
b[0] = -2/((New_Knots[1].t-New_Knots[0].t));
c[0] = 0;
rs[0] = -6*( (New_Knots[1].y[s]-New_Knots[0].y[s])/
( (New_Knots[1].t-New_Knots[0].t)*(New_Knots[1].t-New_Knots[0].t) ) );
c[nr-1] = 2/(New_Knots[nr-1].t-New_Knots[nr-2].t);
a[nr-1] = 4/(New_Knots[nr-1].t-New_Knots[nr-2].t);
b[nr-1] = 0;
rs[nr-1] = 6*( (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-1].t-New_Knots[nr-2].t) ) );
}
if (type==DIRECTION_SPLINE)
{
a[0] = 1;
b[0] = 0;
rs[0] = temp1[s];
a[nr-1] = 1;
c[nr-1] = 0;
rs[nr-1] = temp2[s];
}
/* the other rows */
for (t=1;t<nr-1;t++)
{
c[t] = New_Knots[t+1].t-New_Knots[t].t;
a[t] = 2*((New_Knots[t+1].t-New_Knots[t].t)+(New_Knots[t].t-New_Knots[t-1].t));
b[t] = New_Knots[t].t-New_Knots[t-1].t;
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) );
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) );
}
Jacobi(a,b,c,rs,s_j,nr);
/* Compute coefficients */
for(j=0;j<nr-1;j++)
{
/* der 3. und 4. Eintrag im Schema der dividierten Differenzen... */
koeff2 = ( ( (New_Knots[j+1].y[s]-New_Knots[j].y[s])/
(New_Knots[j+1].t-New_Knots[j].t) ) - s_j[j] )/(New_Knots[j+1].t-New_Knots[j].t);
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) );
koeff3 = koeff3/( (New_Knots[j+1].t-New_Knots[j].t)*(New_Knots[j+1].t-New_Knots[j].t) );
/* die Koeffizienten der Rj von 1, x, x*x, x*x*x ... */
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);
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);
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 );
New_Coeffs[j].c[s][2] = koeff2 - (2*New_Knots[j].t + New_Knots[j+1].t)*koeff3;
New_Coeffs[j].c[s][3] = koeff3;
}
}
else
{
/* first and last row */
/* smooth at t(0) , t(nr) */
c[0] = New_Knots[1].t-New_Knots[0].t; /* Coeff of s(nr-1) ! */
a[0] = 2*(New_Knots[1].t-New_Knots[0].t+New_Knots[nr].t-New_Knots[nr-1].t);
b[0] = New_Knots[nr].t-New_Knots[nr-1].t;
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) );
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) );
/* smooth at t(nr-1) */
c[nr-1] = New_Knots[nr].t-New_Knots[nr-1].t;
a[nr-1] = 2*(New_Knots[nr].t-New_Knots[nr-2].t);
b[nr-1] = New_Knots[nr-1].t-New_Knots[nr-2].t; /* Coeff of s(0) */
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) );
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) );
/* the other rows */
for (t=1;t<nr-1;t++)
{
c[t] = New_Knots[t+1].t-New_Knots[t].t;
a[t] = 2*((New_Knots[t+1].t-New_Knots[t].t)+(New_Knots[t].t-New_Knots[t-1].t));
b[t] = New_Knots[t].t-New_Knots[t-1].t;
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) );
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) );
}
/* solve the equivalations with Jacobi process */
Jacobi(a,b,c,rs,s_j,nr);
s_j[nr] = s_j[0];
/* Compute coefficients */
for(j=0;j<nr;j++)
{
/* der 3. und 4. Eintrag im Schema der dividierten Differenzen... */
koeff2 = ( ( (New_Knots[j+1].y[s]-New_Knots[j].y[s])/
(New_Knots[j+1].t-New_Knots[j].t) ) - s_j[j] )/(New_Knots[j+1].t-New_Knots[j].t);
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) );
koeff3 = koeff3/( (New_Knots[j+1].t-New_Knots[j].t)*(New_Knots[j+1].t-New_Knots[j].t) );
/* die Koeffizienten der Rj von 1, x, x*x, x*x*x ... */
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);
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);
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 );
New_Coeffs[j].c[s][2] = koeff2 - (2*New_Knots[j].t + New_Knots[j+1].t)*koeff3;
New_Coeffs[j].c[s][3] = koeff3;
}
}
}
New->Coeffs = New_Coeffs;
/* put the new spline in the list */
if (The_3D_Splines==NULL) The_3D_Splines=New;
else
{
help1=The_3D_Splines;
while(help1->next != NULL)
help1=(SPLINE_3D*)help1->next;
help1->next=New;
}
/* ... und weg damit .... */
POV_FREE (s_j);
POV_FREE (a);
POV_FREE (b);
POV_FREE (c);
POV_FREE (rs);
POV_FREE (l);
POV_FREE (r);
POV_FREE (y);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static void Jacobi (DBL *a,DBL *b,DBL *c,DBL *rs,DBL *s,int n)
{
int i,is_first=TRUE;
DBL err=1,*next_s;
next_s = (DBL *)POV_MALLOC (sizeof(DBL)*(n), "Spline Stuff ");
/* modify right side and matrix and set startpoint to 0 */
for (i=0;i<n;i++)
{
rs[i] = rs[i]/a[i];
b[i] = -b[i]/a[i];
c[i] = -c[i]/a[i];
a[i] = 0;
s[i] = 0;
}
while (err>0.000000001)
{
/* first row */
next_s[0] = s[1]*b[0]+s[n-1]*c[0];
/* row 1 to n-2 */
for (i=1;i<n-1;i++) next_s[i] = c[i]*s[i-1]+b[i]*s[i+1];
/* last row */
next_s[n-1] = b[n-1]*s[0]+c[n-1]*s[n-2];
for(i=0;i<n;i++) next_s[i]=next_s[i]+rs[i];
if (is_first)
{
is_first=FALSE;
err=0;
for(i=0;i<n;i++) if (fabs(next_s[i]>err)) err=fabs(next_s[i]);
}
else
{
err *= 0.5;
}
for(i=0;i<n;i++) s[i]=next_s[i];
}
POV_FREE (next_s);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* DESCRIPTION
*
* CHANGES
*
******************************************************************************/
static void Destroy_Splines ()
{
SPLINE *help1;
SPLINE_3D *help2;
while (The_Splines != NULL)
{
help1=(SPLINE*)The_Splines->next;
POV_FREE(The_Splines->name);
POV_FREE(The_Splines->Coeffs);
POV_FREE(The_Splines->Knots);
POV_FREE(The_Splines);
The_Splines=help1;
}
while (The_3D_Splines != NULL)
{
help2=(SPLINE_3D*)The_3D_Splines->next;
POV_FREE(The_3D_Splines->name);
POV_FREE(The_3D_Splines->Coeffs);
POV_FREE(The_3D_Splines->Knots);
POV_FREE(The_3D_Splines);
The_3D_Splines=help2;
}
}
#endif
/* NK layers - 1999 June 10 - for backwards compatiblity with layered textures */
void Convert_Filter_To_Transmit(PIGMENT *Pigment)
{
int i;
BLEND_MAP *Map;
if (Pigment==NULL) return;
switch (Pigment->Type)
{
case PLAIN_PATTERN:
Pigment->Colour[TRANSM]+=Pigment->Colour[FILTER];
Pigment->Colour[FILTER]=0;
break;
default:
if (Pigment->Blend_Map != NULL)
{
Map = Pigment->Blend_Map;
/* go through blend map */
if ((Map->Type == PIGMENT_TYPE) || (Map->Type == DENSITY_TYPE))
{
for (i = 0; i < Map->Number_Of_Entries; i++)
{
Convert_Filter_To_Transmit(Map->Blend_Map_Entries[i].Vals.Pigment);
}
}
else
{
for (i = 0; i < Map->Number_Of_Entries; i++)
{
Map->Blend_Map_Entries[i].Vals.Colour[TRANSM]+=Map->Blend_Map_Entries[i].Vals.Colour[FILTER];
Map->Blend_Map_Entries[i].Vals.Colour[FILTER]=0;
}
}
}
break;
}
}
/* NK ---- */
#ifdef IsoBlobPatch
/* Isoblob parse routines -- Lummox JR, July 1999 */
/*****************************************************************************
*
* FUNCTION
*
* Parse_Blob_Element_Mods
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* Jul 1999 : Creation.
*
******************************************************************************/
static void Parse_Isoblob_Element_Mods(ISOBLOB_ELEMENT *Element)
{
VECTOR Local_Vector;
MATRIX Local_Matrix;
TRANSFORM Local_Trans;
TEXTURE *Local_Texture;
EXPECT
CASE (TRANSLATE_TOKEN)
Parse_Vector (Local_Vector);
Translate_Isoblob_Element (Element, Local_Vector);
END_CASE
CASE (ROTATE_TOKEN)
Parse_Vector (Local_Vector);
Rotate_Isoblob_Element (Element, Local_Vector);
END_CASE
CASE (SCALE_TOKEN)
Parse_Scale_Vector (Local_Vector);
Scale_Isoblob_Element (Element, Local_Vector);
END_CASE
CASE (TRANSFORM_TOKEN)
#ifndef TransformPatch /* Chris Huff april 2000 */
GET(TRANSFORM_ID_TOKEN)
Transform_Isoblob_Element (Element, (TRANSFORM *)Token.Data);
#else
{
TRANSFORM * Trans = Parse_Transform();
Transform_Isoblob_Element (Element, Trans);
/*YS sept 17 2000 Memory leak*/
POV_FREE(Trans);
}
#endif
END_CASE
CASE (MATRIX_TOKEN)
Parse_Matrix (Local_Matrix);
Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
Transform_Isoblob_Element (Element, &Local_Trans);
END_CASE
CASE (TEXTURE_TOKEN)
Parse_Begin ();
Local_Texture = Parse_Texture();
Parse_End ();
Link_Textures(&Element->Texture, Local_Texture);
END_CASE
CASE3 (PIGMENT_TOKEN, TNORMAL_TOKEN, FINISH_TOKEN)
if (Element->Texture == NULL)
{
Element->Texture = Copy_Textures(Default_Texture);
}
else
{
if (Element->Texture->Type != PLAIN_PATTERN)
{
Link_Textures(&Element->Texture, Copy_Textures(Default_Texture));
}
}
UNGET
EXPECT
CASE (PIGMENT_TOKEN)
Parse_Begin ();
Parse_Pigment(&Element->Texture->Pigment);
Parse_End ();
END_CASE
CASE (TNORMAL_TOKEN)
Parse_Begin ();
Parse_Tnormal(&Element->Texture->Tnormal);
Parse_End ();
END_CASE
CASE (FINISH_TOKEN)
Parse_Finish(&Element->Texture->Finish);
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End();
/* Postprocess to make sure that HAS_FILTER will be set correctly. */
Post_Textures(Element->Texture);
}
/*****************************************************************************
*
* FUNCTION
*
* Parse_Isoblob
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* Jul 1999 : Creation.
*
******************************************************************************/
static OBJECT *Parse_Isoblob()
{
int npoints,nfuncs,myfunc,i;
char normal_type=0;
DBL threshold,accuracy;
int max_trace;
VECTOR Axis, Base, Apex;
ISOBLOB *Object;
ISOBLOB_LIST *isoblob_components, *isoblob_component;
ISOBLOB_FUNC_LIST *isoblob_funcs, *isoblob_func, *thisfunc;
FUNCTION *func;
Parse_Begin();
if ((Object = (ISOBLOB *)Parse_Object_Id()) != NULL)
{
return ((OBJECT *) Object);
}
Object = Create_Isoblob();
isoblob_components = NULL;
isoblob_funcs = NULL;
npoints = 0;
nfuncs = 0;
threshold = 1.0;
accuracy = 1.0e-6;
max_trace = 10;
EXPECT
CASE (THRESHOLD_TOKEN)
threshold = Parse_Float();
END_CASE
CASE (ACCURACY_TOKEN)
accuracy = Parse_Float();
END_CASE
CASE (MAX_TRACE_TOKEN)
max_trace = Parse_Float();
END_CASE
CASE (TNORMAL_TOKEN)
normal_type = (char)(int)Allow_Float(1.0);
END_CASE
CASE (FUNCTION_TOKEN)
if(npoints>0) Error("Isoblob density functions must be specified before components");
else
{
func=Parse_Function();
func->sign=-1; /* To insure proper operation */
isoblob_func=(ISOBLOB_FUNC_LIST*)Create_Isoblob_List_Element();
isoblob_func->func=func;
if(isoblob_funcs==NULL) isoblob_funcs=isoblob_func;
else
{
for(thisfunc=isoblob_funcs;thisfunc->next!=NULL;thisfunc=thisfunc->next);
thisfunc->next=isoblob_func;
}
++nfuncs;
}
END_CASE
/*************************************************************************
* Read sperical component.
*************************************************************************/
CASE (SPHERE_TOKEN)
isoblob_component = Create_Isoblob_List_Element();
isoblob_component->elem.Type = ISOBLOB_SPHERE;
isoblob_component->elem.Trans = Create_Transform();
Parse_Begin();
Parse_Vector(Base);
Compute_Translation_Transform(isoblob_component->elem.Trans,Base);
Parse_Comma();
isoblob_component->elem.rad2 = Parse_Float();
isoblob_component->elem.rad2 = Sqr(isoblob_component->elem.rad2);
Parse_Comma();
ALLOW(STRENGTH_TOKEN)
isoblob_component->elem.str = Parse_Float();
ALLOW(FUNCTION_TOKEN)
myfunc=(int)Parse_Float();
if(myfunc<1 || myfunc>nfuncs) {Error("Function #%d is not defined for this isoblob.",nfuncs);}
for(i=1,thisfunc=isoblob_funcs;(thisfunc!=NULL && i<myfunc);thisfunc=thisfunc->next,++i);
isoblob_component->elem.Func=thisfunc->func;
Parse_Isoblob_Element_Mods(&isoblob_component->elem);
/* Next component. */
isoblob_component->next = isoblob_components;
isoblob_components = isoblob_component;
npoints++;
END_CASE
/*************************************************************************
* Read cylindrical component.
*************************************************************************/
CASE (CYLINDER_TOKEN)
isoblob_component = Create_Isoblob_List_Element();
isoblob_component->elem.Type = ISOBLOB_CYLINDER;
isoblob_component->elem.Trans = Create_Transform();
Parse_Begin();
Parse_Vector(Base);
Parse_Comma();
Parse_Vector(Apex);
Parse_Comma();
isoblob_component->elem.rad2 = Parse_Float();
isoblob_component->elem.rad2 = Sqr(isoblob_component->elem.rad2);
Parse_Comma();
ALLOW(STRENGTH_TOKEN)
isoblob_component->elem.str = Parse_Float();
/* Calculate cylinder's coordinate system. */
VSub(Axis, Apex, Base);
VLength(isoblob_component->elem.len, Axis);
if (isoblob_component->elem.len < EPSILON)
{
Error("Degenerate cylindrical component in isoblob.\n");
}
VInverseScaleEq(Axis, isoblob_component->elem.len);
Compute_Coordinate_Transform(isoblob_component->elem.Trans, Base, Axis, 1.0, 1.0);
ALLOW(FUNCTION_TOKEN)
myfunc=(int)Parse_Float();
if(myfunc<1 || myfunc>nfuncs) {Error("Function #%d is not defined for this isoblob.",nfuncs);}
for(i=1,thisfunc=isoblob_funcs;(thisfunc!=NULL && i<myfunc);thisfunc=thisfunc->next,++i);
isoblob_component->elem.Func=thisfunc->func;
Parse_Isoblob_Element_Mods(&isoblob_component->elem);
/* Next component. */
isoblob_component->next = isoblob_components;
isoblob_components = isoblob_component;
npoints++;
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Create_Isoblob_Element_Texture_List(Object, isoblob_components, npoints);
Parse_Object_Mods((OBJECT *)Object);
/* The blob's texture has to be processed before Make_Isoblob() is called. */
Post_Textures(Object->Texture);
/* Finally, process the information */
Make_Isoblob(Object, threshold, accuracy, max_trace, normal_type, isoblob_funcs, isoblob_components, npoints);
return((OBJECT *)Object);
}
/* End Lummox JR's isoblob additions */
#endif
#ifdef MotionBlurPatch
static OBJECT *Parse_Motion_Blur ()
{
MOTION_BLUR *Object;
OBJECT *Local;
DBL saveClock,clockDelta;
int i;
saveFilePos();
Object = Create_Motion_Blur ();
Object->Children = NULL;
saveClock = opts.FrameSeq.Clock_Value;
if (opts.motionBlurCount>1)
{
opts.FrameSeq.Clock_Value -= opts.blurClockDelta/2.0;
clockDelta = (opts.blurClockDelta)/(opts.motionBlurCount-1);
}
else
clockDelta = 0;
beginCS_Index = CS_Index;
for(i=1; i<=opts.motionBlurCount; i++)
{
restoreFilePos();
Parse_Begin ();
Local = Parse_Object ();
if(Local)
{
Object->Type |= (Local->Type & CHILDREN_FLAGS);
/* NK Apr 2000 - allow light sources inside motion blur
if ((Local->Type & LIGHT_SOURCE_OBJECT))
{
Error("Light source not allowed in motion_blur\n");
}
*/
if ((Local->Type & MOTION_BLUR_OBJECT))
{
Error("motion_blur objects cannot be nested\n");
}
Local->Type |= IS_CHILD_OBJECT;
Local->TimeStamp = i;
Link(Local, &Local->Sibling, &Object->Children);
/* now parse the mods for motion_blur */
Parse_Object_Mods(Local);
}
opts.FrameSeq.Clock_Value += clockDelta;
if (CS_Index != beginCS_Index)
{
Error("close brace for motion_blur cannot be enclosed in an #if, #case, or #while block.\n");
}
}
if (!Object->Children)
Error("No object inside motion_blur.");
Object->Type |= MOTION_BLUR_OBJECT;
opts.FrameSeq.Clock_Value = saveClock;
Compute_Motion_Blur_BBox((OBJECT *)Object);
return ((OBJECT *) Object);
}
static void Parse_MBlur_Transform (TRANSFORM *New)
{
MATRIX Local_Matrix;
TRANSFORM Local_Trans;
VECTOR Local_Vector;
MIdentity(New->inverse);
MIdentity(New->matrix);
EXPECT
CASE(TRANSFORM_ID_TOKEN)
Compose_Transforms (New, (TRANSFORM *)Token.Data);
END_CASE
CASE (TRANSFORM_TOKEN)
#ifndef TransformPatch /* Chris Huff april 2000 */
GET(TRANSFORM_ID_TOKEN)
Compose_Transforms(New, (TRANSFORM *)Token.Data);
#else
{
TRANSFORM * Trans = Parse_Transform();
Compose_Transforms(New, Trans);
/*YS sept 17 2000 Memory leak*/
POV_FREE(Trans);
}
#endif
END_CASE
CASE (TRANSLATE_TOKEN)
Parse_Vector (Local_Vector);
Compute_Translation_Transform(&Local_Trans, Local_Vector);
Compose_Transforms (New, &Local_Trans);
END_CASE
CASE (ROTATE_TOKEN)
Parse_Vector (Local_Vector);
Compute_Rotation_Transform(&Local_Trans, Local_Vector);
Compose_Transforms (New, &Local_Trans);
END_CASE
CASE (SCALE_TOKEN)
Parse_Scale_Vector (Local_Vector);
Compute_Scaling_Transform(&Local_Trans, Local_Vector);
Compose_Transforms (New, &Local_Trans);
END_CASE
CASE (MATRIX_TOKEN)
Parse_Matrix(Local_Matrix);
Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
Compose_Transforms (New, &Local_Trans);
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
}
#if(0)
static OBJECT *Parse_Motion_Blur2 ()
{
MOTION_BLUR2 *Object;
OBJECT *Local;
DBL saveClock;
Object = Create_Motion_Blur2 ();
Object->Children = NULL;
Parse_Begin ();
Local = Parse_Object ();
if(!Local)
Error("Missing object within motion_blur\n");
Object->Type |= (Local->Type & CHILDREN_FLAGS);
if ((Local->Type & LIGHT_SOURCE_OBJECT))
{
Error("Light source not allowed in motion_blur2\n");
}
if ((Local->Type & MOTION_BLUR_OBJECT))
{
Error("motion_blur objects cannot be nested\n");
}
Local->Type |= IS_CHILD_OBJECT;
Link(Local, &Local->Sibling, &Object->Children);
/* now parse the mods for motion_blur2 */
/* only allow transformations */
saveClock = opts.FrameSeq.Clock_Value;
saveFilePos();
beginCS_Index = CS_Index;
opts.FrameSeq.Clock_Value = saveClock - opts.blurClockDelta/2.0;
Parse_MBlur_Transform (&Object->Trans1);
Parse_End();
if (CS_Index != beginCS_Index)
{
Error("close brace for motion_blur2 cannot be enclosed in an #if, #case, or #while block.\n");
}
restoreFilePos();
opts.FrameSeq.Clock_Value = saveClock + opts.blurClockDelta/2.0;
Parse_MBlur_Transform (&Object->Trans2);
Parse_End();
Object->Type |= MOTION_BLUR_OBJECT;
opts.FrameSeq.Clock_Value = saveClock;
Compute_Motion_Blur2_BBox((OBJECT *)Object);
return ((OBJECT *) Object);
}
#endif
#endif