home *** CD-ROM | disk | FTP | other *** search
- /* RayLathe (c) Koehler
- - Thick <0 = draw solid, =0 = move, >0 = draw hollow
- Revision History:
- 03-24-93 1.00 KJK New. Inspired by uLathe.
- 03-28-93 1.01 KJK Attempting Vivid output for Doug Downs.
- 04-11-93 1.10 KJK Releasable Vivid output version.
- Noticed THICK in Vivid no supported! Must fix if possible.
- 04-11-93 1.11 KJK Cured black speckles in POVRAY output.
- 04-14-93 1.12 KJK Allow 0 length cones (rings) for Vivid.
- 04-15-93 1.13 KJK Enable THICK for Vivid. Print line # of .DAT file.
- 04-24-93 1.20 KJK Since they are necessary when thickness is used,
- simulate cone/rings for POVRAY.
- 06-28-93 1.?? esp Add POV-Ray 2.0 syntax, clean up cmdline parsing,
- add Macintosh (MPW) support, change FP compares like (x==y)
- to (fabs(x-y) < EPSILON) to better conform to
- the way fp numbers (mis)behave, add tabwidth parm, clean up
- indenting.
- 06-05-93 1.21 KJK First attempt at POVRAY triangles.
- 06-25-93 1.22 KJK Steve Anger replied to my message on YCCMR about
- what vertex order is required!
- 07-10-93 1.23 KJK Steve Anger replied again. Problem was that data has
- to be one whole object, not multiple objects.
- 07-11-93 1.24 KJK Combined Eduard Schwan's (esp) changes to 1.20 with
- my 1.23. Removed double slash comments in code to
- keep compatible with regular C. Its my understanding
- the double slash is new for C++.
- 07-20-93 1.25 KJK Doug Downs said Vivid is OK, so lets do final cleanup.
- Also, I will be looking into accepting color data
- to pass along to the RAW converters.
- Watch for seam in RAW output. I'm reluctant to fix what
- I can't prove.
- 07-20-93 2.00 KJK Final release. You know, the one just before the bug fix
- release. The verbose comments for all of the unreleased
- versions are just an informational story. "It doesn't
- matter, and so-what if it did!"
- 09-18-93 2.10 KJK Fix bug: Commas introduced by esp tabbing where they
- didn't belong.
- For POVRAY no longer #declare's name of composite shape
- in .inc file. This helps when memory is at a premium.
- Fixed examples so they work with RAW and POV output.
- */
-
-
- /* ========================================================= */
- /* INCLUDES */
-
- #include <math.h>
- #include <stdio.h> /* printf() */
- #include <stdlib.h> /* exit() */
- #include <string.h> /* strcmp() */
- #include <ctype.h> /* tolower() */
-
-
- /* ========================================================= */
- /* DEFINES */
-
- #define VERSION 2.10
-
- #ifndef min
- #define min(a,b) ((a)<(b) ? (a) : (b))
- #define max(a,b) ((a)>(b) ? (a) : (b))
- #endif
- #define EPSILON 1.0e-10 /* miniscule fp number, essentially zero */
- const double PI = 3.141592653589;
-
- /* Raytracer output styles supported */
- #define TRACER_VIVID 1
- #define TRACER_POV10 2
- #define TRACER_POV20 3
- #define TRACER_RAW 4
-
- #define DATA_OLD 0
- #define DATA_SLICED -1
- #define DATA_COLOR -2
-
- #define TAB_WIDTH 4 /* default width */
-
-
- /* ========================================================= */
- /* PROTOTYPES */
-
- static void show_usage(char *);
- static void lathe_cut_viv(double, double, double, double, double);
- static void lathe_cut_pov10(double, double, double, double, double);
- static void lathe_cut_pov20(double, double, double, double, double);
- static void lathe_tri_raw(double, double, double, double, double, unsigned char, double, double, double);
- static void tab_printf(void);
- static void tab_inc();
- static void tab_dec();
- static double intercept(double, double, double, double);
-
-
- /* ========================================================= */
- /* GLOBAL VARIABLES */
- static int tab_width = TAB_WIDTH;
- static int tab_level = 0;
-
-
- /* ========================================================= */
- int main(argc,argv)
- int argc;
- char *argv[];
- {
- int tracer = TRACER_POV10;
- int line=0;
- int k;
- double oldx = 0.01, oldy = 0.01;
- double x, y, thick;
- double boundminx=1.0e8, boundmaxx=-1.0e8, boundmaxy=0.0;
- double length, center, eye_distance;
- double colorR = -1.0, colorG = -1.0, colorB = -1.0;
- unsigned char slices = 8;
- int datatype = DATA_OLD;
-
- fprintf(stderr,"RayLathe v%2.2f (c) 1993 Koehler\n",VERSION);
-
-
- /* Check the command line options ("/" for MSDOS, "-" for Unix & Mac) */
-
- for (k=1; k<argc; k++)
- {
- /* this setup makes it easier to add new switches later */
- switch (argv[k][0])
- {
- case '/':
- case '-':
- switch (tolower(argv[k][1]))
- {
- case '?':
- show_usage(NULL);
- break;
- case 't':
- tab_width = atoi(&argv[k][2]);
- if ((tab_width < 1) || (tab_width > 16))
- show_usage(argv[k]);
- break;
- case 'v':
- tracer = TRACER_VIVID;
- fprintf(stderr," Generating Vivid 2.0 object\n");
- break;
- case 'r':
- tracer = TRACER_RAW;
- fprintf(stderr," Generating Export (RAW) object\n");
- break;
- case 'p':
- switch (argv[k][2])
- {
- case '1':
- tracer = TRACER_POV10;
- fprintf(stderr," Generating POV-Ray 1.0 object\n");
- break;
- case '2':
- tracer = TRACER_POV20;
- fprintf(stderr," Generating POV-Ray 2.0 object\n");
- break;
- default:
- show_usage(argv[k]);
- break;
- }
- break;
- default:
- show_usage(argv[k]);
- break;
- } /* switch */
- break;
-
- default:
- show_usage(argv[k]);
- break;
- } /* switch */
- } /* for */
-
-
-
- /* write header */
-
- switch (tracer)
- {
- case TRACER_VIVID:
- printf("// Vivid 2.0 object created by RayLathe v%2.2f (c) 1993 Koehler\n",VERSION);
- printf("// See overall dimensions of object at end of this file\n");
- /* printf("// See suggested camera vectors at end of this file\n"); */
- printf("\n");
- break;
- case TRACER_POV10:
- printf("// POVRAY 1.0 object created by RayLathe v%2.2f (c) 1993 Koehler\n",VERSION);
- printf("// See suggested camera vectors at end of this file\n\n");
- printf("//#declare LatheWork =\n");
- tab_inc();
- tab_printf();printf("composite\n");
- tab_printf();printf("{\n");
- tab_inc();
- break;
- case TRACER_POV20:
- printf("// POVRAY 2.0 object created by RayLathe v%2.2f (c) 1993 Koehler\n",VERSION);
- printf("// See suggested camera vectors at end of this file\n\n");
- printf("//#declare LatheWork =\n");
- tab_inc();
- tab_printf();printf("merge\n");
- tab_printf();printf("{\n");
- tab_inc();
- break;
- } /* switch */
-
-
- /* Read first line from file */
-
- scanf("%lf %lf %lf", &x, &y, &thick);
- if (x < DATA_OLD) /* LAT2RAYL v1.00 didn't give slices, v1.10 does */
- {
- datatype = x;
- slices = thick;
- scanf("%lf %lf %lf", &x, &y, &thick);
- }
- if (datatype == DATA_COLOR)
- scanf("%lf %lf %lf", &colorR, &colorG, &colorB);
- line++;
-
-
- /* loop through file */
-
- do
- {
- if (tracer != TRACER_RAW)
- {
- tab_printf();printf("// ###\n");
- tab_printf();printf("// ### Line %-4d (%lg, %lg, %lg)\n", line, x, y, thick);
- }
- if (thick)
- {
- switch (tracer)
- {
- case TRACER_VIVID:
- lathe_cut_viv(oldx, oldy, x, y, thick);
- break;
- case TRACER_POV10:
- lathe_cut_pov10(oldx, oldy, x, y, thick);
- break;
- case TRACER_POV20:
- lathe_cut_pov20(oldx, oldy, x, y, thick);
- break;
- case TRACER_RAW:
- lathe_tri_raw(oldx, oldy, x, y, thick, slices, colorR, colorG, colorB);
- break;
- } /* switch */
- }
-
- boundmaxx = max(boundmaxx, x);
- boundminx = min(boundminx, x);
- boundmaxy = max(boundmaxy, y);
- oldx = x;
- oldy = y;
-
-
- /* read next line of file */
-
- scanf("%lf %lf %lf", &x, &y, &thick);
- if (datatype == DATA_COLOR)
- scanf("%lf %lf %lf", &colorR, &colorG, &colorB);
- line++;
- } while ((x >= 0.0) || (y >= 0.0));
-
-
- /* write trailer */
-
- boundminx *= 1.001;
- boundmaxx *= 1.001;
- boundmaxy *= 1.001;
- switch (tracer)
- {
- case TRACER_VIVID:
- break;
- case TRACER_POV10:
- tab_printf();printf("bounded_by\n");
- tab_printf();printf("{\n");
- tab_inc();
- tab_printf();printf("box { <%g %g %g> <%g %g %g> }\n",boundminx,-boundmaxy,-boundmaxy, boundmaxx, boundmaxy, boundmaxy);
- tab_dec();
- tab_printf();printf("}\n");
- tab_dec();
- tab_printf();printf("} // composite\n");
- tab_dec();
- length = boundmaxx - boundminx;
- center = length / 2.0 + boundminx;
- printf("\n#declare Look_At = <%g 0 0> // Center of object\n", center);
- eye_distance = -max(fabs(length), boundmaxy*2.4);
- printf("#declare Location = <%g 0 %g> // Good camera position\n", center, eye_distance);
- break;
- case TRACER_POV20:
- tab_printf();printf("bounded_by\n");
- tab_printf();printf("{\n");
- tab_inc();
- tab_printf();printf("box { <%g %g %g> <%g %g %g> }\n",boundminx,-boundmaxy,-boundmaxy, boundmaxx, boundmaxy, boundmaxy);
- tab_dec();
- tab_printf();printf("}\n");
- tab_dec();
- tab_printf();printf("} // union\n");
- tab_dec();
- length = boundmaxx - boundminx;
- center = length / 2.0 + boundminx;
- printf("\n#declare Look_At = <%g 0 0> // Center of object\n", center);
- eye_distance = -max(fabs(length), boundmaxy*2.4);
- printf("#declare Location = <%g 0 %g> // Good camera position\n", center, eye_distance);
- break;
- } /* switch */
-
- if (tracer != TRACER_RAW)
- printf("\n// Min X Y Z = %f %f %f Max X Y Z = %f %f %f\n",boundminx,-boundmaxy,-boundmaxy, boundmaxx, boundmaxy, boundmaxy);
-
- return (0); /* Happy ANSI */
-
- } /* main */
-
-
- /* ========================================================= */
- static void show_usage(char * opt)
- {
- if (opt != NULL)
- fprintf(stderr,"### ERROR! Bad option '%s'\n", opt);
- fprintf(stderr,"### Usage: raylathe [-v | -p1 | -p2 | -r] [-tN] <infile.dat >outfile.inc\n");
- fprintf(stderr,"### where -v=Vivid, -p1=POV1.0, -p2=POV2.0, -r=RAW, -tN=tabwidth\n");
- exit(1);
- } /* show_usage */
-
-
- /* ========================================================= */
- static void lathe_cut_viv(x1, y1, x2, y2, thick)
- double x1, y1, x2, y2, thick;
- {
- /* cone { base 1 1 1 base_radius 4 apex 0 0 5 apex_radius 1 } */
- tab_printf();printf("cone { base %g 0.0 0.0 base_radius %g ", x1, y1);
- tab_inc();
- tab_printf();printf("apex %g 0.0 0.0 apex_radius %g }\n", x2, y2);
- tab_dec();
- if (thick > 0)
- {
- tab_printf();printf("cone { base %g 0.0 0.0 base_radius %g ", x1, max(y1-thick, 0.0));
- tab_inc();
- tab_printf();printf("apex %g 0.0 0.0 apex_radius %g }\n", x2, max(y2-thick, 0.0));
- tab_dec();
- tab_printf();printf("cone { base %g 0.0 0.0 base_radius %g ", x1, max(y1, 0.0));
- tab_inc();
- tab_printf();printf("apex %g 0.0 0.0 apex_radius %g }\n", x1, max(y1-thick, 0.0));
- tab_dec();
- tab_printf();printf("cone { base %g 0.0 0.0 base_radius %g ", x2, max(y2, 0.0));
- tab_inc();
- tab_printf();printf("apex %g 0.0 0.0 apex_radius %g }\n", x2, max(y2-thick, 0.0));
- tab_dec();
- }
- } /* lathe_cut_viv */
-
-
- /* ========================================================= */
- static void lathe_cut_pov10(x1, y1, x2, y2, thick)
- double x1, y1, x2, y2, thick;
- {
- double minx, miny, minz, maxx, maxy, maxz, origin;
-
- if (fabs(x1-x2) < EPSILON)
- if (fabs(thick) > EPSILON)
- x1 = x1 * 1.001; /* Fudge a flat cone (ring) */
- else
- return;
-
- minx = min(x1,x2);
- maxx = max(x1,x2);
- maxy = max(y1,y2);
- miny = -maxy;
- maxz = maxy;
- minz = miny;
-
- tab_printf();printf("object\n");
- tab_printf();printf("{\n");
- tab_inc();
- tab_printf();printf("intersection\n");
- tab_printf();printf("{\n");
- tab_inc();
- if (fabs(y1-y2) < EPSILON)
- {
- if (fabs(y1) > EPSILON)
- {
- tab_printf();printf("quadric { Cylinder_X scale <1 %g %g> }\n", y1, y1);
- }
- }
- else
- {
- if ((fabs(x1) < EPSILON) || (fabs(x2) < EPSILON))
- origin = 0;
- else
- origin=intercept(x1, y1, x2, y2);
- tab_printf();printf("quadric { QCone_X ");
-
- if (fabs(x1) < EPSILON)
- {printf("scale <%g %g %g>", fabs(origin-x2), y2, y2);}
- else
- {printf("scale <%g %g %g>", fabs(origin-x1), y1, y1);}
- printf(" translate <%g 0 0> }\n", origin);
- }
-
- if ((thick > 0.0) && (((y1-thick) > 0.0) || ((y2-thick) > 0.0)))
- {
- if (fabs(y1-y2) < EPSILON)
- {
- if ((y1-thick) > 0.0)
- {
- tab_printf();printf("quadric { Cylinder_X scale <1 %g %g> inverse }\n", y1-thick, y1-thick);
- }
- }
- else
- {
- if ((fabs(x1) < EPSILON) || (fabs(x2) < EPSILON))
- origin = 0;
- else
- origin = (((y1-thick)/y1)*(origin-x1))+x1;
- tab_printf();printf("quadric { QCone_X ");
-
- if (fabs(origin-x1) < EPSILON)
- {printf("scale <%g %g %g>", fabs(origin-x2), y2-thick, y2-thick);}
- else
- {printf("scale <%g %g %g>", fabs(origin-x1), y1-thick, y1-thick);}
- printf(" translate <%g 0 0> inverse }\n", origin);
- }
- }
-
- tab_printf();printf("box { <%g %g %g> <%g %g %g> }\n",minx,miny,minz,maxx,maxy,maxz);
- tab_dec();
- tab_printf();printf("} // intersection\n");
-
- minx = minx*1.001; /* Adjust for bounding */
- maxx = maxx*1.001;
- maxy = maxy*1.001;
- miny = -maxy;
- maxz = maxy;
- minz = miny;
-
- tab_printf();printf("bounded_by\n");
- tab_printf();printf("{\n");
- tab_inc();
- tab_printf();printf("box { <%g %g %g> <%g %g %g> }\n",minx,miny,minz,maxx,maxy,maxz);
- tab_dec();
- tab_printf();printf("}\n");
-
- tab_printf();printf("texture\n");
- tab_printf();printf("{\n");
- tab_inc();
- tab_printf();printf("LatheWorkTex\n");
- tab_dec();
- tab_printf();printf("}\n");
-
- tab_dec();
- tab_printf();printf("} // object\n");
-
- } /* lathe_cut_pov10 */
-
-
- /* ========================================================= */
- static void lathe_cut_pov20(x1, y1, x2, y2, thick)
- double x1, y1, x2, y2, thick;
- {
- double minx, miny, minz, maxx, maxy, maxz, origin;
-
- if (fabs(x1-x2) < EPSILON)
- if (fabs(thick) > EPSILON)
- x1 = x1 * 1.001; /* Fudge a flat cone (ring) */
- else
- return;
-
- minx = min(x1,x2);
- maxx = max(x1,x2);
- maxy = max(y1,y2);
- miny = -maxy;
- maxz = maxy;
- minz = miny;
-
- tab_printf();printf("intersection\n");
- tab_printf();printf("{\n");
- tab_inc();
- if (fabs(y1-y2) < EPSILON)
- {
- if (fabs(y1) > EPSILON)
- {
- tab_printf();printf("quadric { Cylinder_X scale <1 %g %g> }\n", y1, y1);
- }
- }
- else
- {
- if ((fabs(x1) < EPSILON) || (fabs(x2) < EPSILON))
- origin = 0;
- else
- origin=intercept(x1, y1, x2, y2);
- tab_printf();printf("quadric { QCone_X ");
-
- if (fabs(x1) < EPSILON)
- {printf("scale <%g %g %g>", fabs(origin-x2), y2, y2);}
- else
- {printf("scale <%g %g %g>", fabs(origin-x1), y1, y1);}
- printf(" translate %g*x }\n", origin);
- }
-
- if ((thick > 0.0) && (((y1-thick) > 0.0) || ((y2-thick) > 0.0)))
- {
- if (fabs(y1-y2) < EPSILON)
- {
- if ((y1-thick) > 0.0)
- {
- tab_printf();printf("quadric { Cylinder_X scale <1, %g %g> inverse }\n", y1-thick, y1-thick);
- }
- }
- else
- {
- if ((fabs(x1) < EPSILON) || (fabs(x2) < EPSILON))
- origin = 0;
- else
- origin = (((y1-thick)/y1)*(origin-x1))+x1;
- tab_printf();printf("quadric { QCone_X ");
-
- if (fabs(origin-x1) < EPSILON)
- {printf("scale <%g %g %g>", fabs(origin-x2), y2-thick, y2-thick);}
- else
- {printf("scale <%g %g %g>", fabs(origin-x1), y1-thick, y1-thick);}
- printf(" translate %g*x inverse }\n", origin);
- }
- }
-
- tab_printf();printf("box { <%g %g %g> <%g %g %g> }\n",minx,miny,minz,maxx,maxy,maxz);
-
- minx = minx*1.001; /* Adjust for bounding */
- maxx = maxx*1.001;
- maxy = maxy*1.001;
- miny = -maxy;
- maxz = maxy;
- minz = miny;
-
- tab_printf();printf("bounded_by\n");
- tab_printf();printf("{\n");
- tab_inc();
- tab_printf();printf("box { <%g %g %g> <%g %g %g> }\n",minx,miny,minz,maxx,maxy,maxz);
- tab_dec();
- tab_printf();printf("}\n");
-
- tab_printf();printf("texture\n");
- tab_printf();printf("{\n");
- tab_inc();
- tab_printf();printf("LatheWorkTex\n");
- tab_dec();
- tab_printf();printf("}\n");
-
- tab_dec();
- tab_printf();printf("} // intersection\n");
-
- } /* lathe_cut_pov20 */
-
-
- /* ========================================================= */
- static void lathe_tri_raw(x1, y1, x2, y2, thick, slices, colorR, colorG, colorB)
- double x1, y1, x2, y2, thick, colorR, colorG, colorB;
- unsigned char slices;
- {
- double byo, bzo, cy1, cz1, byi, bzi, cy3, cz3;
- double ark, angle;
- double pointy, pointz;
-
- ark= (2 * PI / slices);
- byo = 0; /* set outside for first pass */
- bzo = y2;
- cy1 = 0;
- cz1 = y1;
- byi = 0; /* same for inside */
- bzi = y2-thick;
- cy3 = 0;
- cz3 = y1-thick;
- for (angle=ark; angle<(2 * PI); angle+=ark)
- {
- pointy=sin(angle);
- pointz=cos(angle);
- if (y1 > 0)
- {
- if ( colorR >= 0)
- printf("%g %g %g ", colorR, colorG, colorB);
- /*A*/ printf("%g %g %g ", x1, (pointy*y1), (pointz*y1));
- /*D*/ printf("%g %g %g ", x2, byo, bzo );
- /*C*/ printf("%g %g %g\n", x1, cy1, cz1);
- }
- if (y2 > 0)
- {
- if ( colorR >= 0)
- printf("%g %g %g ", colorR, colorG, colorB);
- /*A*/ printf("%g %g %g ", x1, (pointy*y1), (pointz*y1) );
- /*B*/ printf("%g %g %g ", x2, (pointy*y2), (pointz*y2));
- /*D*/ printf("%g %g %g\n", x2, byo, bzo );
- }
- byo = (pointy*y2); /* update for next pass */
- bzo = (pointz*y2);
- cy1 = (pointy*y1);
- cz1 = (pointz*y1);
-
- if ((thick >= 0) && (((y1-thick)>0) || ((y2-thick)>0)))
- {
- if ((y1-thick) > 0)
- {
- if ( colorR >= 0)
- printf("%g %g %g ", colorR, colorG, colorB);
- /*A*/ printf("%g %g %g ", x1, (pointy*(y1-thick)), (pointz*(y1-thick)) );
- /*D*/ printf("%g %g %g ", x2, byi, bzi );
- /*C*/ printf("%g %g %g\n", x1, cy3, cz3);
- }
- if ((y2-thick) > 0)
- {
- if ( colorR >= 0)
- printf("%g %g %g ", colorR, colorG, colorB);
- /*A*/ printf("%g %g %g ", x1, (pointy*(y1-thick)), (pointz*(y1-thick)) );
- /*B*/ printf("%g %g %g ", x2, (pointy*(y2-thick)), (pointz*(y2-thick)));
- /*D*/ printf("%g %g %g\n", x2, byi, bzi );
- }
- byi = (pointy*(y2-thick)); /* update for next pass */
- bzi = (pointz*(y2-thick));
- cy3 = (pointy*(y1-thick));
- cz3 = (pointz*(y1-thick));
- }
- }
- }
-
-
- /* ========================================================= */
- static double intercept(x1, y1, x2, y2)
- double x1, y1, x2, y2;
- {
- return(x2 - ((x2-x1) / (y2-y1) * y2));
- } /* intercept */
-
-
- /* ========================================================= */
- static void tab_printf(void)
- {
- int k;
- /* Q&D way to do it... */
- for (k=0; k<tab_width*tab_level; k++)
- putchar(' ');
- } /* tab_printf */
-
-
- /* ========================================================= */
- static void tab_inc()
- {
- tab_level++;
- } /* tab_inc */
-
-
- /* ========================================================= */
- static void tab_dec()
- {
- tab_level--;
- if (tab_level < 0)
- tab_level = 0;
- } /* tab_dec */