home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright 1992 Mark Spychalla
-
- Permission to use, copy, modify, distribute, and sell this software and
- its documentation for any purpose is hereby granted without fee,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the name of Mark Spychalla not be used
- in advertising or publicity pertaining to distribution of the software
- without specific, written prior permission. Mark Spychalla makes no
- representations about the suitability of this software for any purpose.
- It is provided "as is" without express or implied warranty.
-
- Mark Spychalla disclaims all warranties with regard to this software,
- including all implied warranties of merchantability and fitness, in no
- event shall Mark Spychalla be liable for any special, indirect or
- consequential damages or any damages whatsoever resulting from loss of use,
- data or profits, whether in an action of contract, negligence or other
- tortious action, arising out of or in connection with the use or performance
- of this software.
- */
-
-
-
- /*
-
- NOTE ON X3D CODING STYLE:
-
- Don't think I usually code in the gerberized fashion that X3D demonstrates.
- X3D was written for speed at any cost. My goal was to write the fastest 3D
- object viewer that I could, period. Regular programs ought to be written
- with different goals in mind such as:
-
- 1) A program has excellent documentation that ANYONE can read.
- 2) A program when released has no strange "features" or bugs.
- 3) A program is robust and handles ALL extreme and unusual cases.
- 4) A program is written in phases and modules with hard tests for each one.
- 5) A program is written for any user who doesn't need special knowledge
- to use the program.
- 6) A program has well defined user requirements and functional specifications.
- 7) A program is written with regard to future expansion and integreation
- with other systems (portability).
-
- When programming following these additional principles make programs easier
- to maintain.
-
- A) Choose variable names that accurately describes what the variable does/is.
- B) Write comments to inform someone faced with the task of modifying your code.
- C) Avoid excessive comments. Write the code so that it says what it does.
- D) Follow a strict one-in, one-out flow of control structues except in the
- case of fatal error conditions.
- E) Avoid using global variables.
- F) Do not cause side effects to variables that were not parameters to a
- function.
- G) Have a single function perform a single purpose.
- H) Select a single indentation style and stick with it.
- I) Use a consistent naming convention.
-
- The following principles help me when I try optimizing code:
-
- a) If optimizing, use a profiler to determine which sections of code most of
- the time is spent in. Spend most of your effort in the most used sections.
- Don't bother optimizing a procedure using less than 10% of the time.
-
- b) High level optimizations are far more effective than cycle shaving.
- (e.g. use quick sort instead of optimizing a bubble sort.)
-
- c) Be flexible in your approach to solving a problem. List exactly what you
- need as a result at a minimum. Get rid of unnecessary assumptions.
-
- d) Become familiar with sets of operations that are equivalent, or nearly so.
- Learn the relative expense of basic operations.
-
- e) If possible, be careful not to needlessly sacrifice significant readability
- of the code for a cycle or two.
-
- -- Spy
-
- */
-
- #include <stdio.h>
- #include <math.h>
- #include <X11/Xlib.h>
- #include <X11/Xatom.h>
- #include <X11/Xutil.h>
- #include <X11/X.h>
- #include "x3d.h"
-
-
-
- static void sort(list, numPolys)
- polygon **list;
- int numPolys;
- /*****************************************************************************
- Specialized quick sort for painter algorithm.
- *****************************************************************************/
- {
- polygon **v0, **v1, **v2, **v3, **v4, **v5, **v6, *poly;
- register int stackIndex, stackNotSet, length, start, end, high;
- float dist;
- int numPoints;
- StackElement stack[MAXSTACK];
- point **Point, **lastPoint;
-
- v0 = list;
- v1 = &(list[numPolys]);
-
- /* Set the key value to be the average of the vertices' distances */
-
- while(v0 < v1){
- poly = *v0;
- numPoints = poly->numPoints;
- Point = poly->points;
- lastPoint = Point + numPoints;
- dist = 0.0;
-
- do{
- dist += (*Point)->dist;
- Point++;
- }while(Point < lastPoint);
-
- poly->dist = dist / ((float)numPoints);
- v0++;
- }
-
- /* Initialize for the qsort() */
-
- stackIndex = 1;
- stackNotSet = 0;
- start = 0;
- end = numPolys - 1;
-
- /* Do Qsort */
-
- while(stackIndex){
-
- if(stackNotSet){
- start = stack[stackIndex].start;
- end = stack[stackIndex].end;
- }
-
- stackIndex--;
- stackNotSet = 1;
- length = end - start;
-
- /* Big enough to qsort ? */
-
- if(length > STOP){
- v1 = &(list[start]);
- v2 = &(list[start + (length / 4)]);
- v3 = &(list[start + (length / 2)]);
- v4 = &(list[start + ((length * 3) / 4)]);
- v5 = &(list[end]);
- v6 = v1;
-
- median5(v1,v2,v3,v4,v5)
-
- *v0 = *v3;
- *v3 = *v6;
- *v6 = *v0;
-
- v1 = &(list[start + 1]);
- v2 = &(list[end]);
-
- /* Split */
-
- dist = (*v6)->dist;
- while((*v2)->dist < dist) v2--;
- while((*v1)->dist > dist) v1++;
-
- v5 = v0;
-
- while(v1 < v2){
-
- *v5 = *v2;
- *v2 = *v1;
-
- v5 = v1;
-
- do{
- v2--;
- }while((*v2)->dist < dist);
-
- do{
- v1++;
- }while((*v1)->dist > dist);
-
- }
-
- v2 = v1 - 1;
-
- *v5 = *v2;
- *v2 = *v6;
- *v6 = *v0;
-
- high = v2 - list;
-
- /* Put sublists on the stack, smallest on top */
-
- if((high - start) > (end - high)){
- stack[++stackIndex].start = start;
- stack[stackIndex].end = high - 1;
- ++stackIndex;
- start = high + 1;
- stackNotSet = 0;
- }else{
- stack[++stackIndex].start = high + 1;
- stack[stackIndex].end = end;
- ++stackIndex;
- end = high - 1;
- stackNotSet = 0;
- }
- }
- }
-
- /* insertion sort all the remaining sublists at once */
-
- v2 = list;
- v3 = &(list[numPolys - 1]);
- v4 = v2 + 1;
-
- while(v4 <= v3){
-
- *v0 = *v4;
- v1 = v4 - 1;
-
- while((v1 >= v2) && ((*v1)->dist < (*v0)->dist)){
- *(v1 + 1) = *v1;
- v1--;
- }
-
- *(v1 + 1) = *v0;
- v4++;
- }
- }
-
-
-
- static int readLine(fd, line, lineNo)
- FILE *fd;
- char *line;
- int *lineNo;
- /******************************************************************************
- Read a significant line from a file.
- ******************************************************************************/
- {
- float value;
-
- do{
- if(fgets(line, MAXLINE, fd) == NULL){
- if(feof(fd)){
- return ERROR;
- }else{
- fprintf(stderr, "fgets() failed on line %d\n", *lineNo);
- exit(1);
- }
- }else{
- (*lineNo)++;
-
- /* Warn about long lines */
-
- if(strlen(line) > (MAXLINE - 5)){
- fprintf(stderr, "Line too long on line %d, line may be trucated.\n",
- *lineNo);
- exit(1);
- }
- }
- }while(sscanf(line, "%f", &value) <= 0);
-
- return EOK;
- }
-
-
-
- static void readObjectFile(filename, colors, numColors, points, numPoints, segs,
- numSegs, polys, numPolys, list, bounds)
- char *filename;
- Color **colors;
- int *numColors;
- point **points;
- int *numPoints;
- segment **segs;
- int *numSegs;
- polygon **polys;
- int *numPolys;
- polygon ***list;
- point **bounds;
- /******************************************************************************
- Read the point list and segment list from a file. We allocate space
- for both lists.
- ******************************************************************************/
- {
- FILE *fd;
- char line[MAXLINE], s[MAXLINE];
- int index, index2, lineNo = 0, p, q, num, seg, color, count;
- point *prevPoint;
- segment *tmpSeg;
- float xMin, xMax, yMin, yMax, zMin, zMax;
- float x, y, z;
-
- /* Can we open the file? */
-
- if(!filename){
- (void)fprintf(stderr, "No file specified\n"); exit(1);}
-
- if(!strcmp(filename, "-"))
- fd = stdin;
- else
- if((fd = fopen(filename, "r")) == NULL){
- (void)fprintf(stderr, "Unable to open file: %s\n", filename);
- exit(1);
- }
-
- /* Allocate space for bounding points */
-
- if((*bounds = (point *)calloc(1, NUMBOUNDS * sizeof(point))) == NULL){
- (void)fprintf(stderr, "Unable to allocate memory for bounds\n");
- exit(1);
- }
-
- /* Read colors */
-
- if(readLine(fd, line, &lineNo)){
- (void)fprintf(stderr, "Number of colors not specified\n");
- exit(1);
- }
-
- sscanf(line, "%d", numColors);
-
- if((*colors = (Color *)calloc(1, (*numColors + 4) * sizeof(Color))) == NULL){
- (void)fprintf(stderr, "Unable to allocate memory for colors\n");
- exit(1);
- }
-
- for(index = 0; index < *numColors; index++){
- if(readLine(fd, line, &lineNo)){
- (void)fprintf(stderr, "Expected color on line %d\n", lineNo);
- exit(1);
- }
-
- if(sscanf(line, "%d %d %d %d", &num, &((*colors)[index].red),
- &((*colors)[index].green), &((*colors)[index].blue)) != 4){
- fprintf(stderr, "Error reading color on line %d\n", lineNo);
- exit(1);
- }
-
- if((((*colors)[index].red< 0) || ((*colors)[index].red > 255)) ||
- (((*colors)[index].green < 0) || ((*colors)[index].green > 255)) ||
- (((*colors)[index].blue < 0) || ((*colors)[index].blue > 255))){
- fprintf(stderr, "Color out of range on line %d\n", lineNo);
- exit(1);
- }
- }
-
- /* Read points */
-
- if(readLine(fd, line, &lineNo)){
- (void)fprintf(stderr, "Number of points not specified\n");
- exit(1);
- }
-
- sscanf(line, "%d", numPoints);
-
- if((*points = (point *)calloc(1, *numPoints * sizeof(point))) == NULL){
- (void)fprintf(stderr, "Unable to allocate memory for points\n");
- exit(1);
- }
-
- for(index = 0; index < *numPoints; index++){
- if(readLine(fd, line, &lineNo)){
- (void)fprintf(stderr, "Expected point on line %d\n", lineNo);
- exit(1);
- }
-
- if(sscanf(line, "%d %f %f %f", &num, &x, &y, &z) != 4){
- fprintf(stderr, "Error reading point on line %d\n", lineNo);
- exit(1);
- }
-
- (*points)[index].x = (number)x;
- (*points)[index].y = (number)y;
- (*points)[index].z = (number)z;
- }
-
- /* Read segments */
-
- if(readLine(fd, line, &lineNo)){
- (void)fprintf(stderr, "Number of segments not specified\n");
- exit(1);
- }
-
- sscanf(line, "%d", numSegs);
-
- if((*segs = (segment *)calloc(1, *numSegs * sizeof(segment))) == NULL){
- (void)fprintf(stderr, "Unable to allocate memory for segments\n");
- exit(1);
- }
-
- for(index = 0; index < *numSegs; index++){
- if(readLine(fd, line, &lineNo)){
- (void)fprintf(stderr, "Expected segment on line %d\n", lineNo);
- exit(1);
- }
-
- if(sscanf(line, "%d %d %d %d", &num, &color,
- &p, &q) != 4){
- fprintf(stderr, "Error reading segment on line %d\n", lineNo);
- exit(1);
- }
-
- if((p < 0) || (q < 0) || (p >= *numPoints) || (q >= *numPoints) ||
- (color < 0) || (color >= *numColors)){
- fprintf(stderr, "Segment value out of range on line %d\n", lineNo);
- exit(1);
- }
-
- (*segs)[index].color = &((*colors)[color]);
- (*segs)[index].P = &((*points)[p]);
- (*segs)[index].Q = &((*points)[q]);
-
- /* Update points' segment lists */
-
- if((*points)[p].numSegs == 0){
- if(((*points)[p].segs = (segment **)calloc(1, sizeof(segment *)))
- == NULL){
- fprintf(stderr,
- "Unable to allocate memory for point segments on line %d\n",
- lineNo);
- exit(1);
- }
- }else{
- if(((*points)[p].segs = (segment **)realloc((*points)[p].segs,
- ((*points)[p].numSegs + 1) * sizeof(segment *))) == NULL){
- fprintf(stderr,
- "Unable to allocate memory for point segments on line %d\n",
- lineNo);
- exit(1);
- }
- }
-
- if((*points)[q].numSegs == 0){
- if(((*points)[q].segs = (segment **)calloc(1, sizeof(segment *)))
- == NULL){
- fprintf(stderr,
- "Unable to allocate memory for point segments on line %d\n",
- lineNo);
- exit(1);
- }
- }else{
- if(((*points)[q].segs = (segment **)realloc((*points)[q].segs,
- ((*points)[q].numSegs + 1) * sizeof(segment *))) == NULL){
- fprintf(stderr,
- "Unable to allocate memory for point segments on line %d\n",
- lineNo);
- exit(1);
- }
- }
-
- (*points)[p].segs[(*points)[p].numSegs] = &((*segs)[index]);
- (*points)[q].segs[(*points)[q].numSegs] = &((*segs)[index]);
- (*points)[p].numSegs++;
- (*points)[q].numSegs++;
- }
-
- /* Read polygons */
-
- if(readLine(fd, line, &lineNo)){
- (void)fprintf(stderr, "Number of polygons not specified\n");
- exit(1);
- }
-
- sscanf(line, "%d", numPolys);
-
- if((*polys = (polygon *)calloc(1, *numPolys * sizeof(polygon))) == NULL){
- (void)fprintf(stderr, "Unable to allocate memory for polygons\n");
- exit(1);
- }
-
- for(index = 0; index < *numPolys; index++){
- if(readLine(fd, line, &lineNo)){
- (void)fprintf(stderr, "Expected polygon on line %d\n", lineNo);
- exit(1);
- }
-
- if(sscanf(line, "%d %d %d %[^#]", &num, &color,
- &((*polys)[index].numSegs), s) != 4){
- fprintf(stderr, "Error reading polygon on line %d\n", lineNo);
- exit(1);
- }
-
- if((color < 0) || (color >= *numColors) ||
- ((*polys)[index].numSegs <= 2)){
- fprintf(stderr, "Polygon value out of range on line %d\n", lineNo);
- exit(1);
- }
-
- if(((*polys)[index].segs = (segment **)calloc(1, (*polys)[index].numSegs *
- sizeof(segment *))) == NULL){
- fprintf(stderr,
- "Unable to allocate memory for polygon segments on line %d\n", lineNo);
- exit(1);
- }
-
- (*polys)[index].color = &((*colors)[color]);
-
- for(index2 = 0; index2 < (*polys)[index].numSegs; index2++){
-
- strcpy(line, s);
-
- count = sscanf(line, "%d %[^#]", &seg, s);
-
- if(!((count == 2) || ((count == 1) &&
- (index2 == ((*polys)[index].numSegs - 1))))){
- fprintf(stderr, "Error reading polygon on line %d\n", lineNo);
- exit(1);
- }
-
- if((seg < 0) || (seg >= *numSegs)){
- fprintf(stderr, "Polygon value out of range on line %d\n",
- lineNo);
- exit(1);
- }
-
- (*polys)[index].segs[index2] = &((*segs)[seg]);
-
- /* Update segments' polygon lists */
-
- if((*segs)[seg].numPolys == 0){
- if(((*segs)[seg].polys = (polygon **)calloc(1, sizeof(polygon *)))
- == NULL){
- fprintf(stderr,
- "Unable to allocate memory for segment polygons on line %d\n",
- lineNo);
- exit(1);
- }
- }else{
- if(((*segs)[seg].polys = (polygon **)realloc((*segs)[seg].polys,
- ((*segs)[seg].numPolys + 1) * sizeof(polygon *))) == NULL){
- fprintf(stderr,
- "Unable to allocate memory for segment polygons on line %d\n",
- lineNo);
- exit(1);
- }
- }
-
- (*segs)[seg].polys[((*segs)[seg].numPolys)] = &((*polys)[index]);
- ((*segs)[seg].numPolys)++;
- }
- }
-
- if(readLine(fd, line, &lineNo) == EOK){
- (void)fprintf(stderr, "WARNING: file not entirely read, line %d\n",
- lineNo);
- }
-
- /* Close file */
-
- (void)fclose(fd);
-
- /* Make polygon pointer array */
-
- if((*list = (polygon **)calloc(1, *numPolys * sizeof(polygon *))) == NULL){
- (void)fprintf(stderr, "Unable to allocate memory for pointer list\n"); exit(1);}
-
- for(index = 0; index < *numPolys; index++){
- (*list)[index] = &((*polys)[index]);
- }
-
- /* Update more lists */
-
- for(index = 0; index < *numPolys; index++){
-
- index2 = 0;
-
- if(((*list)[index]->segs[0]->P ==
- (*list)[index]->segs[1]->P) ||
- ((*list)[index]->segs[0]->P ==
- (*list)[index]->segs[1]->Q)){
- prevPoint = (*list)[index]->segs[0]->Q;
- }else{
- prevPoint = (*list)[index]->segs[0]->P;
- }
-
- while(index2 < (*list)[index]->numSegs){
-
- tmpSeg = (*list)[index]->segs[index2];
-
- if(tmpSeg->P == prevPoint){
- prevPoint = tmpSeg->Q;
- }else{
- prevPoint = tmpSeg->P;
- }
-
- /* Update points' polygon lists */
-
- if(prevPoint->numPolys == 0){
- if((prevPoint->polys = (polygon **)calloc(1, sizeof(polygon *)))
- == NULL){
- fprintf(stderr,
- "Unable to allocate memory for point polygons\n");
- exit(1);
- }
- }else{
- if((prevPoint->polys = (polygon **)realloc(prevPoint->polys,
- (prevPoint->numPolys + 1) * sizeof(polygon *))) == NULL){
- fprintf(stderr,
- "Unable to allocate memory for point polygons\n");
- exit(1);
- }
- }
-
- prevPoint->polys[prevPoint->numPolys] = &((*polys)[index]);
- (prevPoint->numPolys)++;
-
- /* Update polygons' point lists */
-
- if((*polys)[index].numPoints == 0){
- if(((*polys)[index].points = (point **)calloc(1, sizeof(point *)))
- == NULL){
- fprintf(stderr,
- "Unable to allocate memory for polygon points\n");
- exit(1);
- }
- }else{
- if(((*polys)[index].points = (point **)realloc(
- (*polys)[index].points, ((*polys)[index].numPoints + 1) *
- sizeof(point *))) == NULL){
- fprintf(stderr,
- "Unable to allocate memory for point polygons\n");
- exit(1);
- }
- }
-
- (*polys)[index].points[(*polys)[index].numPoints] = prevPoint;
- ((*polys)[index].numPoints)++;
-
- index2++;
- }
- }
-
- /* Calculate the bounding cube */
-
- xMin = xMax = (*points)[0].x;
- yMin = yMax = (*points)[0].y;
- zMin = zMax = (*points)[0].z;
-
- for(index = 1; index < *numPoints; index++){
-
- if((*points)[index].x < xMin){
- xMin = (*points)[index].x;
- }
- if((*points)[index].x > xMax){
- xMax = (*points)[index].x;
- }
-
- if((*points)[index].y < yMin){
- yMin = (*points)[index].y;
- }
- if((*points)[index].y > yMax){
- yMax = (*points)[index].y;
- }
-
- if((*points)[index].z < zMin){
- zMin = (*points)[index].z;
- }
- if((*points)[index].z > zMax){
- zMax = (*points)[index].z;
- }
- }
-
- (*bounds)[0].x = xMin; (*bounds)[0].y = yMin; (*bounds)[0].z = zMin;
- (*bounds)[1].x = xMin; (*bounds)[1].y = yMin; (*bounds)[1].z = zMax;
- (*bounds)[2].x = xMin; (*bounds)[2].y = yMax; (*bounds)[2].z = zMin;
- (*bounds)[3].x = xMin; (*bounds)[3].y = yMax; (*bounds)[3].z = zMax;
- (*bounds)[4].x = xMax; (*bounds)[4].y = yMin; (*bounds)[4].z = zMin;
- (*bounds)[5].x = xMax; (*bounds)[5].y = yMin; (*bounds)[5].z = zMax;
- (*bounds)[6].x = xMax; (*bounds)[6].y = yMax; (*bounds)[6].z = zMin;
- (*bounds)[7].x = xMax; (*bounds)[7].y = yMax; (*bounds)[7].z = zMax;
- }
-
-
-
- static void ParseCommandLine(argc, argv, filename, g)
- int argc;
- char *argv[];
- char **filename;
- Ginfo *g;
- /******************************************************************************
- Parse the command line set the filename and the appropriate flags
- ******************************************************************************/
- {
-
- static char options[][MAXOPTIONLEN] = {
- "-help",
- "-display",
- "-geometry"
- };
-
- int NUMOPTIONS = 3;
- int index, option, filenameValid = 0;
-
- g->helpMenu = 0;
- g->DisplayName = g->Geometry = NULL;
-
- /* Default values for flags */
-
- g->renderMode = WIREFRAME;
- g->buffer = 1;
- g->mono = 0;
- g->stereo = 1;
- g->stereoBlue = 0;
-
- for(index = 1; index < argc; index++){
- for(option = 0; option < NUMOPTIONS; option++)
- if(!strcmp(argv[index], options[option]))
- break;
-
- switch(option){
-
- case 0:
- (void)fprintf(stderr, "Options:\n");
- (void)fprintf(stderr, "-display <display> X display name\n");
- (void)fprintf(stderr, "-geometry <geometry> Window geometry\n");
- (void)fprintf(stderr, "-help Print this message\n");
- (void)fprintf(stderr, "\n");
- (void)fprintf(stderr, "Type M or m to get a help menu\n");
- (void)fprintf(stderr, "when the program is running\n");
- (void)fprintf(stderr, "\n");
- exit(0);
- break;
-
- case 1:
- g->DisplayName = argv[++index];
- break;
-
- case 2:
- g->Geometry = argv[++index];
- break;
-
- default:
- if(!filenameValid){
- *filename = (char *)(argv[index]);
- filenameValid = 1;
- }else{
- (void)fprintf(stderr,"usage: %s <object file>\n", argv[0]);
- (void)fprintf(stderr,"%s -help for a list of options\n", argv[0]);
- exit(1);
- }
- break;
- }
- }
-
- if(!filenameValid){
- (void)fprintf(stderr,"usage: %s <object file>\n", argv[0]);
- (void)fprintf(stderr,"%s -help for a list of options\n", argv[0]);
- exit(1);
- }
- }
-
-
-
- static void Rotate(points, cx, cy, cz, sx, sy, sz)
- anglePoint *points;
- double cx, cy, cz, sx, sy, sz;
- /******************************************************************************
- Rotate about Z, X, then Y, for two points.
- ******************************************************************************/
- {
- int index;
- double x, y, z, t;
-
- for(index = 0; index < 2; index++){
- x = points[index].x;
- y = points[index].y;
- z = points[index].z;
-
- t = x * cz + y * sz;
- y = y * cz - x * sz;
- x = t;
-
- points[index].y = y * cx + z * sx;
-
- z = z * cx - y * sx;
-
- points[index].x = x * cy + z * sy;
- points[index].z = z * cy - x * sy;
- }
- }
-
-
-
- static double DotProduct(x1, Y1, x2, y2)
- double x1, Y1, x2, y2;
- /******************************************************************************
- Dot product (calculate the cosine of the angle between two vectors).
- ******************************************************************************/
- {
- double temp;
-
- if((x1 == 0.0 && Y1 == 0.0)){
- return 1.0;
- }
-
- temp = sqrt(x1 * x1 + Y1 * Y1);
- x1 = x1 / temp;
- Y1 = Y1 / temp;
-
- temp = x1 * x2 + Y1 * y2;
-
- if(temp > 1.0)
- temp = fmod(temp, 1.0);
-
- if(temp < -1.0)
- temp = -fmod(-temp, 1.0);
-
- return(temp);
- }
-
-
-
- static void CalculateAngles(X, Y, Z, X1, Y1, Z1)
- double *X, *Y, *Z;
- double X1, Y1, Z1;
- /******************************************************************************
- Calculate what the result of the angle changes of X1, Y1, and Z1 are
- in my weird coordinate system.
- ******************************************************************************/
- {
- anglePoint points[2];
-
- points[0].x = 0.0; points[0].y = 0.0; points[0].z = 1.0;
- points[1].x = 1.0; points[1].y = 0.0; points[1].z = 0.0;
-
- Rotate(points, cos(*X), cos(*Y), cos(*Z), sin(*X), sin(*Y), sin(*Z));
- Rotate(points, cos(X1), cos(Y1), cos(Z1), sin(X1), sin(Y1), sin(Z1));
-
- *Y = acos(DotProduct(points[0].x, points[0].z, 0.0, 1.0));
-
- if(points[0].x < 0.0)
- *Y = -*Y;
-
- Rotate(points, 1.0, cos(-*Y), 1.0, 0.0, sin(-*Y), 0.0);
- *X = acos(DotProduct(points[0].y, points[0].z, 0.0, 1.0));
-
- if(points[0].y < 0.0)
- *X = -*X;
-
- Rotate(points, cos(-*X), 1.0, 1.0, sin(-*X), 0.0, 0.0);
- *Z = acos(DotProduct(points[1].x, points[1].y, 1.0, 0.0));
-
- if(!(points[1].y < 0.0))
- *Z = -*Z;
- }
-
-
-
- static void DrawLogo(g, x, y)
- Ginfo *g;
- int x, y;
- /******************************************************************************
- Display the Logo.
- ******************************************************************************/
- {
- int hUnit, vUnit;
- XPoint points[512];
-
- hUnit = XTextWidth(g->font, LONGESTSTRING, strlen(LONGESTSTRING)) /
- strlen(LONGESTSTRING);
- vUnit = FONTHEIGHT(g->font);
-
- /* X */
-
- points[0].x = 9 * hUnit + x; points[0].y = 1 * vUnit + y;
- points[1].x = 9 * hUnit + vUnit + x; points[1].y = 1 * vUnit + y;
- points[2].x = 14 * hUnit + vUnit + x; points[2].y = 6 * vUnit + y;
- points[3].x = 14 * hUnit + x; points[3].y = 6 * vUnit + y;
-
- XFillPolygon(g->dpy, g->helpWin, g->helpGc, points, 4, Convex,
- CoordModeOrigin);
-
- points[0].x = 14 * hUnit + vUnit + x; points[0].y = 1 * vUnit + y;
- points[1].x = 14 * hUnit + x; points[1].y = 1 * vUnit + y;
- points[2].x = 9 * hUnit + x; points[2].y = 6 * vUnit + y;
- points[3].x = 9 * hUnit + vUnit + x; points[3].y = 6 * vUnit + y;
-
- XFillPolygon(g->dpy, g->helpWin, g->helpGc, points, 4, Convex,
- CoordModeOrigin);
-
- /* 3 */
-
- points[0].x = 18 * hUnit + x; points[0].y = 1 * vUnit + y;
- points[1].x = 22 * hUnit + x; points[1].y = 1 * vUnit + y;
- points[2].x = 23 * hUnit + x; points[2].y = 2 * vUnit + y;
- points[3].x = 18 * hUnit + x; points[3].y = 2 * vUnit + y;
-
- XFillPolygon(g->dpy, g->helpWin, g->helpGc, points, 4, Convex,
- CoordModeOrigin);
-
- points[0].x = 23 * hUnit - vUnit + x; points[0].y = 2 * vUnit + y;
- points[1].x = 23 * hUnit + x; points[1].y = 2 * vUnit + y;
- points[2].x = 23 * hUnit + x; points[2].y = 3 * vUnit + y;
- points[3].x = 23 * hUnit - vUnit + x; points[3].y = 4 * vUnit + y;
-
- XFillPolygon(g->dpy, g->helpWin, g->helpGc, points, 4, Convex,
- CoordModeOrigin);
-
- points[0].x = 23 * hUnit - vUnit + x; points[0].y = 3 * vUnit + y;
- points[1].x = 23 * hUnit + x; points[1].y = 4 * vUnit + y;
- points[2].x = 23 * hUnit + x; points[2].y = 5 * vUnit + y;
- points[3].x = 23 * hUnit - vUnit + x; points[3].y = 5 * vUnit + y;
-
- XFillPolygon(g->dpy, g->helpWin, g->helpGc, points, 4, Convex,
- CoordModeOrigin);
-
- points[0].x = 18 * hUnit + x; points[0].y = 5 * vUnit + y;
- points[1].x = 23 * hUnit + x; points[1].y = 5 * vUnit + y;
- points[2].x = 22 * hUnit + x; points[2].y = 6 * vUnit + y;
- points[3].x = 18 * hUnit + x; points[3].y = 6 * vUnit + y;
-
- XFillPolygon(g->dpy, g->helpWin, g->helpGc, points, 4, Convex,
- CoordModeOrigin);
-
- points[0].x = 19 * hUnit + x; points[0].y = 3 * vUnit + y;
- points[1].x = 23 * hUnit - vUnit + x; points[1].y = 3 * vUnit + y;
- points[2].x = 23 * hUnit - vUnit + x; points[2].y = 4 * vUnit + y;
- points[3].x = 19 * hUnit + x; points[3].y = 4 * vUnit + y;
-
- XFillPolygon(g->dpy, g->helpWin, g->helpGc, points, 4, Convex,
- CoordModeOrigin);
-
- /* D */
-
- points[0].x = 26 * hUnit + x; points[0].y = 1 * vUnit + y;
- points[1].x = 30 * hUnit + x; points[1].y = 1 * vUnit + y;
- points[2].x = 30 * hUnit + vUnit + x; points[2].y = 2 * vUnit + y;
- points[3].x = 26 * hUnit + x; points[3].y = 2 * vUnit + y;
-
- XFillPolygon(g->dpy, g->helpWin, g->helpGc, points, 4, Convex,
- CoordModeOrigin);
-
- points[0].x = 26 * hUnit + x; points[0].y = 5 * vUnit + y;
- points[1].x = 30 * hUnit + vUnit + x; points[1].y = 5 * vUnit + y;
- points[2].x = 30 * hUnit + x; points[2].y = 6 * vUnit + y;
- points[3].x = 26 * hUnit + x; points[3].y = 6 * vUnit + y;
-
- XFillPolygon(g->dpy, g->helpWin, g->helpGc, points, 4, Convex,
- CoordModeOrigin);
-
- points[0].x = 26 * hUnit + x; points[0].y = 1 * vUnit + y;
- points[1].x = 26 * hUnit + vUnit + x; points[1].y = 1 * vUnit + y;
- points[2].x = 26 * hUnit + vUnit + x; points[2].y = 6 * vUnit + y;
- points[3].x = 26 * hUnit + x; points[3].y = 6 * vUnit + y;
-
- XFillPolygon(g->dpy, g->helpWin, g->helpGc, points, 4, Convex,
- CoordModeOrigin);
-
- points[0].x = 30 * hUnit + x; points[0].y = 2 * vUnit + y;
- points[1].x = 30 * hUnit + vUnit + x; points[1].y = 2 * vUnit + y;
- points[2].x = 30 * hUnit + vUnit + x; points[2].y = 5 * vUnit + y;
- points[3].x = 30 * hUnit + x; points[3].y = 5 * vUnit + y;
-
- XFillPolygon(g->dpy, g->helpWin, g->helpGc, points, 4, Convex,
- CoordModeOrigin);
- }
-
-
-
- static void DisplayMenu(g)
- Ginfo *g;
- /******************************************************************************
- Display the help menu.
- ******************************************************************************/
- {
- int x = 5, y = 5;
-
- XSetFont(g->dpy, g->helpGc, g->font->fid );
-
- XSetWindowBackground(g->dpy, g->helpWin, g->black);
- XSetForeground(g->dpy, g->helpGc, g->white);
- XSetBackground(g->dpy, g->helpGc, g->black);
-
- XSetStipple(g->dpy, g->helpGc, g->stipple[NUMSTIPPLES / 3]);
- XSetFillStyle(g->dpy, g->helpGc, FillOpaqueStippled);
-
- DrawLogo(g, (XTextWidth(g->font, LONGESTSTRING, strlen(LONGESTSTRING)) /
- strlen(LONGESTSTRING)) / 2, FONTHEIGHT(g->font) / 3);
-
- XSetFillStyle(g->dpy, g->helpGc, FillSolid);
-
- DrawLogo(g, 0, 0);
-
- HelpPrint(g,x,y,"");
- HelpPrint(g,x,y,"");
- HelpPrint(g,x,y,"");
- HelpPrint(g,x,y,"");
- HelpPrint(g,x,y,"");
- HelpPrint(g,x,y,"");
- HelpPrint(g,x,y,"");
- HelpPrint(g,x,y," VERSION 2.2");
- HelpPrint(g,x,y,"");
- HelpPrint(g,x,y," CONTROLS SUMMARY");
- HelpPrint(g,x,y,"");
- HelpPrint(g,x,y," QUIT q Q");
- HelpPrint(g,x,y," WIREFRAME MODE w W");
- HelpPrint(g,x,y," HIDDEN LINE MODE e E");
- HelpPrint(g,x,y," HIDDEN SURFACE MODE r R");
- HelpPrint(g,x,y," MOVE OBJECT DOWN u U");
- HelpPrint(g,x,y," MOVE OBJECT UP i I");
- HelpPrint(g,x,y," TOGGLE CONTROLS STYLE o O");
- HelpPrint(g,x,y," TOGGLE STEREO DISPLAY s S");
- HelpPrint(g,x,y," TOGGLE BLUE STEREO VIEW d D");
- HelpPrint(g,x,y," TOGGLE DOUBLE BUFFER f F");
- HelpPrint(g,x,y," MOVE OBJECT RIGHT h H");
- HelpPrint(g,x,y," MOVE OBJECT BACKWARD j J");
- HelpPrint(g,x,y," MOVE OBJECT FOREWARD k K");
- HelpPrint(g,x,y," MOVE OBJECT LEFT l L");
- HelpPrint(g,x,y," TOGGLE HELP MENU m M");
- HelpPrint(g,x,y," ROTATE ABOUT X x X a A");
- HelpPrint(g,x,y," ROTATE ABOUT Y y Y b B");
- HelpPrint(g,x,y," ROTATE ABOUT Z z Z c C");
- HelpPrint(g,x,y," AUTOROTATE ABOUT X 1 2 3");
- HelpPrint(g,x,y," AUTOROTATE ABOUT Y 4 5 6");
- HelpPrint(g,x,y," AUTOROTATE ABOUT Z 7 8 9");
- HelpPrint(g,x,y," ADJUST FOCUS [ ] { }");
- HelpPrint(g,x,y,"");
- HelpPrint(g,x,y," POINTER MOVEMENT WITH LEFT BUTTON :");
- HelpPrint(g,x,y,"");
- HelpPrint(g,x,y," ROTATE OBJECT ABOUT X Vertical");
- HelpPrint(g,x,y," ROTATE OBJECT ABOUT Z Horizontal");
- }
-
-
-
- static void ResetPurpleRectangle(XL, YL, XH, YH, g)
- int XL, YL, XH, YH;
- Ginfo *g;
- /******************************************************************************
- Reset the vertices of the purple rectangle.
- ******************************************************************************/
- {
- g->redSegments[3].x1 = (XL + MARGIN);
- g->blueSegments[3].x1 = (XL + MARGIN);
- g->redSegments[3].y1 = (YL + MARGIN);
- g->blueSegments[3].y1 = (YL + MARGIN);
- g->redSegments[3].x2 = (XH - MARGIN);
- g->blueSegments[3].x2 = (XH - MARGIN);
- g->redSegments[3].y2 = (YL + MARGIN);
- g->blueSegments[3].y2 = (YL + MARGIN);
- g->redSegments[2].x1 = (XH - MARGIN);
- g->blueSegments[2].x1 = (XH - MARGIN);
- g->redSegments[2].y1 = (YH - MARGIN);
- g->blueSegments[2].y1 = (YH - MARGIN);
- g->redSegments[2].x2 = (XL + MARGIN);
- g->blueSegments[2].x2 = (XL + MARGIN);
- g->redSegments[2].y2 = (YH - MARGIN);
- g->blueSegments[2].y2 = (YH - MARGIN);
- g->redSegments[1].x1 = (XH - MARGIN);
- g->blueSegments[1].x1 = (XH - MARGIN);
- g->redSegments[1].y1 = (YL + MARGIN);
- g->blueSegments[1].y1 = (YL + MARGIN);
- g->redSegments[1].x2 = (XH - MARGIN);
- g->blueSegments[1].x2 = (XH - MARGIN);
- g->redSegments[1].y2 = (YH - MARGIN);
- g->blueSegments[1].y2 = (YH - MARGIN);
- g->redSegments[0].x1 = (XL + MARGIN);
- g->blueSegments[0].x1 = (XL + MARGIN);
- g->redSegments[0].y1 = (YL + MARGIN);
- g->blueSegments[0].y1 = (YL + MARGIN);
- g->redSegments[0].x2 = (XL + MARGIN);
- g->blueSegments[0].x2 = (XL + MARGIN);
- g->redSegments[0].y2 = (YH - MARGIN);
- g->blueSegments[0].y2 = (YH - MARGIN);
- }
-
-
-
- static void OneBitSetColors(g)
- Ginfo *g;
- /******************************************************************************
- Set up color information/stipples for a one bit display.
- ******************************************************************************/
- {
- int index;
- Color *colors;
- int numColors;
-
- colors = g->colors;
- numColors = g->numColors;
-
- /* Set the colors (may not be used) */
-
- for(index = 0; index < numColors; index++){
- colors[index].value = 1;
-
- /* Set the stipples */
-
- colors[index].stipple =(int)((double)NUMSTIPPLES *
- ((double)sqrt((double)(
- (double)colors[index].red * (double)colors[index].red +
- (double)colors[index].green * (double)colors[index].green +
- (double)colors[index].blue * (double)colors[index].blue))
- / MAXCOLORDIST));
- }
- }
-
-
-
- static void EightBitSetColors(g)
- Ginfo *g;
- /******************************************************************************
- Set up color information/stipples for a eight bit display.
- ******************************************************************************/
- {
- Color *colors;
- int numColors;
- int index, index2, colorIndex, redIndex, blueIndex, greenIndex;
- XColor c;
-
- colors = g->colors;
- numColors = g->numColors;
-
- /* Put "black" into the place reserved for it in the end */
-
- colors[numColors].red = 0;
- colors[numColors].green = 0;
- colors[numColors].blue = 0;
-
- /* Put "red" into the place reserved for it in the end */
-
- colors[numColors + 1].red = 255;
- colors[numColors + 1].green = 0;
- colors[numColors + 1].blue = 0;
-
- /* Put "blue" into the place reserved for it in the end */
-
- colors[numColors + 2].red = 0;
- colors[numColors + 2].green = 0;
- colors[numColors + 2].blue = 255;
-
- /* Put "purple" into the place reserved for it in the end */
-
- colors[numColors + 3].red = 255;
- colors[numColors + 3].green = 0;
- colors[numColors + 3].blue = 255;
-
- /* Blank out the colormap */
-
- for(index = 0; index < 256; index++){
- c.red = 0;
- c.green = 0;
- c.blue = 0;
- c.flags = DoRed | DoGreen | DoBlue;
- c.pixel = 255;
- g->cmapColors[0][index] = c;
- g->cmapColors[1][index] = c;
- g->cmapColors[2][index] = c;
- }
-
- if(numColors <= BUFFER_CMAP){
-
- colorIndex= numColors + 3;
- index = 15;
-
- /* Set stipple, and colormap double buffer colors */
-
- while((index > 0) && (colorIndex >= 0)){
- c.red = colors[colorIndex].red << 8;
- c.green = colors[colorIndex].green << 8;
- c.blue = colors[colorIndex].blue << 8;
- c.flags = DoRed | DoGreen | DoBlue;
-
- colors[colorIndex].value = index * 16 + index;
-
- colors[colorIndex].stipple =(int)((double)NUMSTIPPLES *
- ((double)sqrt((double)(
- (double)colors[colorIndex].red * (double)colors[colorIndex].red +
- (double)colors[colorIndex].green * (double)colors[colorIndex].green +
- (double)colors[colorIndex].blue * (double)colors[colorIndex].blue))
- / MAXCOLORDIST));
-
- for(index2 = 1; index2 < 16; index2++){
- c.pixel = index2 * 16 + index;
- g->cmapColors[0][index2 * 16 + index] = c;
-
- c.pixel = index * 16 + index2;
- g->cmapColors[1][index * 16 + index2] = c;
- }
-
- index--;
- colorIndex--;
- }
- }else{
-
- /* Set permanent black, red, blue, purple for cmap double buffer */
-
- for(index = 0; index < 4; index++){
- c.red = colors[numColors + index].red << 8;
- c.green = colors[numColors + index].green << 8;
- c.blue = colors[numColors + index].blue << 8;
- c.flags = DoRed | DoGreen | DoBlue;
- c.pixel = 12 + index;
- g->cmapColors[0][12 + index] = c;
- g->cmapColors[1][12 + index] = c;
- colors[numColors + index].value = c.pixel;
- }
-
- if(numColors <= MAX_COLORS){
- colorIndex = 0;
- index = 9;
- index2 = 0;
-
- /* Fill in the rest of the colors */
-
- while(colorIndex < numColors){
- if((index < 12) || (index > 15)){
- c.red = colors[colorIndex].red << 8;
- c.green = colors[colorIndex].green << 8;
- c.blue = colors[colorIndex].blue << 8;
- c.flags = DoRed | DoGreen | DoBlue;
- c.pixel = index;
- g->cmapColors[0][index] = c;
- g->cmapColors[1][index] = c;
- colors[colorIndex].value = index;
-
- colors[colorIndex].stipple =(int)((double)NUMSTIPPLES *
- ((double)sqrt((double)(
- (double)colors[colorIndex].red *
- (double)colors[colorIndex].red +
- (double)colors[colorIndex].green *
- (double)colors[colorIndex].green +
- (double)colors[colorIndex].blue *
- (double)colors[colorIndex].blue))
- / MAXCOLORDIST));
-
- colorIndex++;
- }
- index++;
- }
- }else{
- index = 17;
- index2 = 0;
- redIndex = 0;
- greenIndex = 0;
- blueIndex = 0;
-
- /* Otherwise use a default lot */
-
- while(blueIndex < MAXVALUE){
- c.red = (redIndex * VALUESCALE) << 8;
- c.green = (greenIndex * VALUESCALE) << 8;
- c.blue = (blueIndex * VALUESCALE) << 8;
- c.flags = DoRed | DoGreen | DoBlue;
- c.pixel = index;
- g->cmapColors[0][index] = c;
- g->cmapColors[1][index] = c;
-
- redIndex++;
-
- if(redIndex >= MAXVALUE){
- redIndex = 0;
- greenIndex++;
- }
-
- if(greenIndex >= MAXVALUE){
- greenIndex = 0;
- blueIndex++;
- }
- index++;
- }
-
- for(index = 0; index < numColors; index++){
- colors[index].value = colors[index].red * 36 +
- colors[index].green * 6 + colors[index].blue + 17;
-
- colors[colorIndex].stipple =(int)((double)NUMSTIPPLES *
- ((double)sqrt((double)(
- (double)colors[colorIndex].red *
- (double)colors[colorIndex].red +
- (double)colors[colorIndex].green *
- (double)colors[colorIndex].green +
- (double)colors[colorIndex].blue *
- (double)colors[colorIndex].blue))
- / MAXCOLORDIST));
-
- }
- }
- }
-
- /* Set the colors for the special fast colormap double buffer */
-
- index = 0;
- for(redIndex = 0; redIndex < 4; redIndex++){
- for(blueIndex = 0; blueIndex < 4; blueIndex++){
- if(redIndex != blueIndex){
- g->wireframeColors[0][index] =
- g->cmapColors[0][(redIndex + 12) * 16 + (blueIndex + 12)];
- g->wireframeColors[1][index] =
- g->cmapColors[1][(redIndex + 12) * 16 + (blueIndex + 12)];
- index++;
- }
- }
- }
-
- /* Just in case set the rest of the colors */
-
- for(index = 13; index < 256; index++){
- g->wireframeColors[0][index] = g->wireframeColors[0][3];
- g->wireframeColors[1][index] = g->wireframeColors[1][3];
- }
-
- /* Set the colors for the pix stereo mode */
-
- for(redIndex = 0; redIndex < 15; redIndex++){
- for(blueIndex = 0; blueIndex < 15; blueIndex++){
- c.red = (redIndex * 17) << 8;
- c.green = 0;
- c.blue = (blueIndex * 17) << 8;
- c.flags = DoRed | DoGreen | DoBlue;
- c.pixel = (redIndex + 1) * 16 + (blueIndex + 1);
- g->cmapColors[2][c.pixel] = c;
- }
- }
-
- /* Set stereoColor to nearest color */
-
- for(index = 0; index < numColors; index++){
- colorIndex = (int)((double)15 *
- ((double)sqrt((double)((double)colors[index].red *
- (double)colors[index].red + (double)colors[index].green *
- (double)colors[index].green + (double)colors[index].blue *
- (double)colors[index].blue)) / MAXCOLORDIST));
-
- colors[index].stereoColor = (colorIndex + 1) * 16 + (colorIndex + 1);
- }
-
- /* Set various important color values */
-
- g->stereoBlack = (0 + 1) * 16 + (0 + 1);
- g->redMask = BUFFER0;
- g->blueMask = BUFFER1;
- g->Black = colors[numColors].value;
- g->Red = colors[numColors + 1].value;
- g->Blue = colors[numColors + 2].value;
- g->Purple = colors[numColors + 3].value;
- }
-
-
-
- static void TwentyFourBitSetColors(g)
- Ginfo *g;
- /******************************************************************************
- Set up color information/stipples for a twenty-four bit display.
- ******************************************************************************/
- {
- int index, colorValue;
- Color *colors;
- int numColors;
-
- colors = g->colors;
- numColors = g->numColors;
-
- for(index = 0; index < numColors; index++){
-
- /* In 24 bit every color is what it is */
-
- colors[index].value =
- colors[index].red << 16 |
- colors[index].green << 8 |
- colors[index].blue;
-
- /* Set stipple */
-
- colors[index].stipple =(int)((double)NUMSTIPPLES *
- ((double)sqrt((double)(
- (double)colors[index].red * (double)colors[index].red +
- (double)colors[index].green * (double)colors[index].green +
- (double)colors[index].blue * (double)colors[index].blue))
- / MAXCOLORDIST));
-
- /* Set stereo color */
-
- colorValue= (int)((double)255 *
- ((double)sqrt((double)((double)colors[index].red *
- (double)colors[index].red + (double)colors[index].green *
- (double)colors[index].green + (double)colors[index].blue *
- (double)colors[index].blue)) / MAXCOLORDIST));
-
- colors[index].stereoColor = colorValue << 16 | colorValue;
- }
-
- /* Set various important color values */
-
- g->stereoBlack = 0;
- g->redMask = 255 << 16;
- g->blueMask = 255;
- g->Black = 0;
- g->Red = 255 << 16;
- g->Blue = 255;
- g->Purple = (255 << 16) | 255;
- }
-
-
-
- static void InitDisplay(o, g)
- Oinfo *o;
- Ginfo *g;
- /******************************************************************************
- Set up an X window and our colormap. We rely on X's own error handling and
- reporting for most bad X calls because X buffers requests.
- ******************************************************************************/
- {
- static int stipples[NUMSTIPPLES][NUMSTIPPLES * 2 + 1] = {
- {0},
- {1, 1, 1},
- {2, 0, 2, 2, 1},
- {3, 1, 0, 1, 2, 3, 1},
- {4, 0, 1, 0, 3, 2, 1, 2, 3},
- {5, 0, 0, 0, 2, 2, 0, 2, 3, 3, 2},
- {6, 0, 2, 1, 1, 1, 3, 2, 0, 3, 1, 3, 3},
- {7, 0, 1, 0, 3, 1, 0, 1, 1, 2, 2, 3, 1, 3, 3},
- {8, 0, 1, 0, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 0, 3, 2},
- {9, 0, 0, 0, 2, 1, 2, 1, 3, 2, 0, 2, 1, 2, 3, 3, 1, 3, 2},
- {10,0, 0, 0, 1, 0, 3, 1, 0, 1, 2, 2, 1, 2, 2, 2, 3, 3, 0, 3, 2},
- {11,0, 1, 0, 3, 1, 0, 1, 1, 1, 2, 1, 3, 2, 1, 2, 2, 3, 0, 3, 2, 3, 3},
- {12,0, 0, 0, 2, 1, 0, 1, 1, 1, 2, 1, 3, 2, 1, 2, 3, 3, 0, 3, 1, 3, 2, 3, 3},
- {13,0, 0, 0, 2, 0, 3, 1, 0, 1, 1, 1, 2, 2, 0, 2, 2, 2, 3, 3, 0, 3, 1, 3, 2,
- 3, 3},
- {14,0, 0, 0, 1, 0, 2, 0, 3, 1, 0, 1, 1, 1, 3, 2, 1, 2, 2, 2, 3, 3, 0, 3, 1,
- 3, 2, 3, 3},
- {15,0, 0, 0, 1, 0, 2, 0, 3, 1, 0, 1, 2, 1, 3, 2, 0, 2, 1, 2, 2, 2, 3, 3, 0,
- 3, 1, 3, 2, 3, 3},
- {16,0, 0, 0, 1, 0, 2, 0, 3, 1, 0, 1, 1, 1, 2, 1, 3, 2, 0, 2, 1, 2, 2, 2, 3,
- 3, 0, 3, 1, 3, 2, 3, 3}
- };
-
- char bits[(STIPPLESIZE * STIPPLESIZE) / BITSPERBYTE];
-
- GC temp_gc;
- XColor oldColormap[MAXCOLORS];
- XWindowAttributes attributes;
- XSetWindowAttributes attribs;
- XWMHints wmhint;
- int index, index2, screen;
- XVisualInfo vInfo;
- XSizeHints sizehint;
- int x, y, NUMCOLORS;
- unsigned int width, height, numSegments;
-
- numSegments = o->numSegs;
-
- if((g->redColors = (long *)calloc(1, (numSegments + 4) * (sizeof(long))))
- == NULL){
- (void)fprintf(stderr, "Unable to allocate memory for redColors\n"); exit(1);}
-
- if((g->redSegments = (XSegment *)calloc(1, (numSegments + 4) *
- (sizeof(XSegment)))) == NULL){
- (void)fprintf(stderr, "Unable to allocate memory for redSegments\n"); exit(1);}
-
- if((g->blueSegments = (XSegment *)calloc(1, (numSegments + 4) *
- sizeof(XSegment))) == (XSegment *)NULL){
- (void)fprintf(stderr, "Unable to allocate memory for blueSegments\n"); exit(1);}
-
- /* Can we connect with the server? */
-
- if((g->dpy = XOpenDisplay(g->DisplayName)) == NULL){
- fprintf(stderr, "Cannot connect to server\n");
- exit(1);
- }
-
- screen = DefaultScreen(g->dpy);
- g->black = (long)BlackPixel(g->dpy, screen);
- g->white = (long)WhitePixel(g->dpy, screen);
-
- /* Initialize various flags and default values */
-
- g->requestSize = XMaxRequestSize(g->dpy) / REQUESTFACTOR;
- g->dpyX = DisplayWidth(g->dpy, screen);
- g->dpyY = DisplayHeight(g->dpy, screen);
- g->winX = g->dpyX / 2;
- g->winY = g->dpyY / 2 /* - 25 */ ;
- g->mono = g->ColorSelect = g->oldPointerX = g->oldPointerY = 0;
- g->Block = 1;
- g->Relative = 0;
-
- /* Initialize the fonts */
-
- if((g->font = XLoadQueryFont(g->dpy, FONT)) == NULL){
- fprintf(stderr, "Unable to load font: %s ... trying fixed\n", FONT);
-
- if((g->font = XLoadQueryFont(g->dpy, FIXED)) == NULL){
- fprintf(stderr, "Unable to load font: %s\n", FIXED);
- exit(1);
- }
- }
-
- if((g->titleFont = XLoadQueryFont(g->dpy, TITLEFONT)) == NULL){
- fprintf(stderr, "Unable to load font: %s ... trying fixed\n", TITLEFONT);
-
- if((g->titleFont = XLoadQueryFont(g->dpy, FIXED)) == NULL){
- fprintf(stderr, "Unable to load font: %s\n", FIXED);
- exit(1);
- }
- }
-
- if((g->boldFont = XLoadQueryFont(g->dpy, BOLDFONT)) == NULL){
- fprintf(stderr, "Unable to load font: %s ... trying fixed\n", BOLDFONT);
-
- if((g->boldFont = XLoadQueryFont(g->dpy, FIXED)) == NULL){
- fprintf(stderr, "Unable to load font: %s\n", FIXED);
- exit(1);
- }
- }
-
- /* Which visual do we get? */
-
- g->depth = ONE;
-
- /* An 8 bit PseudoColor ? */
-
- if(XMatchVisualInfo(g->dpy, screen, 8, PseudoColor, &vInfo)){
- g->depth = EIGHT;
- }else{
-
- /* A 24 bit TrueColor ? */
-
- if(XMatchVisualInfo(g->dpy, screen, 24, TrueColor, &vInfo)){
- g->depth = TWENTYFOUR;
- }
- }
-
- g->pix = XCreatePixmap(g->dpy, RootWindow(g->dpy,screen), g->winX,
- g->winY, g->depth);
-
- /* Everything else we treat as monochrome whether or not
- something better may be supported */
-
- /* Make a vanilla window */
-
- g->helpWinX =XTextWidth(g->font, LONGESTSTRING, strlen(LONGESTSTRING));
- g->helpWinY = FONTHEIGHT(g->font) * HELPLINES;
-
- g->helpWin = XCreateSimpleWindow(g->dpy, RootWindow(g->dpy, screen), 0, 0,
- g->helpWinX, g->helpWinY, 0, 0, 0);
-
- g->win = XCreateSimpleWindow(g->dpy, RootWindow(g->dpy,screen), 0, 0,
- g->winX, g->winY, 0, 0, 0);
-
- /* Any user geometry? */
-
- if(g->Geometry){
-
- x = 0;
- y = 0;
- width = g->winX;
- height = g->winY;
- sizehint.flags = USPosition | USSize;
-
- XParseGeometry(g->Geometry, &x, &y, &width, &height);
-
- sizehint.x = x;
- sizehint.y = y;
- sizehint.width = width;
- sizehint.height = height;
- g->winX = width;
- g->winY = height;
-
- XResizeWindow(g->dpy, g->win, width, height);
- XSetNormalHints(g->dpy, g->win, &sizehint);
- }
-
- /* Set horizontal and vertical ranges */
-
- g->winH = (int)(g->winX / 2.0);
- g->winV = (int)(g->winY / 2.0);
-
- /* Make our graphics context */
-
- g->gc = XCreateGC(g->dpy, g->win, 0x0, NULL);
- g->helpGc = XCreateGC(g->dpy, g->helpWin, 0x0, NULL);
-
- /* Create Tiles for monochrome display */
-
- for(index = 0; index < NUMSTIPPLES; index++){
- g->stipple[index]= XCreateBitmapFromData(g->dpy, g->win, bits,
- STIPPLESIZE, STIPPLESIZE);
- temp_gc = XCreateGC(g->dpy, g->stipple[index], 0x0, NULL);
- XSetForeground(g->dpy, temp_gc, 0);
- XFillRectangle(g->dpy, g->stipple[index], temp_gc, 0, 0, STIPPLESIZE,
- STIPPLESIZE);
- XSetForeground(g->dpy, temp_gc, 1);
- for(index2 = 0; index2 < stipples[index][0]; index2++){
- XDrawPoint(g->dpy, g->stipple[index], temp_gc,
- stipples[index][index2 * 2 + 1], stipples[index][index2 * 2 + 2]);
- }
- XFreeGC(g->dpy, temp_gc);
- }
-
- /* We want to have the input focus if we can */
-
- XSetInputFocus(g->dpy, PointerRoot, RevertToNone, CurrentTime);
-
- /*
- Thanks go to Otmar Lendl for the following bit of code that
- permits the program to work properly with losing window managers
- that don't handle input focus correctly.
- */
-
- wmhint.input = True;
- wmhint.flags = InputHint;
- XSetWMHints(g->dpy,g->win,&wmhint);
-
- /* Please do not do backing store on the contents of our window */
-
- attribs.backing_store = NotUseful;
- XChangeWindowAttributes(g->dpy, g->win, CWBackingStore, &attribs);
-
- /* We only want certain kinds of events */
-
- XSelectInput(g->dpy, g->win, ButtonPressMask | ButtonReleaseMask |
- KeyPressMask | Button1MotionMask | Button2MotionMask |
- StructureNotifyMask | ExposureMask | ColormapChangeMask);
-
- XSelectInput(g->dpy, g->helpWin, ButtonPressMask | ButtonReleaseMask |
- KeyPressMask | Button1MotionMask | Button2MotionMask |
- StructureNotifyMask | ExposureMask | ColormapChangeMask);
-
- /* Do not generate expose events */
-
- XSetGraphicsExposures(g->dpy, g->gc, 0);
-
- /* Name our windows */
-
- XStoreName(g->dpy, g->win, "X3D");
- XStoreName(g->dpy, g->helpWin, "X3D Help");
-
- /* Some window managers are not friendly, explicitly set the background color */
-
- XSetWindowBackground(g->dpy, g->win, g->black);
-
- if(g->depth == ONE){
- OneBitSetColors(g);
- }
-
- if(g->depth == TWENTYFOUR){
- TwentyFourBitSetColors(g);
- }
-
- if(g->depth == EIGHT){
-
- NUMCOLORS = 256;
-
- /* Make our colormap */
-
- g->colormap = XCreateColormap(g->dpy, g->win, DefaultVisual(g->dpy,
- screen), AllocAll);
-
- /* Get the current colormap */
-
- XGetWindowAttributes(g->dpy, RootWindow(g->dpy,screen), &attributes);
-
- /* Since we only use 16 colors, set all our other entries to the old values.
- Hopefully some other windows might display in true colors */
-
- for(index = 0; index < NUMCOLORS; index++)
- oldColormap[index].pixel = index;
-
- XQueryColors(g->dpy, attributes.colormap, oldColormap, NUMCOLORS);
- XStoreColors(g->dpy, g->colormap, oldColormap, NUMCOLORS);
-
- /* Set up the colormap */
-
- EightBitSetColors(g);
-
- /* Set our special 12 colors to something */
-
- XStoreColors(g->dpy, g->colormap, g->cmapColors[0], 256);
- XSetWindowColormap(g->dpy, g->helpWin, g->colormap);
- XSetWindowColormap(g->dpy, g->win, g->colormap);
- }
-
- /* Make the purple rectangle */
-
- ResetPurpleRectangle(0, 0, g->winX, g->winY, g);
-
- /*
- Make the windows appear.
- */
- XMapWindow(g->dpy, g->win);
- DisplayMenu(g);
- }
-
-
-
- static int CheckEvent(display, event, arg)
- Display *display;
- XEvent *event;
- char *arg;
- /******************************************************************************
- Check an event to see if it is one we are interested in.
- This is used by X to wake up our program once some interesting event
- happens. Returns: 1 if we are interested, 0 if we are not.
- ******************************************************************************/
- {
- if(event == NULL){
- fprintf(stderr, "WARNING: Null event in CheckEvent()!!\n");
- }
-
- if((event->type == MotionNotify) || (event->type == KeyPress) ||
- (event->type == ConfigureNotify) || (event->type == Expose) ||
- (event->type == ColormapNotify))
- return 1;
-
- return 0;
- }
-
-
-
- static void GetInput(pointerX, pointerY, command, same, g)
- int *pointerX, *pointerY;
- char *command;
- int *same;
- Ginfo *g;
- /******************************************************************************
- Get an interesting event and update the user input information.
-
- The routine will eventually block waiting for an event if block is 1
- and the no events of interest have shown up.
- ******************************************************************************/
- {
- XEvent event;
- XSizeHints sizehint;
- int numEvents;
- char string[TMPSTRLEN];
-
- /* set command to a meaningless value (hopefully) */
-
- *command = '\0';
-
- do{
- string[0] = '\0';
-
- /* How many events? */
-
- numEvents = XEventsQueued(g->dpy, QueuedAfterReading);
-
- /* Block to obtain an event yet? */
-
- if((numEvents == 0) && (g->Block)){
-
- /* If the user falls asleep stop using CPU cycles */
-
- XIfEvent(g->dpy, &event, CheckEvent, NULL);
- numEvents = 1;
- }else{
-
- /* If we have at least one event , fetch the first event off the queue*/
-
- if(numEvents)
- XNextEvent(g->dpy,&event);
- }
-
- }while((numEvents == 0) && (g->Block));
-
- /* Process the events we have obtained (if any) */
-
- while(numEvents){
-
- switch(event.type){
-
- case MotionNotify :
- if(numEvents == 1){
- *pointerX = (int)event.xmotion.x;
- *pointerY = (int)event.xmotion.y;
- }
- break;
-
- case KeyPress :
- if(numEvents == 1){
- XLookupString(&event.xkey,string,TMPSTRLEN,NULL,NULL);
- *command = string[0];
- }
- break;
-
- case ConfigureNotify :
-
- if(event.xconfigure.window == g->win){
-
- g->winX = event.xconfigure.width;
- g->winY = event.xconfigure.height;
- g->winH = (int)(g->winX / 2.0);
- g->winV = (int)(g->winY / 2.0);
- ResetPurpleRectangle(0, 0, g->winX, g->winY, g);
- sizehint.flags = USSize | USPosition;
- sizehint.width = g->winX;
- sizehint.height = g->winY;
- XSetNormalHints(g->dpy, g->win, &sizehint);
-
- /* Resize our pix etc... */
-
- XFreePixmap(g->dpy, g->pix);
-
- g->pix = XCreatePixmap(g->dpy, g->win, g->winX, g->winY,
- g->depth);
-
- }
- if(event.xconfigure.window == g->helpWin){
- DisplayMenu(g);
- }
- g->modeChanged = 1;
- *same = 0;
- break;
-
- case Expose :
- if(event.xexpose.window == g->helpWin){
- DisplayMenu(g);
- }
- *same = 0;
- break;
-
- case MapNotify :
-
- if(event.xmap.window == g->helpWin){
-
- sizehint.flags = USPosition | USSize;
- XSetNormalHints(g->dpy, g->helpWin, &sizehint);
-
- DisplayMenu(g);
- }
- g->modeChanged = 1;
- *same = 0;
- break;
-
- case ColormapNotify :
-
- if(event.xcolormap.colormap == g->colormap){
-
- if(event.xcolormap.state == ColormapUninstalled){
- g->mono = 1;
- }else{
- g->mono = 0;
- }
-
- g->modeChanged = 1;
- *same = 0;
- }
- break;
-
- default :
- break;
- }
-
- numEvents--;
-
- if(numEvents)
- XNextEvent(g->dpy,&event);
- }
- }
-
-
-
- static void UpdatePosition(o, g)
- Oinfo *o;
- Ginfo *g;
- /******************************************************************************
- Update the scene position information using user input.
-
- The routine will eventually block waiting for an event if block is True
- and the no events of interest show up due to the call to GetInput()
- ******************************************************************************/
- {
- int same, pointerX, pointerY, dx, dy;
- char command;
- double X, Y, Z;
-
- X = Y = Z = 0.0;
-
- same = 1;
-
- pointerX = g->oldPointerX;
- pointerY = g->oldPointerY;
-
- while(same) {
-
- /* dx, dy, dz are the amount to step about each axis every frame
- We want the scene to continue to rotate even if the user does
- not give any new input */
-
- /* Do not forget to put your automatic update variables into this if
- statement. Be careful somehow you can get MANY bugs with these! */
-
- if((o->dX) || (o->dY) || (o->dZ)){
- same = 0;
- g->Block = 0;
- }else
- g->Block = 1;
-
- /* Get the input */
-
- GetInput(&pointerX, &pointerY, &command, &same, g);
-
- /* Fill in code for your favorite keyboard and pointer controls */
-
- /* My default controls */
-
- /* Note: I do not move the origin which the scene is rotated about around.
- You may want to do oX += ???; oY += ???; oZ += ??? */
-
- switch(command){
- case ' ' : break;
- case 'm' : same = 0; g->helpMenu = !g->helpMenu;
- if(g->helpMenu == False){
- XUnmapWindow(g->dpy, g->helpWin);
- }else{
- XMapWindow(g->dpy, g->helpWin);
- }
- break;
- case 'M' : same = 0; g->helpMenu = !g->helpMenu;
- if(g->helpMenu == False){
- XUnmapWindow(g->dpy, g->helpWin);
- }else{
- XMapWindow(g->dpy, g->helpWin);
- }
- break;
- case 's' : same = 0; g->stereo = !g->stereo; g->modeChanged = 1;
- break;
- case 'S' : same = 0; g->stereo = !g->stereo; g->modeChanged = 1;
- break;
- case 'd' : same = 0; g->stereoBlue = !g->stereoBlue;
- g->modeChanged = 1;break;
- case 'D' : same = 0; g->stereoBlue = !g->stereoBlue;
- g->modeChanged = 1;break;
- case 'f' : same = 0; g->buffer = !g->buffer; g->modeChanged = 1;break;
- case 'F' : same = 0; g->buffer = !g->buffer; g->modeChanged = 1;break;
- case 'o' : same = 0; g->Relative = !g->Relative; break;
- case 'O' : same = 0; g->Relative = !g->Relative; break;
- case 'w' : same = 0; g->renderMode = WIREFRAME; g->modeChanged = 1;
- break;
- case 'W' : same = 0; g->renderMode = WIREFRAME; g->modeChanged = 1;
- break;
- case 'e' : same = 0; g->renderMode = HIDDENLINE; g->modeChanged = 1;
- break;
- case 'E' : same = 0; g->renderMode = HIDDENLINE; g->modeChanged = 1;
- break;
- case 'r' : same = 0; g->renderMode = SOLID; g->modeChanged = 1;break;
- case 'R' : same = 0; g->renderMode = SOLID; g->modeChanged = 1;break;
- case 'l' : same = 0; o->tX -= 100.0; break;
- case 'j' : same = 0; o->tY -= 100.0; break;
- case 'k' : same = 0; o->tY += 100.0; break;
- case 'h' : same = 0; o->tX += 100.0; break;
- case 'i' : same = 0; o->tZ += 100.0; break;
- case 'u' : same = 0; o->tZ -= 100.0; break;
- case 'L' : same = 0; o->tX -= 500.0; break;
- case 'J' : same = 0; o->tY -= 500.0; break;
- case 'K' : same = 0; o->tY += 500.0; break;
- case 'H' : same = 0; o->tX += 500.0; break;
- case 'I' : same = 0; o->tZ += 500.0; break;
- case 'U' : same = 0; o->tZ -= 500.0; break;
- case '1' : same = 0; o->dX += 0.02; break;
- case '2' : same = 0; o->dX = 0.0 ; break;
- case '3' : same = 0; o->dX -= 0.02; break;
- case '4' : same = 0; o->dY -= 0.02; break;
- case '5' : same = 0; o->dY = 0.0 ; break;
- case '6' : same = 0; o->dY += 0.02; break;
- case '7' : same = 0; o->dZ += 0.02; break;
- case '8' : same = 0; o->dZ = 0.0 ; break;
- case '9' : same = 0; o->dZ -= 0.02; break;
- case 'x' : same = 0; X -= 0.03; break;
- case 'X' : same = 0; X += 0.03; break;
- case 'y' : same = 0; Y += 0.03; break;
- case 'Y' : same = 0; Y -= 0.03; break;
- case 'z' : same = 0; Z -= 0.03; break;
- case 'Z' : same = 0; Z += 0.03; break;
- case 'a' : same = 0; X -= 0.05; break;
- case 'A' : same = 0; X += 0.05; break;
- case 'b' : same = 0; Y += 0.05; break;
- case 'B' : same = 0; Y -= 0.05; break;
- case 'c' : same = 0; Z -= 0.05; break;
- case 'C' : same = 0; Z += 0.05; break;
- case '[' : same = 0;
- o->focus = o->focus += 0.1;
- if((o->focus > 1.8))
- o->focus = 1.8;
- break;
- case ']' : same = 0;
- o->focus = o->focus -= 0.1;
- if((o->focus < -0.8))
- o->focus = -0.8;
- break;
- case '{' : same = 0; o->BViewpointX -= 4.0; break;
- case '}' : same = 0; o->BViewpointX += 4.0; break;
- case 'q' : XFreePixmap(g->dpy, g->pix); exit(0);
- case 'Q' : XFreePixmap(g->dpy, g->pix); exit(0);
-
- default : {
-
- /* My pointer movement stuff */
-
- /* Only update if the movement was reasonably small */
-
- dx = pointerX - g->oldPointerX;
- dy = pointerY - g->oldPointerY;
-
- if((dy * dy <= SMALLMOVEMENT) &&
- (dx * dx <= SMALLMOVEMENT)){
-
- /* Rotate proportionally with the amount the pointer moved */
- /* Note: I only control the X and Z axes by the pointer */
-
- X -= (dy * POINTERRATIO);
- Z -= (dx * POINTERRATIO);
- same = 0;
- }
-
- g->oldPointerY = pointerY;
- g->oldPointerX = pointerX;
- }
- }
- }
-
- /* Keep angles 0 - 6.28 */
-
- X = fmod(X + o->dX, TWOPI);
- Y = fmod(Y + o->dY, TWOPI);
- Z = fmod(Z + o->dZ, TWOPI);
-
- /* Fix up the angles */
-
- if(g->Relative){
- o->X = fmod(X + o->X, TWOPI);
- o->Y = fmod(Y + o->Y, TWOPI);
- o->Z = fmod(Z + o->Z, TWOPI);
- }else{
- CalculateAngles(&(o->X), &(o->Y), &(o->Z), X, Y, Z);
- }
- }
-
-
-
- static int clipSegment(pX, pY, qX, qY, Pclip, Qclip, H, V)
- float *pX, *pY, *qX, *qY;
- int Pclip, Qclip;
- float H,V;
- /******************************************************************************
- Calculate the portion of the projected line segment that is visible.
- ******************************************************************************/
- {
- register float PX, PY, QX, QY, dx, dy;
-
- PX = *pX; QX = *qX;
- PY = *pY; QY = *qY;
-
- dx = QX - PX;
- dy = QY - PY;
-
- /* Clip P first so it will be somewhere on the screen,
- if we cannot move P on screen the segment is not visible */
-
- /* See x3d.h for the meaning of the clipping flags */
-
- switch(Pclip){
-
- case 1 : /* 00001 */
- clipWithTop(PX, PY, dx, dy, V)
- if((PX < -H) || (PX > H))
- return 0;
- break;
-
- case 2 : /* 00010 */
- clipWithBottom(PX, PY, dx, dy, V)
- if((PX < -H) || (PX > H))
- return 0;
- break;
-
- case 4 : /* 00100 */
- clipWithLeftSide(PX, PY, dx, dy, H)
- if((PY < -V) || (PY > V))
- return 0;
- break;
-
- case 5 : /* 00101 */
- clipWithTop(PX, PY, dx, dy, V)
- if((PX < -H) || (PX > H)){
- clipWithLeftSide(PX, PY, dx, dy, H)
- if((PY < -V) || (PY > V))
- return 0;
- }
- break;
-
- case 6 : /* 00110 */
- clipWithBottom(PX, PY, dx, dy, V)
- if((PX < -H) || (PX > H)){
- clipWithLeftSide(PX, PY, dx, dy, H)
- if((PY < -V) || (PY > V))
- return 0;
- }
- break;
-
- case 8 : /* 01000 */
- clipWithRightSide(PX, PY, dx, dy, H)
- if((PY < -V) || (PY > V))
- return 0;
- break;
-
- case 9 : /* 01001 */
- clipWithTop(PX, PY, dx, dy, V)
- if((PX < -H) || (PX > H)){
- clipWithRightSide(PX, PY, dx, dy, H)
- if((PY < -V) || (PY > V))
- return 0;
- }
- break;
-
- case 10 : /* 01010 */
- clipWithBottom(PX, PY, dx, dy, V)
- if((PX < -H) || (PX > H)){
- clipWithRightSide(PX, PY, dx, dy, H)
- if((PY < -V) || (PY > V))
- return 0;
- }
- break;
-
- }
-
- /* P is now somewhere on screen, calculate where Q should be */
-
- switch(Qclip){
-
- case 1 : /* 00001 */
- clipWithTop(QX, QY, dx, dy, V)
- break;
-
- case 2 : /* 00010 */
- clipWithBottom(QX, QY, dx, dy, V)
- break;
-
- case 4 : /* 00100 */
- clipWithLeftSide(QX, QY, dx, dy, H)
- break;
-
- case 5 : /* 00101 */
- clipWithTop(QX, QY, dx, dy, V)
- if(QX < -H)
- clipWithLeftSide(QX, QY, dx, dy, H)
- break;
-
- case 6 : /* 00110 */
- clipWithBottom(QX, QY, dx, dy, V)
- if(QX < -H)
- clipWithLeftSide(QX, QY, dx, dy, H)
- break;
-
- case 8 : /* 01000 */
- clipWithRightSide(QX, QY, dx, dy, H)
- break;
-
- case 9 : /* 01001 */
- clipWithTop(QX, QY, dx, dy, V)
- if(QX > H)
- clipWithRightSide(QX, QY, dx, dy, H)
- break;
-
- case 10 : /* 01010 */
- clipWithBottom(QX, QY, dx, dy, V)
- if(QX > H)
- clipWithRightSide(QX, QY, dx, dy, H)
- break;
-
- case 21 : /* 10101 */
- clipWithTop(QX, QY, dx, dy, V)
- if(QX < -H)
- clipWithLeftSide(QX, QY, dx, dy, H)
- break;
-
- case 22 : /* 10110 */
- clipWithBottom(QX, QY, dx, dy, V)
- if(QX < -H)
- clipWithLeftSide(QX, QY, dx, dy, H)
- break;
-
- case 23 : /* 10111 */
- if(QY < PY)
- clipWithTop(QX, QY, dx, dy, V)
- else
- clipWithBottom(QX, QY, dx, dy, V)
- if(QX < -H)
- clipWithLeftSide(QX, QY, dx, dy, H)
- break;
-
- case 25 : /* 11001 */
- clipWithTop(QX, QY, dx, dy, V)
- if(QX > H)
- clipWithRightSide(QX, QY, dx, dy, H)
- break;
-
- case 26 : /* 11010 */
- clipWithBottom(QX, QY, dx, dy, V)
- if(QX > H)
- clipWithRightSide(QX, QY, dx, dy, H)
- break;
-
- case 27 : /* 11011 */
- if(QY < PY)
- clipWithTop(QX, QY, dx, dy, V)
- else
- clipWithBottom(QX, QY, dx, dy, V)
- if(QX > H)
- clipWithRightSide(QX, QY, dx, dy, H)
- break;
-
- case 29 : /* 11101 */
- if(QX < PX)
- clipWithRightSide(QX, QY, dx, dy, H)
- else
- clipWithLeftSide(QX, QY, dx, dy, H)
- if(QY > V)
- clipWithTop(QX, QY, dx, dy, V)
- break;
-
- case 30 : /* 11110 */
- if(QX < PX)
- clipWithRightSide(QX, QY, dx, dy, H)
- else
- clipWithLeftSide(QX, QY, dx, dy, H)
- if(QY < -V)
- clipWithBottom(QX, QY, dx, dy, V)
- break;
-
- case 31 : /* 11111 */
- if(QX < PX)
- clipWithRightSide(QX, QY, dx, dy, H)
- else
- clipWithLeftSide(QX, QY, dx, dy, H)
-
- if((QY < -V) || (QY > V))
- if(*qY < PY)
- clipWithTop(QX, QY, dx, dy, V)
- else
- clipWithBottom(QX, QY, dx, dy, V)
- break;
-
- }
-
- *pX = PX; *qX = QX;
- *pY = PY; *qY = QY;
- return 1;
- }
-
-
-
- static void clip(o, g)
- Oinfo *o;
- Ginfo *g;
- /******************************************************************************
- Clip a list of segments.
- ******************************************************************************/
- {
- register int PClipFlags, QClipFlags, Pclip, Qclip, Tclip;
- register float H, V;
- register short pX, pY, qX, qY;
- float PX, PY, QX, QY;
- segment *seg, *lastSeg;
- point *P, *Q, *T;
- XSegment *red, *blue;
- long *redCol;
-
- lastSeg = &(o->segs[o->numSegs]);
- seg = o->segs;
-
- H = (float)g->winH;
- V = (float)g->winV;
-
- red = &(g->redSegments[g->numberRed]);
- redCol = &(g->redColors[g->numRedColors]);
-
- if((g->mono) || ((g->stereo) && (!(g->stereoBlue))) ||
- ((g->renderMode == WIREFRAME) && (!g->stereo))){
-
- if(o->objClip){
-
- /* For every segment ... */
-
- while(seg < lastSeg){
-
- P = seg->P;
- PClipFlags = P->ClipFlags;
- Q = seg->Q;
- QClipFlags = Q->ClipFlags;
-
- /* Optimization for best case */
-
- if((PClipFlags | QClipFlags) == 0){
- *redCol = seg->color->value;
- redCol++;
- ((xsegment *)red)->P = P->R;
- ((xsegment *)red)->Q = Q->R;
- red++;
- }else{
-
- /* Red segments */
-
- /* Shuffle the bits around so we get the right configuration
- for the clipping function */
-
- Pclip = (PClipFlags & RBmask) | ((PClipFlags & RLeftRight) >> 3);
- Qclip = (QClipFlags & RBmask) | ((QClipFlags & RLeftRight) >> 3);
-
- if((Qclip | Pclip) == 0){
-
- *redCol = seg->color->value;
- redCol++;
- red->x1 = P->R.x;
- red->y1 = P->R.y;
- red->x2 = Q->R.x;
- red->y2 = Q->R.y;
- red++;
-
- }else{
-
- if((Qclip & Pclip) == 0){
-
- /* We make P be a point in front of us if there is one in front,
- (it simplifies the code) */
-
- if((Pclip > Qclip) || (Pclip & Behind)){
- T = P; P = Q; Q = T;
- Tclip = Pclip; Pclip = Qclip; Qclip = Tclip;
- }
-
- PX = P->RX - H; PY = -(P->Y - V);
- QX = Q->RX - H; QY = -(Q->Y - V);
-
- if(clipSegment(&PX, &PY, &QX, &QY, Pclip, Qclip, H, V)){
-
- *redCol = seg->color->value;
- redCol++;
- red->x1 = (short)(PX + H);
- red->y1 = (short)(V - PY);
- red->x2 = (short)(QX + H);
- red->y2 = (short)(V - QY);
- red++;
-
- }
- }
- }
- }
- seg++;
- }
- }else{
-
- /* Optimization for object completely visible */
-
- if((g->renderMode == WIREFRAME) && (g->stereo)){
- while(seg < lastSeg){
- ((xsegment *)red)->P = seg->P->R;
- ((xsegment *)red)->Q = seg->Q->R;
- red++;
- seg++;
- }
- }else{
- while(seg < lastSeg){
- *redCol = seg->color->value;
- redCol++;
- ((xsegment *)red)->P = seg->P->R;
- ((xsegment *)red)->Q = seg->Q->R;
- red++;
- seg++;
- }
- }
- }
- }else{
- blue = &(g->blueSegments[g->numberBlue]);
-
- if(o->objClip){
- while(seg < lastSeg){
-
- P = seg->P; Q = seg->Q;
- PClipFlags = P->ClipFlags;
- QClipFlags = Q->ClipFlags;
-
- /* Optimization for best case */
-
- if((PClipFlags | QClipFlags) == 0){
-
- pX = P->R.x; pY = P->R.y;
- qX = Q->R.x; qY = Q->R.y;
- red->x1 = pX;
- red->y1 = pY;
- red->x2 = qX;
- red->y2 = qY;
- red++;
- pX = P->sBX; qX = Q->sBX;
- blue->x1 = pX;
- blue->y1 = pY;
- blue->x2 = qX;
- blue->y2 = qY;
- blue++;
-
- }else{
-
- /* Red segments */
-
- /* Shuffle the bits around so we get the right configuration
- for the clipping function */
-
- Pclip = (PClipFlags & RBmask) | ((PClipFlags & RLeftRight) >> 3);
- Qclip = (QClipFlags & RBmask) | ((QClipFlags & RLeftRight) >> 3);
-
- if((Qclip | Pclip) == 0){
-
- red->x1 = P->R.x;
- red->y1 = P->R.y;
- red->x2 = Q->R.x;
- red->y2 = Q->R.y;
- red++;
-
- }else{
-
- if((Qclip & Pclip) == 0){
-
- /* We make P be a point in front of us if there is one in front,
- (it simplifies the code) */
-
- if((Pclip > Qclip) || (Pclip & Behind)){
- T = P; P = Q; Q = T;
- Tclip = Pclip; Pclip = Qclip; Qclip = Tclip;
- }
-
- PX = P->RX - H; PY = -(P->Y - V);
- QX = Q->RX - H; QY = -(Q->Y - V);
-
- if(clipSegment(&PX, &PY, &QX, &QY, Pclip, Qclip, H, V)){
-
- red->x1 = (short)(PX + H);
- red->y1 = (short)(V - PY);
- red->x2 = (short)(QX + H);
- red->y2 = (short)(V - QY);
- red++;
-
- }
-
- }
- }
-
- /* Blue segments */
-
- PClipFlags = P->ClipFlags;
- QClipFlags = Q->ClipFlags;
-
- /* Shuffle the bits around so we get the right configuration
- for the clipping function */
-
- Pclip = (PClipFlags & Rmask);
- Qclip = (QClipFlags & Rmask);
-
- if((Qclip | Pclip) == 0){
-
- blue->x1 = P->sBX;
- blue->y1 = P->R.y;
- blue->x2 = Q->sBX;
- blue->y2 = Q->R.y;
- blue++;
-
- }else{
- if((Qclip & Pclip) == 0){
-
- /* We make P be a point in front of us if there is one in front,
- (it simplifies the code) */
-
- if((Pclip > Qclip) || (Pclip & Behind)){
- T = P; P = Q; Q = T;
- Tclip = Pclip; Pclip = Qclip; Qclip = Tclip;
- }
-
- /* check the bits, clip if necessary, and add the segment to the
- appropriate buffer if visible */
-
- PX = P->BX - H; PY = -(P->Y - V);
- QX = Q->BX - H; QY = -(Q->Y - V);
-
- if(clipSegment(&PX, &PY, &QX, &QY, Pclip, Qclip, H, V)){
-
- blue->x1 = (short)(PX + H);
- blue->y1 = (short)(V - PY);
- blue->x2 = (short)(QX + H);
- blue->y2 = (short)(V - QY);
- blue++;
-
- }
- }
- }
- }
- seg++;
- }
- }else{
-
- /* Optimization for object completely visible */
-
- while(seg < lastSeg){
- P = seg->P; Q = seg->Q;
- pX = P->R.x; pY = P->R.y;
- qX = Q->R.x; qY = Q->R.y;
- red->x1 = pX;
- red->y1 = pY;
- red->x2 = qX;
- red->y2 = qY;
- red++;
- pX = P->sBX; qX = Q->sBX;
- blue->x1 = pX;
- blue->y1 = pY;
- blue->x2 = qX;
- blue->y2 = qY;
- blue++;
- seg++;
- }
-
- }
-
- g->numberBlue = blue - g->blueSegments;
- }
-
- g->numRedColors = redCol - g->redColors;
- g->numberRed = red - g->redSegments;
- }
-
-
- #ifdef USE_INTS
-
- /* The REDROTATE macro does 3 rotates, 2 translates, 1 projection */
-
- #define REDROTATE \
- r8 = p0->x + c16; \
- r5 = p0->y + c17; \
- r2 = ((r8 * c5 + r5 * c6) >> SHIFT); \
- r7 = ((r5 * c5 - r8 * c6) >> SHIFT); \
- r8 = p0->z + c18; \
- r5 = ((r7 * c3 + r8 * c4) >> SHIFT) + c12; \
- r6 = ((r8 * c3 - r7 * c4) >> SHIFT); \
- r7 = c7 + ((((r6 * c1 - r2 * c2) >> SHIFT) + c13) * c0) / r5; \
- r8 = c9 - ((((r2 * c1 + r6 * c2) >> SHIFT) + c11) * c0) / r5; \
- r5 = (c0 * 8192) / r5
-
- /* Project the blue point too */
-
- #define STEREOROTATE \
- r8 = p0->x + c16; \
- r5 = p0->y + c17; \
- r2 = ((r8 * c5 + r5 * c6) >> SHIFT); \
- r7 = ((r5 * c5 - r8 * c6) >> SHIFT); \
- r8 = p0->z + c18; \
- r5 = ((r7 * c3 + r8 * c4) >> SHIFT) + c12; \
- r6 = ((r8 * c3 - r7 * c4) >> SHIFT); \
- r7 = c7 + ((((r6 * c1 - r2 * c2) >> SHIFT) + c13) * c0) / r5; \
- r8 = c9 - ((((r2 * c1 + r6 * c2) >> SHIFT) + c11) * c0) / r5; \
- r9 = r8 - c15 - (c0 * c14) / r5; \
- r5 = (c0 * 8192) / r5
-
- #else
-
- /* The REDROTATE macro does 3 rotates, 2 translates, 1 projection */
-
- #define REDROTATE \
- r8 = p0->x + c16; \
- r5 = p0->y + c17; \
- r2 = r8 * c5 + r5 * c6; \
- r7 = r5 * c5 - r8 * c6; \
- r8 = p0->z + c18; \
- r5 = c0 / (r7 * c3 + r8 * c4 + c12); \
- r6 = r8 * c3 - r7 * c4; \
- r7 = c7 + (r6 * c1 - r2 * c2 + c13) * r5; \
- r8 = c9 - (r2 * c1 + r6 * c2 + c11) * r5
-
- #define STEREOROTATE \
- REDROTATE; \
- r9 = r8 - c15 - r5 * c14
-
- #endif
-
-
- /* Set all the red clipping flags */
-
- #define REDCLIPFLAGS \
- (r5 > 0) * ALLmask ^ (r7 < 0 | (r7 > c10) << ClipWithBottom | \
- (r8 > c8) << RClipWithRight | (r8 < 0) << RClipWithLeft)
-
- /* Set all the red and blue clipping flags */
-
- #define STEREOCLIPFLAGS \
- (r5 > 0) * ALLmask ^ (r7 < 0 | (r7 > c10) << ClipWithBottom | \
- (r8 > c8) << RClipWithRight | (r8 < 0) << RClipWithLeft | \
- (r9 > c8) << BClipWithRight | (r9 < 0) << BClipWithLeft)
-
-
-
- static void rotate(o, g)
- Oinfo *o;
- Ginfo *g;
- /******************************************************************************
- Rotate, project, and set the clipping flags for a list of points.
- ******************************************************************************/
- {
- register number r2,r5,r6,r7,r8,r9;
- register point *p0;
- register number c1,c2,c3,c4,c5,c6;
- register point *p1;
- register number c0,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16,c17,c18;
- register int objClip;
- register short RX, BX;
-
- p0 = o->bounds; p1 = &(o->bounds[NUMBOUNDS]); c0 = (number)o->viewpointY;
- c1 = (number)(cos(o->Y) * TRIG_ADJ); c2 = (number)(sin(o->Y) * TRIG_ADJ);
- c3 = (number)(cos(o->X) * TRIG_ADJ); c4 = (number)(sin(o->X) * TRIG_ADJ);
- c5 = (number)(cos(o->Z) * TRIG_ADJ); c6 = (number)(sin(o->Z) * TRIG_ADJ);
- c7 = (number)g->winH; c8 = (number)(2.0 * g->winH);
- c9 = (number)g->winV; c10 = (number)(2.0 * g->winV);
- c11 = (number)o->tX; c12 = (number)(o->tY - o->viewpointY);
- c13 = (number)o->tZ; c14 = (number)o->BViewpointX;
- c15 = (number)(o->BViewpointX * o->focus); c16 = (number)-o->oX;
- c17 = (number)-o->oY; c18 = (number)-o->oZ;
-
- objClip = 0;
- o->Hmin2 = o->Hmin1; o->Vmin2 = o->Vmin1;
- o->Hmax2 = o->Hmax1; o->Vmax2 = o->Vmax1;
- o->Hmin1 = o->Hmin; o->Vmin1 = o->Vmin;
- o->Hmax1 = o->Hmax; o->Vmax1 = o->Vmax;
- o->Hmin = c8; o->Vmin = c10;
- o->Hmax = 0; o->Vmax = 0;
-
- /* What happens to the bounding box? */
-
- while(p0 != p1){
- STEREOROTATE;
-
- if(STEREOCLIPFLAGS)
- objClip = 1;
-
- if((int)r7 < o->Vmin){ o->Vmin = (int)r7; }
- if((int)r7 > o->Vmax){ o->Vmax = (int)r7; }
-
- if((int)r8 < o->Hmin){ o->Hmin = (int)r8; }
- if((int)r8 > o->Hmax){ o->Hmax = (int)r8; }
-
- if((g->stereo) && (g->stereoBlue)){
- if((int)r9 < o->Hmin){ o->Hmin = (int)r9; }
- if((int)r9 > o->Hmax){ o->Hmax = (int)r9; }
- }
-
- p0++;
- }
-
- /* Update screen clearing, pix copying variables */
-
- if((g->modeChanged) || (objClip)){
- o->Hmin = o->Hmin1 = o->Hmin2 = 0;
- o->Vmin = o->Vmin1 = o->Vmin2 = 0;
- o->Hmax = o->Hmax1 = o->Hmax2 = g->winX;
- o->Vmax = o->Vmax1 = o->Vmax2 = g->winY;
- }else{
- if(o->Hmin < 0){o->Hmin = 0;}
- if(o->Vmin < 0){o->Vmin = 0;}
- if(o->Hmax > c8){o->Hmax = c8;}
- if(o->Vmax > c10){o->Vmax = c10;}
-
- if(o->Hmin1 < o->Hmin2){o->Hmin2 = o->Hmin1;}
- if(o->Vmin1 < o->Vmin2){o->Vmin2 = o->Vmin1;}
- if(o->Hmax1 > o->Hmax2){o->Hmax2 = o->Hmax1;}
- if(o->Vmax1 > o->Vmax2){o->Vmax2 = o->Vmax1;}
- }
-
- o->fillX = o->Hmin2; o->fillY = o->Vmin2;
- o->fillWidth = o->Hmax2 - o->Hmin2 + 1;
- o->fillHeight = o->Vmax2 - o->Vmin2 + 1;
-
- if(o->Hmin < o->Hmin2){o->Hmin2 = o->Hmin;}
- if(o->Vmin < o->Vmin2){o->Vmin2 = o->Vmin;}
- if(o->Hmax > o->Hmax2){o->Hmax2 = o->Hmax;}
- if(o->Vmax > o->Vmax2){o->Vmax2 = o->Vmax;}
-
- o->copyX = o->Hmin2; o->copyY = o->Vmin2;
- o->copyWidth = o->Hmax2 - o->Hmin2 + 1;
- o->copyHeight = o->Vmax2 - o->Vmin2 + 1;
-
- o->objClip = objClip;
- p0 = o->points;
- p1 = &(o->points[o->numPoints]);
-
- if(objClip){
-
- /* The object is not totally visible, do clipping */
-
- if((g->stereo) && (g->stereoBlue)){
- if(g->renderMode == WIREFRAME){
- while(p0 != p1){
- STEREOROTATE;
- p0->Y = (float)r7; p0->R.y = (short)r7;
- p0->RX = (float)r8; p0->R.x = (short)r8;
- p0->BX = (float)r9; p0->sBX = (short)r9;
- p0->ClipFlags = STEREOCLIPFLAGS;
- p0++;
- }
- }else{
-
- while(p0 != p1){
- STEREOROTATE;
- p0->dist = (float)r5;
- p0->Y = (float)r7; p0->R.y = (short)r7;
- p0->RX = (float)r8; p0->R.x = (short)r8;
- p0->BX = (float)r9; p0->sBX = (short)r9;
- p0->ClipFlags = STEREOCLIPFLAGS;
- p0++;
- }
- }
- }else{
- if(g->renderMode == WIREFRAME){
- while(p0 != p1){
- REDROTATE;
- p0->Y = (float)r7; p0->R.y = (short)r7;
- p0->RX = (float)r8; p0->R.x = (short)r8;
- p0->ClipFlags = REDCLIPFLAGS;
- p0++;
- }
- }else{
-
- while(p0 != p1){
- REDROTATE;
- p0->dist = (float)r5;
- p0->Y = (float)r7; p0->R.y = (short)r7;
- p0->RX = (float)r8; p0->R.x = (short)r8;
- p0->ClipFlags = REDCLIPFLAGS;
- p0++;
- }
- }
- }
- }else{
-
- /* The object is totally visible, skip clipping */
-
- if((g->stereo) && (g->stereoBlue)){
- if(g->renderMode == WIREFRAME){
- while(p0 != p1){
- STEREOROTATE;
- p0->R.y = (short)r7;
- p0->R.x = (short)r8;
- p0->sBX = (short)r9;
- p0++;
- }
- }else{
-
- while(p0 != p1){
- STEREOROTATE;
- p0->dist = (float)r5;
- p0->R.y = (short)r7;
-
- RX = r8;
- p0->R.x = (float)RX;
-
- BX = r9;
- p0->sBX = (float)BX;
-
- p0++;
- }
- }
- }else{
- if(g->renderMode == WIREFRAME){
- while(p0 != p1){
- REDROTATE;
- p0->R.y = (short)r7;
- p0->R.x = (short)r8;
- p0++;
- }
- }else{
-
- while(p0 != p1){
- REDROTATE;
- p0->dist = (float)r5;
-
- p0->R.y = (short)r7;
- RX = (short)r8;
- p0->R.x = (float)RX;
-
- p0++;
- }
- }
- }
- }
- }
-
-
-
-
- static void DrawSegments(display, win, gc, segs, numSegs, g)
- Display *display;
- Window win;
- GC gc;
- XSegment segs[];
- int numSegs;
- Ginfo *g;
- /******************************************************************************
- Thanks to Mark Cook for the suggestion to pay attention the the
- maximum request size of the X server!
- ******************************************************************************/
- {
- int requestSize, evenAmount, remainder, index;
-
- requestSize = g->requestSize;
- evenAmount = (numSegs / requestSize) * requestSize;
- remainder = numSegs - evenAmount;
-
- index = 0;
-
- while(index < evenAmount){
- XDrawSegments(display, win, gc, &segs[index], requestSize);
- index += requestSize;
- }
-
- if(remainder)
- XDrawSegments(display, win, gc, &segs[index], remainder);
- }
-
-
-
- static void DrawLines(o, g, mode)
- Oinfo *o;
- Ginfo *g;
- int mode;
- /******************************************************************************
- Draw lines for the three display modes.
- ******************************************************************************/
- {
- Drawable dest;
- long lastColor;
- int lastChange, index;
-
- dest = g->dest;
-
- switch(mode){
-
- case BW:
- XSetForeground(g->dpy, g->gc, g->black);
- XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
- o->fillWidth, o->fillHeight);
- XSetForeground(g->dpy, g->gc, g->white);
- DrawSegments (g->dpy, dest, g->gc, g->redSegments, g->numberRed, g);
- break;
-
- case STEREO:
-
- XSetForeground(g->dpy, g->gc, (long)g->Black);
- XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
- o->fillWidth, o->fillHeight);
-
- XSetForeground(g->dpy, g->gc, (long)g->Red);
- DrawSegments(g->dpy, dest, g->gc, g->redSegments, g->numberRed, g);
-
- if(g->stereoBlue){
-
- XSetFunction (g->dpy, g->gc, GXor);
-
- XSetForeground(g->dpy, g->gc, (long)g->Blue);
- DrawSegments(g->dpy, dest, g->gc, g->blueSegments, g->numberBlue,
- g);
-
- XSetFunction (g->dpy, g->gc, GXcopy);
- }
-
- break;
-
- case COLOR:
-
- XSetForeground(g->dpy, g->gc, g->Black);
- XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
- o->fillWidth, o->fillHeight);
-
- lastChange = 4;
- lastColor = g->redColors[lastChange];
-
- for(index = 5; index < g->numberRed; index++){
- if(g->redColors[index] != lastColor){
- XSetForeground(g->dpy, g->gc, lastColor);
- DrawSegments(g->dpy, dest, g->gc, &(g->redSegments[lastChange]),
- index - lastChange, g);
- lastChange = index;
- lastColor = g->redColors[lastChange];
- }
- }
-
- XSetForeground(g->dpy, g->gc, lastColor);
- DrawSegments(g->dpy, dest, g->gc, &(g->redSegments[lastChange]),
- g->numberRed - lastChange, g);
-
- break;
-
- default:
- break;
- }
- }
-
-
-
- static void DrawHiddenLines(o, g, mode)
- Oinfo *o;
- Ginfo *g;
- int mode;
- /******************************************************************************
- Draw polygon outlines using painter algorithm for the three display modes.
- ******************************************************************************/
- {
- register int index, npoints, numPolys;
- register polygon *poly, **list;
- register point **pointPtr, **lastPointPtr;
- Drawable dest;
-
- XPoint points[512], *XPointPtr;
-
- dest = g->dest;
- numPolys = o->numPolys;
- list = o->list;
-
- sort(list, numPolys);
-
- switch(mode){
-
- case BW:
-
- XSetForeground(g->dpy, g->gc, g->black);
- XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
- o->fillWidth, o->fillHeight);
-
- for(index = 0; index < numPolys; index++){
-
- poly = list[index];
- XPointPtr = points;
- npoints = poly->numPoints;
- pointPtr = poly->points;
- lastPointPtr = &(poly->points[npoints]);
-
- while(pointPtr < lastPointPtr){
- *XPointPtr = (*pointPtr)->R;
- XPointPtr++;
- pointPtr++;
- }
-
- XSetForeground(g->dpy, g->gc, g->black);
- XFillPolygon(g->dpy, dest, g->gc, points, npoints, Convex,
- CoordModeOrigin);
- points[npoints] = points[0];
- XSetForeground(g->dpy, g->gc, g->white);
- XDrawLines(g->dpy, dest, g->gc, points, npoints + 1,
- CoordModeOrigin);
- }
-
- XSetFillStyle(g->dpy, g->gc, FillSolid);
- break;
-
- case STEREO:
-
- XSetForeground(g->dpy, g->gc, g->stereoBlack);
- XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
- o->fillWidth, o->fillHeight);
-
- XSetPlaneMask(g->dpy, g->gc, g->redMask);
-
- for(index = 0; index < numPolys; index++){
- poly = list[index];
- XPointPtr = points;
- npoints = poly->numPoints;
- pointPtr = poly->points;
- lastPointPtr = &(poly->points[npoints]);
-
- while(pointPtr < lastPointPtr){
- *XPointPtr = (*pointPtr)->R;
- XPointPtr++;
- pointPtr++;
- }
-
- XSetForeground(g->dpy, g->gc, g->stereoBlack);
- XFillPolygon(g->dpy, dest, g->gc, points, npoints, Convex,
- CoordModeOrigin);
- points[npoints] = points[0];
- XSetForeground(g->dpy, g->gc, poly->color->stereoColor);
- XDrawLines(g->dpy, dest, g->gc, points, npoints + 1,
- CoordModeOrigin);
- }
-
- if(g->stereoBlue){
- XSetPlaneMask(g->dpy, g->gc, g->blueMask);
-
- for(index = 0; index < numPolys; index++){
- poly = list[index];
- XPointPtr = points;
- npoints = poly->numPoints;
- pointPtr = poly->points;
- lastPointPtr = &(poly->points[npoints]);
-
- while(pointPtr < lastPointPtr){
- XPointPtr->x = (*pointPtr)->sBX;
- XPointPtr->y = (*pointPtr)->R.y;
- XPointPtr++;
- pointPtr++;
- }
-
- XSetForeground(g->dpy, g->gc, g->stereoBlack);
- XFillPolygon(g->dpy, dest, g->gc, points, npoints, Convex,
- CoordModeOrigin);
- points[npoints] = points[0];
- XSetForeground(g->dpy, g->gc, poly->color->stereoColor);
- XDrawLines(g->dpy, dest, g->gc, points, npoints + 1,
- CoordModeOrigin);
- }
- }
- XSetPlaneMask(g->dpy, g->gc, AllPlanes);
- break;
-
- case COLOR:
-
- XSetForeground(g->dpy, g->gc, g->Black);
- XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
- o->fillWidth, o->fillHeight);
-
- for(index = 0; index < numPolys; index++){
- poly = list[index];
- XPointPtr = points;
- npoints = poly->numPoints;
- pointPtr = poly->points;
- lastPointPtr = &(poly->points[npoints]);
-
- while(pointPtr < lastPointPtr){
- *XPointPtr = (*pointPtr)->R;
- XPointPtr++;
- pointPtr++;
- }
-
- XSetForeground(g->dpy, g->gc, g->Black);
- XFillPolygon(g->dpy, dest, g->gc, points, npoints, Convex,
- CoordModeOrigin);
- points[npoints] = points[0];
- XSetForeground(g->dpy, g->gc, poly->color->value);
- XDrawLines(g->dpy, dest, g->gc, points, npoints + 1,
- CoordModeOrigin);
- }
-
- break;
-
- default:
- break;
- }
- }
-
-
-
- static void DrawPolys(o, g, mode)
- Oinfo *o;
- Ginfo *g;
- int mode;
- /******************************************************************************
- Draw polygons using painter algorithm for the three display modes.
- ******************************************************************************/
- {
- register int index, npoints, numPolys;
- register polygon *poly, **list;
- register point **pointPtr, **lastPointPtr;
- Drawable dest;
- XPoint points[512], *XPointPtr;
- long lastColor;
-
- dest = g->dest;
- numPolys = o->numPolys;
- list = o->list;
-
- sort(list, numPolys);
-
- switch(mode){
-
- case BW:
-
- XSetForeground(g->dpy, g->gc, g->black);
- XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
- o->fillWidth, o->fillHeight);
- XSetForeground(g->dpy, g->gc, g->white);
- XSetBackground(g->dpy, g->gc, g->black);
- XSetFillStyle(g->dpy, g->gc, FillOpaqueStippled);
-
- for(index = 0; index < numPolys; index++){
-
- poly = list[index];
- XPointPtr = points;
- XSetStipple(g->dpy, g->gc, g->stipple[poly->color->stipple]);
- npoints = poly->numPoints;
- pointPtr = poly->points;
- lastPointPtr = &(poly->points[npoints]);
-
- while(pointPtr < lastPointPtr){
- *XPointPtr = (*pointPtr)->R;
- XPointPtr++;
- pointPtr++;
- }
-
- XFillPolygon(g->dpy, dest, g->gc, points, npoints, Convex,
- CoordModeOrigin);
- }
-
- XSetFillStyle(g->dpy, g->gc, FillSolid);
- break;
-
- case STEREO:
-
- XSetForeground(g->dpy, g->gc, g->stereoBlack);
- XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
- o->fillWidth, o->fillHeight);
- lastColor = g->stereoBlack;
-
- XSetPlaneMask(g->dpy, g->gc, g->redMask);
-
- for(index = 0; index < numPolys; index++){
- poly = list[index];
- XPointPtr = points;
- if(poly->color->stereoColor != lastColor){
- XSetForeground(g->dpy, g->gc, poly->color->stereoColor);
- lastColor = poly->color->stereoColor;
- }
- npoints = poly->numPoints;
- pointPtr = poly->points;
- lastPointPtr = &(poly->points[npoints]);
-
- while(pointPtr < lastPointPtr){
- *XPointPtr = (*pointPtr)->R;
- XPointPtr++;
- pointPtr++;
- }
-
- XFillPolygon(g->dpy, dest, g->gc, points, npoints, Convex,
- CoordModeOrigin);
- }
-
- if(g->stereoBlue){
- XSetPlaneMask(g->dpy, g->gc, g->blueMask);
-
- for(index = 0; index < numPolys; index++){
- poly = list[index];
- XPointPtr = points;
- if(poly->color->stereoColor != lastColor){
- XSetForeground(g->dpy, g->gc, poly->color->stereoColor);
- lastColor = poly->color->stereoColor;
- }
- npoints = poly->numPoints;
- pointPtr = poly->points;
- lastPointPtr = &(poly->points[npoints]);
-
- while(pointPtr < lastPointPtr){
- XPointPtr->x = (*pointPtr)->sBX;
- XPointPtr->y = (*pointPtr)->R.y;
- XPointPtr++;
- pointPtr++;
- }
-
- XFillPolygon(g->dpy, dest, g->gc, points, npoints, Convex,
- CoordModeOrigin);
- }
- }
- XSetPlaneMask(g->dpy, g->gc, AllPlanes);
- break;
-
- case COLOR:
-
- XSetForeground(g->dpy, g->gc, g->Black);
- XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
- o->fillWidth, o->fillHeight);
- lastColor = g->Black;
-
- for(index = 0; index < numPolys; index++){
- poly = list[index];
- XPointPtr = points;
- if(poly->color->value != lastColor){
- XSetForeground(g->dpy, g->gc, poly->color->value);
- lastColor = poly->color->value;
- }
- npoints = poly->numPoints;
- pointPtr = poly->points;
- lastPointPtr = &(poly->points[npoints]);
-
- while(pointPtr < lastPointPtr){
- *XPointPtr = (*pointPtr)->R;
- XPointPtr++;
- pointPtr++;
- }
-
- XFillPolygon(g->dpy, dest, g->gc, points, npoints, Convex,
- CoordModeOrigin);
- }
-
- break;
-
- default:
- break;
- }
- }
-
-
-
- static void BeginImage(o, g)
- Oinfo *o;
- Ginfo *g;
- /******************************************************************************
- Prepare to draw some x3d objects.
- ******************************************************************************/
- {
-
- /* Try to get rid of a few of the mode change glitches (several exist yet) */
-
- if(g->modeChanged){
- XSetPlaneMask(g->dpy, g->gc, AllPlanes);
- if((g->mono) || (g->depth == ONE)){
- XSetForeground(g->dpy, g->gc, g->black);
- }else{
- if(g->stereo){
- XSetForeground(g->dpy, g->gc, (long)g->Black);
- }else{
- XSetForeground(g->dpy, g->gc, g->Black);
- }
- }
-
- XFillRectangle(g->dpy, g->pix, g->gc, 0, 0, g->winX, g->winY);
- XFillRectangle(g->dpy, g->win, g->gc, 0, 0, g->winX, g->winY);
- }
-
- if(g->buffer){
- if((g->mono) || (g->depth != EIGHT)){
- g->dest = g->pix;
- }else{
- if((g->numColors > BUFFER_CMAP) || (((g->renderMode == SOLID) ||
- (g->renderMode == HIDDENLINE)) && (g->stereo))){
- g->dest = g->pix;
- }else{
- g->dest = g->win;
-
- if(g->ColorSelect){
- XSetPlaneMask(g->dpy, g->gc, BUFFER1);
- }else{
- XSetPlaneMask(g->dpy, g->gc, BUFFER0);
- }
- }
- }
- }else{
- g->dest = g->win;
- }
- }
-
-
-
- static void DrawObject(o, g)
- Oinfo *o;
- Ginfo *g;
- /******************************************************************************
- Draw an x3d objext to the screen. Be sure to draw the objects back to
- front when calling this function.
- ******************************************************************************/
- {
-
- /* rotate the object */
-
- rotate(o, g);
-
- /* Clip against the screen edges */
-
- clip(o, g);
-
- /* Draw in the proper render mode */
-
- switch(g->renderMode){
-
- case WIREFRAME:
- if((g->mono) || (g->depth == ONE)){
- DrawLines(o, g, BW);
- }else{
- if(g->stereo){
- DrawLines(o, g, STEREO);
- }else{
- DrawLines(o, g, COLOR);
- }
- }
- break;
-
- case HIDDENLINE:
- if((g->mono) || (g->depth == ONE)){
- DrawHiddenLines(o, g, BW);
- }else{
- if(g->stereo){
- DrawHiddenLines(o, g, STEREO);
- }else{
- DrawHiddenLines(o, g, COLOR);
- }
- }
- break;
-
- case SOLID:
- if((g->mono) || (g->depth == ONE)){
- DrawPolys(o, g, BW);
- }else{
- if(g->stereo){
- DrawPolys(o, g, STEREO);
- }else{
- DrawPolys(o, g, COLOR);
- }
- }
- break;
-
- default :
- fprintf(stderr, "Unknown Render Mode!\n");
- exit(1);
- break;
- }
-
- /* Reset the number of lines (We always keep the purple rectangle) */
-
- g->numberRed = 4;
- g->numberBlue = 4;
- g->numRedColors = 4;
- g->modeChanged = 0;
- }
-
-
-
- static void EndImage(o, g)
- Oinfo *o;
- Ginfo *g;
- /******************************************************************************
- Finish drawing x3d objects.
- ******************************************************************************/
- {
-
- /* Colormap double buffer? */
-
- if((g->depth == EIGHT) && (!(g->mono)) && (g->numColors <= BUFFER_CMAP) &&
- (!((g->stereo) && (g->renderMode == HIDDENLINE))) &&
- (!((g->stereo) && (g->renderMode == SOLID)))){
- g->ColorSelect = !g->ColorSelect;
-
- if((g->stereo) && (g->renderMode == WIREFRAME) && (!(g->modeChanged))){
- XStoreColors(g->dpy, g->colormap, g->wireframeColors[g->ColorSelect],
- 12);
- }else{
- XStoreColors(g->dpy, g->colormap, g->cmapColors[g->ColorSelect], 256);
- }
- }else{
-
- /* Stereo solid, wireframe? */
-
- if(g->depth == EIGHT){
- if(((g->renderMode == SOLID) || (g->renderMode == HIDDENLINE))
- && (g->stereo)){
- XStoreColors(g->dpy, g->colormap, g->cmapColors[2], 256);
- }else{
- XStoreColors(g->dpy, g->colormap, g->cmapColors[g->ColorSelect],
- 256);
- }
- }
-
- /* generic */
-
- if(g->buffer){
- XCopyArea(g->dpy, g->pix, g->win, g->gc, o->copyX, o->copyY,
- o->copyWidth, o->copyHeight, o->copyX, o->copyY);
- }
- }
-
- XFlush(g->dpy);
- }
-
- #ifndef DEBUG
-
- void main(argc, argv)
- int argc;
- char *argv[];
- /******************************************************************************
- Parse the command line, read the object from a file, then for forever
- drawObjects, update position ...
- ******************************************************************************/
- {
- Ginfo *g;
- Oinfo *o;
- char *filename;
-
- if((o = (Oinfo *)calloc(1, sizeof(Oinfo))) == NULL){
- (void)fprintf(stderr, "Unable to allocate memory for Object\n"); exit(1);}
-
- if((g = (Ginfo *)calloc(1, sizeof(Ginfo))) == NULL){
- (void)fprintf(stderr, "Unable to allocate memory for Ginfo\n"); exit(1);}
-
- /* Check the usage */
-
- ParseCommandLine(argc, argv, &filename, g);
-
- /* Read in the points and segments from a file */
-
- readObjectFile(filename, &(g->colors), &(g->numColors), &(o->points),
- &(o->numPoints), &(o->segs), &(o->numSegs), &(o->polys),
- &(o->numPolys), &(o->list), &(o->bounds));
-
- /* Define viewing parameters */
-
- o->BViewpointX = 100.0;
- o->tX = 640.0; o->tY = 6000.0; o->tZ = 490.0;
- o->viewpointY = -650.0;
- o->X = o->Y = o->Z = 0.0;
- o->dX = o->dY = o->dZ = 0.0;
- o->oX = o->oY = o->oZ = 0.0;
- o->focus = 0.2;
-
- /* Initialize the display */
-
- InitDisplay(o, g);
-
- /* Forever do... */
-
- while (1){
-
- /* Draw object according to current position and rendering information */
-
- BeginImage(o, g);
- DrawObject(o, g);
- EndImage(o, g);
-
- /* Get new position information */
-
- UpdatePosition(o, g);
- }
- }
-
-
- #else
-
- void main(argc, argv)
- int argc;
- char *argv[];
- /******************************************************************************
- Parse the command line, read the object from a file, then for forever
- drawObjects, update position ...
- ******************************************************************************/
- {
-
- char line[MAXLINE];
-
- static char results[][MAXLINE] = {
- "Below",
- "Intersect",
- "Above",
- "Same",
- "Ends Intersect"
- };
-
- FILE *fd;
- int lineNo;
-
- int v1, v2, v3, v4;
-
- point mp, mq, np, nq, *pt;
- segment m, n, *seg;
- int x, y;
-
- if((fd = fopen(argv[1], "r")) == NULL){
- fprintf(stderr, "Unable to open %s\n", argv[1]);
- exit(1);
- }
-
- lineNo = 0;
-
- m.P = ∓
- m.Q = &mq;
- n.P = &np;
- n.Q = &nq;
-
- if(readLine(fd, line, &lineNo)){
- (void)fprintf(stderr, "Error reading line.\n");
- exit(1);
- }
-
- while(feof(fd) == 0){
-
- sscanf(line, "%d %d %d %d", &v1, &v2, &v3, &v4);
-
- mp.R.x = v1;
- mp.R.y = v2;
- mq.R.x = v3;
- mq.R.y = v4;
-
- if(readLine(fd, line, &lineNo)){
- (void)fprintf(stderr, "ERROR reading line.\n");
- exit(1);
- }
-
- sscanf(line, "%d %d %d %d", &v1, &v2, &v3, &v4);
-
- np.R.x = v1;
- np.R.y = v2;
- nq.R.x = v3;
- nq.R.y = v4;
-
- printf("M %d %d %d %d\n", mp.R.x, mp.R.y, mq.R.x, mq.R.y);
- printf("N %d %d %d %d\n", np.R.x, np.R.y, nq.R.x, nq.R.y);
-
- x = 0; y = 0;
-
- seg = &m;
-
- pt = seg->P;
- if(pt->R.y > seg->Q->R.y){
- seg->P = seg->Q;
- seg->Q = pt;
- }
-
- seg = &n;
-
- pt = seg->P;
- if(pt->R.y > seg->Q->R.y){
- seg->P = seg->Q;
- seg->Q = pt;
- }
-
- printf(" result %s ", results[1 + compareSegments(&m, &n, &x, &y, 0)]);
- printf(" %d %d\n", x, y);
-
- readLine(fd, line, &lineNo);
- }
-
- fclose(fd);
- }
-
- #endif
-