home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Encyclopedia of Graphics File Formats Companion
/
GFF_CD.ISO
/
formats
/
ttddd
/
spec
/
t3d_doc
/
igensurf.zoo
/
src
/
igensurf.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-15
|
30KB
|
1,061 lines
/* :ts=8 */ /* Yes some of us still use vi ! */
/************************************************************************/
/* */
/* Program to generate a TTDDD description of a functional surface. */
/* */
/* Usage: */
/* */
/* igensurf [-n name] [-s step_s] [-t step_t] */
/* [-C] [-R] [-T] [-S scale_factor] [-p] [-v] */
/* [-e expression] [-o output_file] input_file ... */
/* */
/************************************************************************/
/* */
/* This program is based on the 'gensurf' program found in the Radiance */
/* Synthetic Imaging System. Radiance (and gensurf) is written by */
/* Greg Ward. */
/* */
/* Igensurf produces a TTDDD object description of a functional surface */
/* defined by the parametric equations x(s,t), y(s,t) and z(s,t). */
/* The object is scaled by the factor given with the -S option. */
/* */
/* The surface normal is defined ny the right and rule as applied to */
/* (s,t). S will vary from 0 to 1 in steps of 1/step_s, and t will vary */
/* from 0 to 1 in steps of 1/step_t. The surface will be composed of */
/* 2 * step_s * step_t or fewer triangles. */
/* */
/* -n defines name of the generated object. */
/* -C enables generation of face color info. */
/* -R enables generation of face reflectance info. */
/* -T enables generation of face transmittance info. */
/* -S defines a scale factor. */
/* -p enables phong smothing of the surface. */
/* -v enables writing of some messages to stderr. */
/* -e defines extra expressions (can be repeated). */
/* -o defines name of the TTDDD output file (default is stdout). */
/* */
/* See the 'igensurf.doc' file for further information. */
/* */
/************************************************************************/
/* */
/* EXAMPLE: */
/* */
/* To generate a sphere: */
/* */
/* igensurf -n ball -e "x(s,t)=sin(PI*s)*cos(2*PI*t)" */
/* -e "y(x,t)=cos(PI*s)" -e "z(x,t)=sin(PI*s)*sin(2*PI*t)" */
/* -s 7 -t 10 -S 100 -o ball.ttddd */
/* */
/* writetddd ball.ttddd ball.obj */
/* */
/* You can of course use a pipe instead of using a temporary file. */
/* */
/************************************************************************/
/* */
/* BUGS: */
/* */
/* Has limits on object sizes. These may be changed by recompiling after*/
/* changing some defines below. */
/* It might also be necessary to change the sizes if you are using a */
/* 512 K machine. */
/* */
/* All points, edges and faces are saved in arrays. The program does a */
/* linear search for points before adding new points. This method can */
/* be very time consuming for big objects. */
/* */
/* igensurf doesn't free allocated space itself. Hopefully the OS, or */
/* the compiler will do it. It only uses standard malloc calls. */
/* */
/************************************************************************/
/* */
/* Author: Helge E. Rasmussen (her@compel.dk) */
/* */
/* Original Radiance code by Greg Ward. */
/* */
/* You may use the program and the source code in any way you want as */
/* long as you do not resell the software as your own, or use it in a */
/* commercial product. */
/* */
/* Please let me know if you find any bugs, or have ideas for enhance- */
/* ments. */
/* */
/************************************************************************/
#define Version "v. 1.0" /* Current version of program. */
/* Increase these for very big objects */
/* Decrease them if you are using a 512 K machine */
/* Maximum limits removed by Glenn M. Lewis - 10/15/91 */
int Max_Nbr_Points = 10000;
int Max_Nbr_Edges = 10000;
int Max_Nbr_Faces = 10000;
extern char *malloc(), *realloc();
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#ifdef AMIGA
#include <stdlib.h>
#else
#include <unistd.h>
#endif
#include "calc.h"
#ifndef PI
#define PI M_PI
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#define FTINY (double) 1e-6
#define Buffer_Length 256
#define ABS(x) ((x)>=0 ? (x) : -(x))
typedef int Boolean_T;
typedef struct {
unsigned char R;
unsigned char G;
unsigned char B;
} Color_T;
typedef struct {
double X;
double Y;
double Z;
} Vector_T;
typedef struct {
int P1;
int P2;
} Edge_T;
typedef struct {
int E1;
int E2;
int E3;
Color_T Color;
Color_T Refl;
Color_T Trans;
} Face_T;
#define X_FUNC "x" /* x function name */
#define Y_FUNC "y" /* y function name */
#define Z_FUNC "z" /* z function name */
#define CR_FUNC "cr" /* color R function name */
#define CG_FUNC "cg" /* color G function name */
#define CB_FUNC "cb" /* color B function name */
#define RR_FUNC "rr" /* refl. R function name */
#define RG_FUNC "rg" /* refl. G function name */
#define RB_FUNC "rb" /* refl. B function name */
#define TR_FUNC "tr" /* trans R function name */
#define TG_FUNC "rg" /* trans G function name */
#define TB_FUNC "tb" /* trans B function name */
char Object_Name[Buffer_Length+1];/* Name of object. */
Boolean_T Verbose = FALSE; /* Be verbose */
Boolean_T Phong = FALSE; /* Phong smoothing? */
Boolean_T Compute_Color = FALSE; /* Compute color */
Boolean_T Compute_Refl = FALSE; /* Compute reflectance */
Boolean_T Compute_Trans = FALSE; /* Compute transmittance */
int Step_S = 10; /* Number of steps (s). */
int Step_T = 10; /* Number of steps (t). */
double Scale_Factor = 1.0; /* Scale factor */
double Precision = 1e-7; /* Precision in coordinates */
Vector_T *Row0 = NULL;
Vector_T *Row1 = NULL;
Vector_T *Row2 = NULL;
FILE *O_Stream = NULL;
Boolean_T Generate_Done = FALSE;
Vector_T *Points; /* Table of points */
int Nbr_Points = 0;
Edge_T *Edges; /* Table of edges */
int Nbr_Edges = 0;
Face_T *Faces; /* Table of faces */
int Nbr_Faces = 0;
void Error(Txt)
char *Txt;
/************************************************************************/
/* */
/* Write error messages and stop the program. */
/* */
/************************************************************************/
{
fprintf(stderr, "Error: %s\n", Txt);
exit(9);
} /* Error */
void Usage()
/************************************************************************/
/* */
/* Write a usage message to stderr, and stop the program. */
/* */
/************************************************************************/
{
fprintf(stderr, "Usage: igensurf [-n name] [-s step_s] [-t step_t]\n");
fprintf(stderr, " [-C] [-R] [-T] [-S scale_factor] [-p] [-v]\n");
fprintf(stderr, " [-e expression] [-o output_file] input_file ...\n");
exit(1);
} /* Usage */
/* The following routine was optimized for speed by Glenn M. Lewis - 10/15/91 */
int Get_Point(Point)
register Vector_T *Point;
/************************************************************************/
/* */
/* Get id for the point 'Point'. */
/* If no such point exist, then create it and return the newly created */
/* id. */
/* */
/************************************************************************/
{
register int i;
register Vector_T *p = &Points[Nbr_Points-1];
for (i = Nbr_Points; i--; ) {
if (ABS(Point->X - p->X) < Precision &&
ABS(Point->Y - p->Y) < Precision &&
ABS(Point->Z - p->Z) < Precision) return(i);
p--;
} /* for */
if (Nbr_Points >= Max_Nbr_Points) { /* MAX Limits removed by GML */
Max_Nbr_Points *= 2;
if (!(Points = (Vector_T*)
realloc(Points, Max_Nbr_Points*sizeof(Vector_T))))
Error("Couldn't allocate more Points");
}
(p = &Points[Nbr_Points])->X = Point->X;
p->Y = Point->Y;
p->Z = Point->Z;
return(Nbr_Points++);
} /* Get_Point */
/* The following routine was optimized for speed by Glenn M. Lewis - 10/15/91 */
int Get_Edge(P1, P2)
register int P1;
register int P2;
/************************************************************************/
/* */
/* Get id for the edge that connects the points P1 and P2. */
/* If no such edge exists, then create it and return the newly created */
/* id. */
/* */
/************************************************************************/
{
register int i;
register Edge_T *e = &Edges[Nbr_Edges-1];
for (i = Nbr_Edges; i--; ) {
if ( (e->P1 == P1 && e->P2 == P2) ||
(e->P1 == P2 && e->P2 == P1) ) return(i);
e--;
} /* for */
if (Nbr_Edges >= Max_Nbr_Edges) { /* MAX Limits removed by GML */
Max_Nbr_Edges *= 2;
if (!(Edges = (Edge_T*)
realloc(Edges, Max_Nbr_Edges*sizeof(Edge_T))))
Error("Couldn't allocate more Edges");
}
(e = &Edges[Nbr_Edges])->P1 = P1;
e->P2 = P2;
return(Nbr_Edges++);
} /* Get_Edge */
/* The following routine was optimized for speed by Glenn M. Lewis - 10/15/91 */
void Add_Face(P1, P2, P3, Color, Refl, Trans)
int P1;
int P2;
int P3;
Color_T *Color;
Color_T *Refl;
Color_T *Trans;
/************************************************************************/
/* */
/* Add a new face connecting P1, P2 and P3 to the face table. */
/* The corresponding edges will be created if they don't exist. */
/* */
/************************************************************************/
{
register int i;
register int E1, E2, E3;
register Face_T *f = &Faces[Nbr_Edges-1];
E1 = Get_Edge(P1, P2);
E2 = Get_Edge(P2, P3);
E3 = Get_Edge(P3, P1);
for (i = Nbr_Faces; i--; ) {
if (f->E1 == E1 && f->E2 == E2 && f->E3 == E3) return;
} /* for */
if (Nbr_Faces >= Max_Nbr_Faces) { /* MAX Limits removed by GML */
Max_Nbr_Faces *= 2;
if (!(Faces = (Face_T*)
realloc(Faces, Max_Nbr_Faces*sizeof(Face_T))))
Error("Couldn't allocate more Faces");
}
(f= &Faces[Nbr_Faces])->E1 = Get_Edge(P1, P2);
f->E2 = Get_Edge(P2, P3);
f->E3 = Get_Edge(P3, P1);
f->Color.R = Color->R;
f->Color.G = Color->G;
f->Color.B = Color->B;
f->Refl.R = Refl->R;
f->Refl.G = Refl->G;
f->Refl.B = Refl->B;
f->Trans.R = Trans->R;
f->Trans.G = Trans->G;
f->Trans.B = Trans->B;
Nbr_Faces++;
} /* Add_Face */
void Write_TTDDD_Object()
/************************************************************************/
/* */
/* Write the object saved in the global variables to O_Stream in TTDDD */
/* format. */
/* Set the name of the object to 'Object_Name'. */
/* If 'Phong' is TRUE, the object should be phong smoothed. */
/* */
/************************************************************************/
{
int i;
if (Nbr_Points == 0) return;
if (Verbose)
fprintf(stderr,
"Generating TTDDD description for %s...\n", Object_Name);
fprintf(O_Stream, "OBJ Begin %% Begin Object chunk\n");
fprintf(O_Stream, "\n");
fprintf(O_Stream, "DESC Begin %% Begin DESC sub-chunk\n");
fprintf(O_Stream, "\n");
fprintf(O_Stream, "\tNAME \"%s\"\n", Object_Name);
fprintf(O_Stream, "\n");
fprintf(O_Stream, "\tSHAP Shape 2 %% Axis object\n");
fprintf(O_Stream, "\tSHAP Lamp 0 %% Not a lamp\n");
fprintf(O_Stream, "\n");
fprintf(O_Stream, "\tPOSI X=0.0 Y=0.0 Z=0.0 %% Position.\n");
fprintf(O_Stream, "\n");
fprintf(O_Stream, "\tAXIS XAxis X=1 %% Defaults to 1 0 0\n");
fprintf(O_Stream, "\tAXIS YAxis Y=1 %% Defaults to 0 1 0\n");
fprintf(O_Stream, "\tAXIS ZAxis Z=1 %% Defaults to 0 0 1\n");
fprintf(O_Stream, "\n");
fprintf(O_Stream, "\tSIZE X=32 Y=32 Z=32 %% Defaults to 32.0\n");
fprintf(O_Stream, "\n");
/* POINTS */
if (Verbose) fprintf(stderr, "Points (%d)...\n", Nbr_Points);
fprintf(O_Stream, "\tPNTS PCount %d %% Number of points\n", Nbr_Points);
fprintf(O_Stream, "\n");
for (i = 0; i < Nbr_Points; i++) {
fprintf(O_Stream, "\tPNTS Point[%d] %lf %lf %lf\n",
i,
Scale_Factor * Points[i].X,
Scale_Factor * Points[i].Y,
Scale_Factor * Points[i].Z);
} /* for */
fprintf(O_Stream, "\n");
/* EDGES */
if (Verbose) fprintf(stderr, "Edges (%d)...\n", Nbr_Edges);
fprintf(O_Stream, "\tEDGE ECount %d %% Number of edges\n", Nbr_Edges);
fprintf(O_Stream, "\n");
for (i = 0; i < Nbr_Edges; i++) {
fprintf(O_Stream, "\tEDGE Edge[%d] %d %d\n",
i, Edges[i].P1, Edges[i].P2);
} /* for */
fprintf(O_Stream, "\n");
/* FACES */
if (Verbose) fprintf(stderr, "Faces (%d)...\n", Nbr_Faces);
fprintf(O_Stream, "\tFACE TCount %d %% Number of faces\n", Nbr_Faces);
fprintf(O_Stream, "\n");
for (i = 0; i < Nbr_Faces; i++) {
fprintf(O_Stream, "\tFACE Connect[%d] %d %d %d\n",
i, Faces[i].E1, Faces[i].E2, Faces[i].E3);
} /* for */
fprintf(O_Stream, "\n");
if (Compute_Color) {
/* COLORS */
if (Verbose) fprintf(stderr, "Colors (%d)...\n", Nbr_Faces);
fprintf(O_Stream, "\tCLST Count %d %% Number of colors\n",Nbr_Faces);
fprintf(O_Stream, "\n");
for (i = 0; i < Nbr_Faces; i++) {
fprintf(O_Stream, "\tCLST Color[%d] %d %d %d\n", i,
Faces[i].Color.R,
Faces[i].Color.G,
Faces[i].Color.B);
} /* for */
fprintf(O_Stream, "\n");
} /* if */
if (Compute_Refl) {
/* COLORS */
if (Verbose) fprintf(stderr, "Reflectance (%d)...\n", Nbr_Faces);
fprintf(O_Stream, "\tRLST Count %d %% Number of colors\n",Nbr_Faces);
fprintf(O_Stream, "\n");
for (i = 0; i < Nbr_Faces; i++) {
fprintf(O_Stream, "\tRLST Color[%d] %d %d %d\n", i,
Faces[i].Refl.R,
Faces[i].Refl.G,
Faces[i].Refl.B);
} /* for */
fprintf(O_Stream, "\n");
} /* if */
if (Compute_Trans) {
/* COLORS */
if (Verbose) fprintf(stderr, "Transmittance (%d)...\n", Nbr_Faces);
fprintf(O_Stream, "\tTLST Count %d %% Number of colors\n",Nbr_Faces);
fprintf(O_Stream, "\n");
for (i = 0; i < Nbr_Faces; i++) {
fprintf(O_Stream, "\tTLST Color[%d] %d %d %d\n", i,
Faces[i].Trans.R,
Faces[i].Trans.G,
Faces[i].Trans.B);
} /* for */
fprintf(O_Stream, "\n");
} /* if */
fprintf(O_Stream, "\tMTTR Type 4 %%\n");
fprintf(O_Stream, "\tMTTR Index 1.0 %%\n");
fprintf(O_Stream, "\n");
fprintf(O_Stream, "\tSPEC Specularity 0\n");
fprintf(O_Stream, "\tSPEC Hardness 0\n");
fprintf(O_Stream, "\n");
fprintf(O_Stream, "\tPRP0[0] 0 %% Blending (dither) factor.\n");
fprintf(O_Stream, "\tPRP0[1] 0 %% Roughness factor.\n");
fprintf(O_Stream, "\tPRP0[2] 0 %% Shading on/off.\n");
fprintf(O_Stream, "\tPRP0[3] %d %% Phong shading flag.\n", !Phong);
fprintf(O_Stream, "\tPRP0[4] 0 %% Glossy flag. \n");
fprintf(O_Stream, "\tPRP0[5] 0 %% Quickdraw flag.\n");
fprintf(O_Stream, "\n");
fprintf(O_Stream, "End DESC %% End of DESC sub-chunk\n");
fprintf(O_Stream, "\n");
fprintf(O_Stream, "TOBJ %% End of object hierachy.\n");
fprintf(O_Stream, "\n");
fprintf(O_Stream, "End OBJ %% End of object chunk\n");
fprintf(O_Stream, "\n");
Nbr_Points = 0;
Nbr_Edges = 0;
Nbr_Faces = 0;
} /* Write_TTDDD_Object */
Boolean_T Face_Is_Ok(Point0, Point1, Point2)
Vector_T *Point0;
Vector_T *Point1;
Vector_T *Point2;
/************************************************************************/
/* */
/* Check if the three points defines a triangle. */
/* Return TRUE if they do. */
/* */
/************************************************************************/
{
Vector_T V1;
Vector_T V2;
double Vx, Vy, Vz;
V1.X = Point1->X - Point0->X;
V1.Y = Point1->Y - Point0->Y;
V1.Z = Point1->Z - Point0->Z;
V2.X = Point2->X - Point0->X;
V2.Y = Point2->Y - Point0->Y;
V2.Z = Point2->Z - Point0->Z;
/* Cross product: */
Vx = V1.Y * V2.Z - V1.Z * V2.Y;
Vy = V1.Z * V2.X - V1.X * V2.Z;
Vz = V1.X * V2.Y - V1.Y * V2.X;
if (ABS(Vx) < FTINY &&
ABS(Vy) < FTINY &&
ABS(Vz) < FTINY) return(FALSE);
return(TRUE);
} /* Face_Is_Ok */
void Compute_Face_Info(s, t, Point0, Point1, Point2, Color, Refl, Trans)
double s, t;
Vector_T *Point0, *Point1, *Point2;
Color_T *Color;
Color_T *Refl;
Color_T *Trans;
/************************************************************************/
/* */
/* Compute Color, Reflectance and Transmittance for the face defined by */
/* Point0, Point1 and Point2 (plus s and t). */
/* */
/************************************************************************/
{
double Arguments[5];
if (!Compute_Color && !Compute_Refl && !Compute_Trans) return;
Arguments[0] = s;
Arguments[1] = t;
Arguments[2] = (Point0->X + Point1->X + Point2->X) / 3.0;
Arguments[3] = (Point0->Y + Point1->Y + Point2->Y) / 3.0;
Arguments[4] = (Point0->Z + Point1->Z + Point2->Z) / 3.0;
if (Compute_Color) {
Color->R = 255.0 * Func_Value(CR_FUNC, 5, Arguments);
Color->G = 255.0 * Func_Value(CG_FUNC, 5, Arguments);
Color->B = 255.0 * Func_Value(CB_FUNC, 5, Arguments);
}
if (Compute_Refl) {
Refl->R = 255.0 * Func_Value(RR_FUNC, 5, Arguments);
Refl->G = 255.0 * Func_Value(RG_FUNC, 5, Arguments);
Refl->B = 255.0 * Func_Value(RB_FUNC, 5, Arguments);
}
if (Compute_Trans) {
Trans->R = 255.0 * Func_Value(TR_FUNC, 5, Arguments);
Trans->G = 255.0 * Func_Value(TG_FUNC, 5, Arguments);
Trans->B = 255.0 * Func_Value(TB_FUNC, 5, Arguments);
}
} /* Compute_Face_Info */
void Generate_Face(s, t, Point0, Point1, Point2, Point3)
double s, t;
Vector_T *Point0, *Point1, *Point2, *Point3;
/************************************************************************/
/* */
/* Add the square given by the four points to the face/edge/point lists.*/
/* */
/************************************************************************/
{
int Face1_Ok, Face2_Ok;
int Point0_Id, Point1_Id, Point2_Id, Point3_Id;
Color_T Color, Refl, Trans;
Face1_Ok = Face_Is_Ok(Point0, Point1, Point2);
Face2_Ok = Face_Is_Ok(Point1, Point2, Point3);
if (Face1_Ok || Face2_Ok) {
if (Face1_Ok) Point0_Id = Get_Point(Point0);
Point1_Id = Get_Point(Point1);
Point2_Id = Get_Point(Point2);
if (Face2_Ok) Point3_Id = Get_Point(Point3);
if (Face1_Ok) {
Compute_Face_Info(s, t, Point0, Point1, Point2,
&Color, &Refl, &Trans);
Add_Face(Point0_Id, Point1_Id, Point2_Id,
&Color, &Refl, &Trans);
}
if (Face2_Ok) {
Compute_Face_Info(s, t, Point2, Point1, Point3,
&Color, &Refl, &Trans);
Add_Face(Point2_Id, Point1_Id, Point3_Id,
&Color, &Refl, &Trans);
}
} /* if */
} /* Generate_Face */
Compute_Row(s, Row, Step_Size)
double s;
register Vector_T *Row;
int Step_Size;
/************************************************************************/
/* */
/* Compute row of values for a given 's'. */
/* */
/************************************************************************/
{
double Arguments[2];
int end;
register int i;
if (s < -FTINY || s > 1.0+FTINY) return;
i = 0;
end = Step_Size;
Arguments[0] = s;
while (i <= end) {
Arguments[1] = (double) i / Step_Size;
Row[i].X = Func_Value(X_FUNC, 2, Arguments);
Row[i].Y = Func_Value(Y_FUNC, 2, Arguments);
Row[i].Z = Func_Value(Z_FUNC, 2, Arguments);
i++;
} /* while */
} /* Compute_Row */
int Generate_Object()
/************************************************************************/
/* */
/* Generate the points, edges and faces of the current object. */
/* */
/************************************************************************/
{
int i, j;
int New_Step_S;
int New_Step_T;
Vector_T *Tmp_Row;
/* Get Step_S and Step_T from user variables. */
New_Step_S = Var_Value("step_s");
New_Step_T = Var_Value("step_t");
if (New_Step_S <= 0 || New_Step_T <= 0 ||
New_Step_S > 999 || New_Step_T > 999) {
fprintf(stderr, "Illegal values for step_s (%d) or step_t (%d)\n",
New_Step_S, New_Step_T);
exit(1);
} /* if */
/* Allocate space for three rows if they have changed size. */
if (Row0 == NULL || Step_T != New_Step_T) {
if (Row0 != NULL) free(Row0);
Row0 = (Vector_T *) malloc( (New_Step_T+3) * sizeof(Vector_T) );
if (Row0 == NULL) Error("Error in malloc");
if (Row1 != NULL) free(Row1);
Row1 = (Vector_T *) malloc( (New_Step_T+3) * sizeof(Vector_T) );
if (Row1 == NULL) Error("Error in malloc");
if (Row2 != NULL) free(Row2);
Row2 = (Vector_T *) malloc( (New_Step_T+3) * sizeof(Vector_T) );
if (Row2 == NULL) Error("Error in malloc");
} /* if */
Step_S = New_Step_S;
Step_T = New_Step_T;
if (Verbose) fprintf(stderr, "Computing surfaces (%d):\n", Step_S - 1);
/* Initialize the first rows */
/* It is not neccessary to initialize Row0, as it is */
/* computed as the first step in the main loop. */
Compute_Row(0.0, Row1, Step_T);
Compute_Row(1.0/Step_S, Row2, Step_T);
for (i = 0; i < Step_S; i++) {
if (Verbose) {
if ( i != 0 && i % 10 == 0) fprintf(stderr, "%d", i);
else fprintf(stderr, ".");
}
/* compute next row */
Tmp_Row = Row0;
Row0 = Row1;
Row1 = Row2;
Row2 = Tmp_Row;
Compute_Row((double)(i + 2) / Step_S, Row2, Step_T);
for (j = 0; j < Step_T; j++) {
if ( (i + j) & 1 ) {
Generate_Face((double) i / Step_S, (double) j / Step_T,
&Row0[j], &Row1[j], &Row0[j+1], &Row1[j+1]);
} else {
Generate_Face((double) i / Step_S, (double) j / Step_T,
&Row1[j], &Row1[j+1], &Row0[j], &Row0[j+1]);
}
} /* for */
} /* for */
if (Verbose) fprintf(stderr, "\n");
} /* Generate_Object */
Boolean_T On_Off(Text)
char *Text;
/************************************************************************/
/* */
/* Return TRUE if text is "on" or "yes", otherwise FALSE. */
/* */
/************************************************************************/
{
if (strcmp(Text, "on") == 0 ||
strcmp(Text, "yes") == 0) return(TRUE);
return(FALSE);
} /* On_Off */
int Exec_Command(Command_Line, Line_Number)
char *Command_Line;
int Line_Number;
/************************************************************************/
/* */
/* Handle special commands: */
/* */
/* #name [object_name] */
/* Set the object name. This name will be used for new objects. */
/* */
/* #add */
/* Generate the surface, and add it to the current object. */
/* */
/* #write [object_name] */
/* Write the current object to the TTDDD file and start a new */
/* object. */
/* */
/* #generate [object_name] */
/* Generate the surface, add it to the current object, and write */
/* it to the TTDDD file. This is the same as */
/* #add followed by #write [object_name] */
/* */
/* #scale scale_factor */
/* Change the scale factor to 'scale_factor'. */
/* */
/* #phong [on|off] */
/* #smooth [on|off] */
/* Activate/Deactivate phong smoothing. */
/* */
/* #color [on|off] */
/* Activate/deactivate generation of face color info. */
/* The functions cr, cb and cg MUST be defined! */
/* */
/* #refl [on|off] */
/* Activate/deactivate generation of face reflectance info. */
/* The functions rr, rb and rg MUST be defined! */
/* */
/* #trans [on|off] */
/* Activate/deactivate generation of face transmittance info. */
/* The functions tr, tb and tg MUST be defined! */
/* */
/************************************************************************/
{
char *Command;
char *Rest;
int i;
for (i = 0; Command_Line[i] != '\0'; i++)
/* Command_Line[i] = tolower(Command_Line[i]); */
if (isupper(Command_Line[i])) Command_Line[i]=tolower(Command_Line[i]);
Command = strtok(&Command_Line[1], "\n \t");
if (Command == NULL) goto SyntaxError;
Rest = strtok(NULL, "\n \t");
if (strcmp(Command, "add") == 0) {
Generate_Object();
Generate_Done = TRUE;
} else if (strcmp(Command, "name") == 0) {
if (Rest != NULL && *Rest != '\0') strcpy(Object_Name, Rest);
} else if (strcmp(Command, "write") == 0) {
if (Rest != NULL && *Rest != '\0') strcpy(Object_Name, Rest);
if (Nbr_Points > 0) Write_TTDDD_Object();
} else if (strcmp(Command, "generate") == 0) {
if (Rest != NULL && *Rest != '\0') strcpy(Object_Name, Rest);
Generate_Object();
Generate_Done = TRUE;
if (Nbr_Points > 0) Write_TTDDD_Object();
} else if (strcmp(Command, "scale") == 0) {
if (Rest == NULL) goto SyntaxError;
Scale_Factor = atof(Rest);
if (Scale_Factor <= 0.0) {
fprintf(stderr, "Invalid scale factor in line %d:\n",
Line_Number);
fprintf(stderr, "%s\n", Command_Line);
exit(1);
}
Precision = 1.0 / Scale_Factor; /* Precision of coordinates */
if (Verbose) fprintf(stderr, "New scale factor is %lf\n",
Scale_Factor);
} else if (strcmp(Command, "phong") == 0 ||
strcmp(Command, "smooth") == 0) {
if (Rest == NULL) goto SyntaxError;
Phong = On_Off(Rest);
if (Verbose) fprintf(stderr, "Phong smoothing is %s\n",
Phong ? "on" : "off");
} else if (strcmp(Command, "color") == 0) {
if (Rest == NULL) goto SyntaxError;
Compute_Color = On_Off(Rest);
if (Verbose) fprintf(stderr, "Compute color is %s\n",
Compute_Color ? "on" : "off");
} else if (strncmp(Command, "refl", 4) == 0) {
if (Rest == NULL) goto SyntaxError;
Compute_Refl = On_Off(Rest);
if (Verbose) fprintf(stderr, "Compute reflectance is %s\n",
Compute_Refl ? "on" : "off");
} else if (strncmp(Command, "trans", 5) == 0) {
if (Rest == NULL) goto SyntaxError;
Compute_Trans = On_Off(Rest);
if (Verbose) fprintf(stderr, "Compute Transmittance is %s\n",
Compute_Trans ? "on" : "off");
} else goto SyntaxError;
return(0);
SyntaxError:
fprintf(stderr, "Invalid command in line %d:\n", Line_Number);
fprintf(stderr, "%s\n", Command_Line);
exit(1);
} /* Exec_Command */
main(argc, argv)
int argc;
char *argv[];
/************************************************************************/
/* */
/* Main program. */
/* */
/************************************************************************/
{
int i;
char *O_FileName = NULL;
if (argc == 1) Usage();
strcpy(Object_Name, "IGENSURF");
/* Allocate memory for points, edges, and faces */
if (!(Points = (Vector_T*)malloc(Max_Nbr_Points*sizeof(Vector_T))))
Error("Couldn't allocate Points");
if (!(Edges = (Edge_T*)malloc(Max_Nbr_Edges*sizeof(Edge_T))))
Error("Couldn't allocate Edges");
if (!(Faces = (Face_T*)malloc(Max_Nbr_Faces*sizeof(Face_T))))
Error("Couldn't allocate Faces");
for (i = 1; i < argc && *argv[i] == '-'; i++) {
switch (argv[i][1]) {
case 'C':
Compute_Color = TRUE;
break;
case 'R':
Compute_Refl = TRUE;
break;
case 'T':
Compute_Trans = TRUE;
break;
case 'n':
strcpy(Object_Name, argv[++i]);
break;
case 'S':
Scale_Factor = atof(argv[++i]);
if (Scale_Factor <= 0.0) {
fprintf(stderr, "Invalid scale factor %lf:\n", Scale_Factor);
exit(1);
}
Precision = 1.0 / Scale_Factor; /* Precision of coordinates */
break;
case 'p':
Phong = TRUE;
break;
case 'v':
Verbose = TRUE;
break;
case 's':
Step_S = atoi(argv[++i]);
if (Step_S <= 0) {
fprintf(stderr, "Invalid Step_S\n", Step_S);
exit(1);
}
break;
case 't':
Step_T = atoi(argv[++i]);
if (Step_T <= 0) {
fprintf(stderr, "Invalid Step_T\n", Step_T);
exit(1);
}
break;
case 'e':
String_Compile(argv[++i], NULL, 0, NULL);
break;
case 'o':
if (O_FileName != NULL) Usage();
O_FileName = argv[++i];
break;
default:
Usage();
break;
} /* switch */
} /* for */
if (Verbose) fprintf(stderr, "igensurf %s\n", Version);
if (O_FileName == NULL) O_Stream = stdout;
else {
O_Stream = fopen(O_FileName, "w");
if (O_Stream == NULL) Error("Couldn't open the output file");
}
/* Define PI, step_s and step_t so that they can be used */
/* in expressions */
eclock = 0;
Var_Set("PI", ':', PI);
Var_Set("step_s", ':', (double) Step_S);
Var_Set("step_t", ':', (double) Step_T);
while (i < argc) {
if (Verbose) fprintf(stderr, "Compiling %s\n", argv[i]);
File_Compile(argv[i++], Exec_Command);
} /* while */
if (!Generate_Done) Generate_Object();
if (Nbr_Points > 0) Write_TTDDD_Object();
if (O_Stream != stdout) fclose(O_Stream);
if (Verbose) fprintf(stderr, "Done.\n");
exit(0);
} /* main */