x3d.c

Go to the documentation of this file.
00001 /* @(#)root/x3d:$Id: x3d.c 35365 2010-09-17 12:38:18Z brun $ */
00002 /* Author: Mark Spychalla*/
00003 /*
00004   Copyright 1992 Mark Spychalla
00005 
00006   Permission to use, copy, modify, distribute, and sell this software and
00007   its documentation for any purpose is hereby granted without fee,
00008   provided that the above copyright notice appear in all copies and that
00009   both that copyright notice and this permission notice appear in
00010   supporting documentation, and that the name of Mark Spychalla not be used
00011   in advertising or publicity pertaining to distribution of the software
00012   without specific, written prior permission.  Mark Spychalla makes no
00013   representations about the suitability of this software for any purpose.
00014   It is provided "as is" without express or implied warranty.
00015 
00016   Mark Spychalla disclaims all warranties with regard to this software,
00017   including all implied warranties of merchantability and fitness, in no
00018   event shall Mark Spychalla be liable for any special, indirect or
00019   consequential damages or any damages whatsoever resulting from loss of use,
00020   data or profits, whether in an action of contract, negligence or other
00021   tortious action, arising out of or in connection with the use or performance
00022   of this software.
00023 */
00024 
00025 
00026 
00027 /*
00028 
00029 NOTE ON X3D CODING STYLE:
00030 
00031    Don't think I usually code in the gerberized fashion that X3D demonstrates.
00032 X3D was written for speed at any cost.  My goal was to write the fastest 3D
00033 object viewer that I could, period.   Regular programs ought to be written
00034 with different goals in mind such as:
00035 
00036 1) A program has excellent documentation that ANYONE can read.
00037 2) A program when released has no strange "features" or bugs.
00038 3) A program is robust and handles ALL extreme and unusual cases.
00039 4) A program is written in phases and modules with hard tests for each one.
00040 5) A program is written for any user who doesn't need special knowledge
00041    to use the program.
00042 6) A program has well defined user requirements and functional specifications.
00043 7) A program is written with regard to future expansion and integreation
00044    with other systems (portability).
00045 
00046 When programming following these additional principles make programs easier
00047 to maintain.
00048 
00049 A) Choose variable names that accurately describes what the variable does/is.
00050 B) Write comments to inform someone faced with the task of modifying your code.
00051 C) Avoid excessive comments.  Write the code so that it says what it does.
00052 D) Follow a strict one-in, one-out flow of control structues except in the
00053    case of fatal error conditions.
00054 E) Avoid using global variables.
00055 F) Do not cause side effects to variables that were not parameters to a
00056    function.
00057 G) Have a single function perform a single purpose.
00058 H) Select a single indentation style and stick with it.
00059 I) Use a consistent naming convention.
00060 
00061 The following principles help me when I try optimizing code:
00062 
00063 a) If optimizing, use a profiler to determine which sections of code most of
00064    the time is spent in.  Spend most of your effort in the most used sections.
00065    Don't bother optimizing a procedure using less than 10% of the time.
00066 
00067 b) High level optimizations are far more effective than cycle shaving.
00068    (e.g. use quick sort instead of optimizing a bubble sort.)
00069 
00070 c) Be flexible in your approach to solving a problem.  List exactly what you
00071    need as a result at a minimum.  Get rid of unnecessary assumptions.
00072 
00073 d) Become familiar with sets of operations that are equivalent, or nearly so.
00074    Learn the relative expense of basic operations.
00075 
00076 e) If possible, be careful not to needlessly sacrifice significant readability
00077    of the code for a cycle or two.
00078 
00079 -- Spy
00080 
00081 */
00082 
00083 
00084 #ifndef WIN32
00085 #include "x3d.h"
00086 #include "X3DBuffer.h"
00087 #endif
00088 
00089 #ifdef WIN32
00090 
00091 unsigned long x3d_main(float *longitude, float *latitude, float *psi,
00092                        const char *string) { return 0L; }
00093 void x3d_terminate() { }
00094 void x3d_get_position(float *longitude, float *latitude, float *psi) { }
00095 int  x3d_dispatch_event(unsigned long event) { return 0; }
00096 void x3d_set_display(unsigned long display) { }
00097 void x3d_update() { }
00098 
00099 #else
00100 
00101 
00102 #include <stdio.h>
00103 #include <math.h>
00104 #include <string.h>
00105 #include <stdlib.h>
00106 #include <X11/Xlib.h>
00107 #include <X11/Xatom.h>
00108 #include <X11/Xutil.h>
00109 #include <X11/X.h>
00110 
00111 
00112 extern Color   *colors;
00113 extern point   *points;
00114 extern segment *segs;
00115 extern polygon *polys;
00116 
00117 extern int  currPoint, currSeg, currPoly;
00118 
00119 static polygon **list;
00120 static point   *bounds;
00121 static int quitApplication = 0;
00122 static Display *gDisplay = NULL;
00123 static Ginfo *gGInfo = NULL;
00124 static Oinfo *gOInfo = NULL;
00125 
00126 static int gRedDiv, gGreenDiv, gBlueDiv, gRedShift, gGreenShift, gBlueShift;
00127 
00128 
00129 
00130 static void sort(list1, numPolys)
00131 polygon **list1;
00132 int numPolys;
00133 /*****************************************************************************
00134    Specialized quick sort for painter algorithm.
00135 *****************************************************************************/
00136 {
00137 polygon **v0, **v1, **v2, **v3, **v4, **v5, **v6, *poly;
00138 register int stackIndex, stackNotSet, length, start, end, high;
00139 float dist;
00140 int numPoints;
00141 StackElement stack[MAXSTACK];
00142 point **Point, **lastPoint;
00143 
00144    v0 = list1;
00145    v1 = &(list1[numPolys]);
00146 
00147 /* Set the key value to be the average of the vertices' distances */
00148 
00149    while(v0 < v1){
00150       poly = *v0;
00151       numPoints = poly->numPoints;
00152       Point = poly->points;
00153       lastPoint = Point + numPoints;
00154       dist = 0.0;
00155 
00156       do{
00157          dist += (*Point)->dist;
00158          Point++;
00159       }while(Point < lastPoint);
00160 
00161       poly->dist = dist / ((float)numPoints);
00162       v0++;
00163       }
00164 
00165 /* Initialize for the qsort() */
00166 
00167    stackIndex = 1;
00168    stackNotSet = 0;
00169    start = 0;
00170    end = numPolys - 1;
00171 
00172 /* Do Qsort */
00173 
00174    while(stackIndex){
00175 
00176        if(stackNotSet){
00177           start = stack[stackIndex].start;
00178           end = stack[stackIndex].end;
00179        }
00180 
00181        stackIndex--;
00182        stackNotSet = 1;
00183        length = end - start;
00184 
00185 /* Big enough to qsort ? */
00186 
00187       if(length > STOP){
00188          v1 = &(list1[start]);
00189          v2 = &(list1[start + (length / 4)]);
00190          v3 = &(list1[start + (length / 2)]);
00191          v4 = &(list1[start + ((length * 3) / 4)]);
00192          v5 = &(list1[end]);
00193          v6 = v1;
00194 
00195          median5(v1,v2,v3,v4,v5)
00196 
00197          *v0 = *v3;
00198          *v3 = *v6;
00199          *v6 = *v0;
00200 
00201          v1 = &(list1[start + 1]);
00202          v2 = &(list1[end]);
00203 
00204 /* Split */
00205 
00206          dist = (*v6)->dist;
00207          while((*v2)->dist < dist) v2--;
00208          while((*v1)->dist > dist) v1++;
00209 
00210          v5 = v0;
00211 
00212          while(v1 < v2){
00213 
00214             *v5 = *v2;
00215             *v2 = *v1;
00216 
00217             v5 = v1;
00218 
00219             do{
00220                v2--;
00221             }while(((*v2)->dist < dist) && (v1 < v2));
00222             if (v2 <= v1) break;
00223 
00224             do{
00225                v1++;
00226             }while(((*v1)->dist > dist) && (v1 < v2));
00227             if (v2 <= v1) break;
00228          }
00229 
00230          v2 = v1 - 1;
00231 
00232          *v5 = *v2;
00233          *v2 = *v6;
00234          *v6 = *v0;
00235 
00236          high = v2 - list1;
00237 
00238 /* Put sublists on the stack, smallest on top */
00239 
00240          if((high - start) > (end - high)){
00241             stack[++stackIndex].start = start;
00242             stack[stackIndex].end = high - 1;
00243             ++stackIndex;
00244             start = high + 1;
00245             stackNotSet = 0;
00246          }else{
00247             stack[++stackIndex].start = high + 1;
00248             stack[stackIndex].end = end;
00249             ++stackIndex;
00250             end = high - 1;
00251             stackNotSet = 0;
00252             }
00253       }
00254    }
00255 
00256 /* insertion sort all the remaining sublists at once */
00257 
00258    v2 = list1;
00259    v3 = &(list1[numPolys - 1]);
00260    v4 = v2 + 1;
00261 
00262    while(v4 <= v3){
00263 
00264       *v0 = *v4;
00265       v1 = v4 - 1;
00266 
00267       while((v1 >= v2) && ((*v1)->dist < (*v0)->dist)){
00268          *(v1 + 1) = *v1;
00269          v1--;
00270          }
00271 
00272       *(v1 + 1) = *v0;
00273       v4++;
00274       }
00275 }
00276 
00277 
00278 
00279 static void Rotate(points1, cx, cy, cz, sx, sy, sz)
00280 anglePoint *points1;
00281 double cx, cy, cz, sx, sy, sz;
00282 /******************************************************************************
00283    Rotate about Z, X, then Y, for two points.
00284 ******************************************************************************/
00285 {
00286 int index1;
00287 double x, y, z, t;
00288 
00289     for(index1 = 0; index1 < 2; index1++){
00290        x = points1[index1].x;
00291        y = points1[index1].y;
00292        z = points1[index1].z;
00293 
00294        t = x * cz + y * sz;
00295        y = y * cz - x * sz;
00296        x = t;
00297 
00298        points1[index1].y = y * cx + z * sx;
00299 
00300        z = z * cx - y * sx;
00301 
00302        points1[index1].x = x * cy + z * sy;
00303        points1[index1].z = z * cy - x * sy;
00304        }
00305 }
00306 
00307 
00308 
00309 static double DotProduct(x1, Y1, x2, y2)
00310 double x1, Y1, x2, y2;
00311 /******************************************************************************
00312    Dot product (calculate the cosine of the angle between two vectors).
00313 ******************************************************************************/
00314 {
00315 double temp;
00316 
00317    if((x1 == 0.0 && Y1 == 0.0)){
00318       return 1.0;
00319       }
00320 
00321    temp = sqrt(x1 * x1 + Y1 * Y1);
00322    x1 = x1 / temp;
00323    Y1 = Y1 / temp;
00324 
00325    temp = x1 * x2 + Y1 * y2;
00326 
00327    if(temp > 1.0)
00328       temp = fmod(temp, 1.0);
00329 
00330    if(temp < -1.0)
00331       temp = -fmod(-temp, 1.0);
00332 
00333    return(temp);
00334 }
00335 
00336 
00337 
00338 static void CalculateAngles(X, Y, Z, X1, Y1, Z1)
00339 double *X, *Y, *Z;
00340 double X1, Y1, Z1;
00341 /******************************************************************************
00342    Calculate what the result of the angle changes of X1, Y1, and Z1 are
00343    in my weird coordinate system.
00344 ******************************************************************************/
00345 {
00346 anglePoint points1[2];
00347 
00348    points1[0].x = 0.0; points1[0].y = 0.0; points1[0].z = 1.0;
00349    points1[1].x = 1.0; points1[1].y = 0.0; points1[1].z = 0.0;
00350 
00351    Rotate(points1, cos(*X), cos(*Y), cos(*Z), sin(*X), sin(*Y), sin(*Z));
00352    Rotate(points1, cos(X1), cos(Y1), cos(Z1), sin(X1), sin(Y1), sin(Z1));
00353 
00354    *Y = acos(DotProduct(points1[0].x, points1[0].z, 0.0, 1.0));
00355 
00356    if(points1[0].x < 0.0)
00357       *Y = -*Y;
00358 
00359    Rotate(points1, 1.0, cos(-*Y), 1.0, 0.0, sin(-*Y), 0.0);
00360    *X = acos(DotProduct(points1[0].y, points1[0].z, 0.0, 1.0));
00361 
00362    if(points1[0].y < 0.0)
00363       *X = -*X;
00364 
00365    Rotate(points1, cos(-*X), 1.0, 1.0, sin(-*X), 0.0, 0.0);
00366    *Z = acos(DotProduct(points1[1].x, points1[1].y, 1.0, 0.0));
00367 
00368    if(!(points1[1].y < 0.0))
00369       *Z = -*Z;
00370 }
00371 
00372 
00373 
00374 static void DrawLogo(g, x, y)
00375 Ginfo *g;
00376 int x, y;
00377 /******************************************************************************
00378    Display the Logo.
00379 ******************************************************************************/
00380 {
00381 int hUnit, vUnit;
00382    _XPoint points1[512];
00383    void *ptrp = points1;
00384 
00385    hUnit = XTextWidth(g->font, LONGESTSTRING, strlen(LONGESTSTRING)) /
00386    strlen(LONGESTSTRING);
00387    vUnit = FONTHEIGHT(g->font);
00388 
00389 /* X */
00390 
00391    points1[0].x =  9 * hUnit + x; points1[0].y =  1 * vUnit + y;
00392    points1[1].x =  9 * hUnit + vUnit + x; points1[1].y =  1 * vUnit + y;
00393    points1[2].x = 14 * hUnit + vUnit + x; points1[2].y =  6 * vUnit + y;
00394    points1[3].x = 14 * hUnit + x; points1[3].y =  6 * vUnit + y;
00395 
00396    XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
00397    CoordModeOrigin);
00398 
00399    points1[0].x = 14 * hUnit + vUnit + x; points1[0].y =  1 * vUnit + y;
00400    points1[1].x = 14 * hUnit + x; points1[1].y =  1 * vUnit + y;
00401    points1[2].x =  9 * hUnit + x; points1[2].y =  6 * vUnit + y;
00402    points1[3].x =  9 * hUnit + vUnit + x; points1[3].y =  6 * vUnit + y;
00403 
00404    XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
00405    CoordModeOrigin);
00406 
00407 /* 3 */
00408 
00409    points1[0].x = 18 * hUnit + x; points1[0].y =  1 * vUnit + y;
00410    points1[1].x = 22 * hUnit + x; points1[1].y =  1 * vUnit + y;
00411    points1[2].x = 23 * hUnit + x; points1[2].y =  2 * vUnit + y;
00412    points1[3].x = 18 * hUnit + x; points1[3].y =  2 * vUnit + y;
00413 
00414    XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
00415    CoordModeOrigin);
00416 
00417    points1[0].x = 23 * hUnit - vUnit + x; points1[0].y =  2 * vUnit + y;
00418    points1[1].x = 23 * hUnit + x; points1[1].y =  2 * vUnit + y;
00419    points1[2].x = 23 * hUnit + x; points1[2].y =  3 * vUnit + y;
00420    points1[3].x = 23 * hUnit - vUnit + x; points1[3].y =  4 * vUnit + y;
00421 
00422    XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
00423    CoordModeOrigin);
00424 
00425    points1[0].x = 23 * hUnit - vUnit + x; points1[0].y =  3 * vUnit + y;
00426    points1[1].x = 23 * hUnit + x; points1[1].y =  4 * vUnit + y;
00427    points1[2].x = 23 * hUnit + x; points1[2].y =  5 * vUnit + y;
00428    points1[3].x = 23 * hUnit - vUnit + x; points1[3].y =  5 * vUnit + y;
00429 
00430    XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
00431    CoordModeOrigin);
00432 
00433    points1[0].x = 18 * hUnit + x; points1[0].y =  5 * vUnit + y;
00434    points1[1].x = 23 * hUnit + x; points1[1].y =  5 * vUnit + y;
00435    points1[2].x = 22 * hUnit + x; points1[2].y =  6 * vUnit + y;
00436    points1[3].x = 18 * hUnit + x; points1[3].y =  6 * vUnit + y;
00437 
00438    XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
00439    CoordModeOrigin);
00440 
00441    points1[0].x = 19 * hUnit + x; points[0].y =  3 * vUnit + y;
00442    points1[1].x = 23 * hUnit - vUnit + x; points1[1].y =  3 * vUnit + y;
00443    points1[2].x = 23 * hUnit - vUnit + x; points1[2].y =  4 * vUnit + y;
00444    points1[3].x = 19 * hUnit + x; points1[3].y =  4 * vUnit + y;
00445 
00446    XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
00447    CoordModeOrigin);
00448 
00449 /* D */
00450 
00451    points1[0].x = 26 * hUnit + x; points1[0].y =  1 * vUnit + y;
00452    points1[1].x = 30 * hUnit + x; points1[1].y =  1 * vUnit + y;
00453    points1[2].x = 30 * hUnit + vUnit + x; points1[2].y =  2 * vUnit + y;
00454    points1[3].x = 26 * hUnit + x; points1[3].y =  2 * vUnit + y;
00455 
00456    XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
00457    CoordModeOrigin);
00458 
00459    points1[0].x = 26 * hUnit + x; points1[0].y =  5 * vUnit + y;
00460    points1[1].x = 30 * hUnit + vUnit + x; points1[1].y =  5 * vUnit + y;
00461    points1[2].x = 30 * hUnit + x; points1[2].y =  6 * vUnit + y;
00462    points1[3].x = 26 * hUnit + x; points1[3].y =  6 * vUnit + y;
00463 
00464    XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
00465    CoordModeOrigin);
00466 
00467    points1[0].x = 26 * hUnit + x; points1[0].y =  1 * vUnit + y;
00468    points1[1].x = 26 * hUnit + vUnit + x; points1[1].y =  1 * vUnit + y;
00469    points1[2].x = 26 * hUnit + vUnit + x; points1[2].y =  6 * vUnit + y;
00470    points1[3].x = 26 * hUnit + x; points1[3].y =  6 * vUnit + y;
00471 
00472    XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
00473    CoordModeOrigin);
00474 
00475    points1[0].x = 30 * hUnit + x; points1[0].y =  2 * vUnit + y;
00476    points1[1].x = 30 * hUnit + vUnit + x; points1[1].y =  2 * vUnit + y;
00477    points1[2].x = 30 * hUnit + vUnit + x; points1[2].y =  5 * vUnit + y;
00478    points1[3].x = 30 * hUnit + x; points1[3].y =  5 * vUnit + y;
00479 
00480    XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
00481    CoordModeOrigin);
00482 }
00483 
00484 
00485 
00486 static void DisplayMenu(g)
00487 Ginfo *g;
00488 /******************************************************************************
00489    Display the help menu.
00490 ******************************************************************************/
00491 {
00492 int x = 5, y = 5;
00493 
00494    XSetFont(g->dpy, g->helpGc, g->font->fid );
00495 
00496    XSetWindowBackground(g->dpy, g->helpWin, g->black);
00497    XSetForeground(g->dpy, g->helpGc, g->white);
00498    XSetBackground(g->dpy, g->helpGc, g->black);
00499 
00500    XSetStipple(g->dpy, g->helpGc, g->stipple[NUMSTIPPLES / 3]);
00501    XSetFillStyle(g->dpy, g->helpGc, FillOpaqueStippled);
00502 
00503    DrawLogo(g, (XTextWidth(g->font, LONGESTSTRING, strlen(LONGESTSTRING)) /
00504    (int)strlen(LONGESTSTRING)) / 2, FONTHEIGHT(g->font) / 3);
00505 
00506    XSetFillStyle(g->dpy, g->helpGc, FillSolid);
00507 
00508    DrawLogo(g, 0, 0);
00509 
00510    HelpPrint(g,x,y,"");
00511    HelpPrint(g,x,y,"");
00512    HelpPrint(g,x,y,"");
00513    HelpPrint(g,x,y,"");
00514    HelpPrint(g,x,y,"");
00515    HelpPrint(g,x,y,"");
00516    HelpPrint(g,x,y,"");
00517    HelpPrint(g,x,y,"              VERSION 2.2");
00518    HelpPrint(g,x,y,"");
00519    HelpPrint(g,x,y,"  CONTROLS SUMMARY");
00520    HelpPrint(g,x,y,"");
00521    HelpPrint(g,x,y,"     QUIT                    q Q");
00522    HelpPrint(g,x,y,"     WIREFRAME MODE          w W");
00523    HelpPrint(g,x,y,"     HIDDEN LINE MODE        e E");
00524    HelpPrint(g,x,y,"     HIDDEN SURFACE MODE     r R");
00525    HelpPrint(g,x,y,"     MOVE OBJECT DOWN        u U");
00526    HelpPrint(g,x,y,"     MOVE OBJECT UP          i I");
00527    HelpPrint(g,x,y,"     TOGGLE CONTROLS STYLE   o O");
00528    HelpPrint(g,x,y,"     TOGGLE STEREO DISPLAY   s S");
00529    HelpPrint(g,x,y,"     TOGGLE BLUE STEREO VIEW d D");
00530    HelpPrint(g,x,y,"     TOGGLE DOUBLE BUFFER    f F");
00531    HelpPrint(g,x,y,"     MOVE OBJECT RIGHT       h H");
00532    HelpPrint(g,x,y,"     MOVE OBJECT BACKWARD    j J");
00533    HelpPrint(g,x,y,"     MOVE OBJECT FOREWARD    k K");
00534    HelpPrint(g,x,y,"     MOVE OBJECT LEFT        l L");
00535    HelpPrint(g,x,y,"     TOGGLE HELP MENU        m M");
00536    HelpPrint(g,x,y,"     ROTATE ABOUT X          x X a A");
00537    HelpPrint(g,x,y,"     ROTATE ABOUT Y          y Y b B");
00538    HelpPrint(g,x,y,"     ROTATE ABOUT Z          z Z c C");
00539    HelpPrint(g,x,y,"     AUTOROTATE ABOUT X      1 2 3");
00540    HelpPrint(g,x,y,"     AUTOROTATE ABOUT Y      4 5 6");
00541    HelpPrint(g,x,y,"     AUTOROTATE ABOUT Z      7 8 9");
00542    HelpPrint(g,x,y,"     ADJUST FOCUS            [ ] { }");
00543    HelpPrint(g,x,y,"");
00544    HelpPrint(g,x,y,"  POINTER MOVEMENT WITH LEFT BUTTON :");
00545    HelpPrint(g,x,y,"");
00546    HelpPrint(g,x,y,"     ROTATE OBJECT ABOUT X   Vertical");
00547    HelpPrint(g,x,y,"     ROTATE OBJECT ABOUT Z   Horizontal");
00548 }
00549 
00550 
00551 
00552 static void ResetPurpleRectangle(XL, YL, XH, YH, g)
00553 int XL, YL, XH, YH;
00554 Ginfo *g;
00555 /******************************************************************************
00556    Reset the vertices of the purple rectangle.
00557 ******************************************************************************/
00558 {
00559    g->redSegments[3].x1  = (XL + MARGIN);
00560    g->blueSegments[3].x1 = (XL + MARGIN);
00561    g->redSegments[3].y1  = (YL + MARGIN);
00562    g->blueSegments[3].y1 = (YL + MARGIN);
00563    g->redSegments[3].x2  = (XH - MARGIN);
00564    g->blueSegments[3].x2 = (XH - MARGIN);
00565    g->redSegments[3].y2  = (YL + MARGIN);
00566    g->blueSegments[3].y2 = (YL + MARGIN);
00567    g->redSegments[2].x1  = (XH - MARGIN);
00568    g->blueSegments[2].x1 = (XH - MARGIN);
00569    g->redSegments[2].y1  = (YH - MARGIN);
00570    g->blueSegments[2].y1 = (YH - MARGIN);
00571    g->redSegments[2].x2  = (XL + MARGIN);
00572    g->blueSegments[2].x2 = (XL + MARGIN);
00573    g->redSegments[2].y2  = (YH - MARGIN);
00574    g->blueSegments[2].y2 = (YH - MARGIN);
00575    g->redSegments[1].x1  = (XH - MARGIN);
00576    g->blueSegments[1].x1 = (XH - MARGIN);
00577    g->redSegments[1].y1  = (YL + MARGIN);
00578    g->blueSegments[1].y1 = (YL + MARGIN);
00579    g->redSegments[1].x2  = (XH - MARGIN);
00580    g->blueSegments[1].x2 = (XH - MARGIN);
00581    g->redSegments[1].y2  = (YH - MARGIN);
00582    g->blueSegments[1].y2 = (YH - MARGIN);
00583    g->redSegments[0].x1  = (XL + MARGIN);
00584    g->blueSegments[0].x1 = (XL + MARGIN);
00585    g->redSegments[0].y1  = (YL + MARGIN);
00586    g->blueSegments[0].y1 = (YL + MARGIN);
00587    g->redSegments[0].x2  = (XL + MARGIN);
00588    g->blueSegments[0].x2 = (XL + MARGIN);
00589    g->redSegments[0].y2  = (YH - MARGIN);
00590    g->blueSegments[0].y2 = (YH - MARGIN);
00591 }
00592 
00593 
00594 
00595 static void OneBitSetColors(g)
00596 Ginfo *g;
00597 /******************************************************************************
00598    Set up color information/stipples for a one bit display.
00599 ******************************************************************************/
00600 {
00601 int index1;
00602 Color *color;
00603 int numColors;
00604 
00605    color = g->colors;
00606    numColors = g->numColors;
00607 
00608 /* Set the colors (may not be used) */
00609 
00610    for(index1 = 0; index1 < numColors; index1++){
00611       color[index1].value = 1;
00612 
00613 /* Set the stipples */
00614 
00615       color[index1].stipple =(int)((double)NUMSTIPPLES *
00616       ((double)sqrt((double)(
00617       (double)color[index1].red   * (double)color[index1].red +
00618       (double)color[index1].green * (double)color[index1].green +
00619       (double)color[index1].blue  * (double)color[index1].blue))
00620       / MAXCOLORDIST));
00621       }
00622 }
00623 
00624 
00625 
00626 static void EightBitSetColors(g)
00627 Ginfo *g;
00628 /******************************************************************************
00629    Set up color information/stipples for a eight bit display.
00630 ******************************************************************************/
00631 {
00632 Color *colors1;
00633 int numColors;
00634 int colorIndex = 0;
00635 int index1, index2, redIndex, blueIndex, greenIndex;
00636 XColor c;
00637 
00638    colors1 = g->colors;
00639    numColors = g->numColors;
00640 
00641 /* Put "black" into the place reserved for it in the end */
00642 
00643    colors1[numColors].red   = 0;
00644    colors1[numColors].green = 0;
00645    colors1[numColors].blue  = 0;
00646 
00647 /* Put "red" into the place reserved for it in the end */
00648 
00649    colors1[numColors + 1].red   = 255;
00650    colors1[numColors + 1].green = 0;
00651    colors1[numColors + 1].blue  = 0;
00652 
00653 /* Put "blue" into the place reserved for it in the end */
00654 
00655    colors1[numColors + 2].red   = 0;
00656    colors1[numColors + 2].green = 0;
00657    colors1[numColors + 2].blue  = 255;
00658 
00659 /* Put "purple" into the place reserved for it in the end */
00660 
00661    colors1[numColors + 3].red   = 255;
00662    colors1[numColors + 3].green = 0;
00663    colors1[numColors + 3].blue  = 255;
00664 
00665 /* Blank out the colormap */
00666 
00667    for(index1 = 0; index1 < 256; index1++){
00668       c.red    = 0;
00669       c.green  = 0;
00670       c.blue   = 0;
00671       c.flags  = DoRed | DoGreen | DoBlue;
00672       c.pixel  = 255;
00673       c.pad    = 0;
00674       g->cmapColors[0][index1] = c;
00675       g->cmapColors[1][index1] = c;
00676       g->cmapColors[2][index1] = c;
00677       }
00678 
00679    if(numColors <= BUFFER_CMAP){
00680 
00681       colorIndex= numColors + 3;
00682       index1 = 15;
00683 
00684 /* Set stipple, and colormap double buffer colors */
00685 
00686       while((index1 > 0) && (colorIndex >= 0)){
00687          c.red    = colors1[colorIndex].red   << 8;
00688          c.green  = colors1[colorIndex].green << 8;
00689          c.blue   = colors1[colorIndex].blue  << 8;
00690          c.flags  = DoRed | DoGreen | DoBlue;
00691 
00692          colors1[colorIndex].value = index1 * 16 + index1;
00693 
00694          colors1[colorIndex].stipple =(int)((double)NUMSTIPPLES *
00695          ((double)sqrt((double)(
00696          (double)colors1[colorIndex].red   * (double)colors1[colorIndex].red +
00697          (double)colors1[colorIndex].green * (double)colors1[colorIndex].green +
00698          (double)colors1[colorIndex].blue  * (double)colors1[colorIndex].blue))
00699          / MAXCOLORDIST));
00700 
00701          for(index2 = 1; index2 < 16; index2++){
00702             c.pixel  = index2 * 16 + index1;
00703             g->cmapColors[0][index2 * 16 + index1] = c;
00704 
00705             c.pixel  = index1 * 16 + index2;
00706             g->cmapColors[1][index1 * 16 + index2] = c;
00707             }
00708 
00709          index1--;
00710          colorIndex--;
00711          }
00712    }else{
00713 
00714 /* Set permanent black, red, blue, purple for cmap double buffer */
00715 
00716       for(index1 = 0; index1 < 4; index1++){
00717          c.red    = colors1[numColors + index1].red   << 8;
00718          c.green  = colors1[numColors + index1].green << 8;
00719          c.blue   = colors1[numColors + index1].blue  << 8;
00720          c.flags  = DoRed | DoGreen | DoBlue;
00721          c.pixel  = 12 + index1;
00722          g->cmapColors[0][12 + index1] = c;
00723          g->cmapColors[1][12 + index1] = c;
00724          colors1[numColors + index1].value = c.pixel;
00725          }
00726 
00727       if(numColors <= MAX_COLORS){
00728          colorIndex = 0;
00729          index1 = 9;
00730          index2 = 0;
00731 
00732 /* Fill in the rest of the colors */
00733 
00734          while(colorIndex < numColors){
00735             if((index1 < 12) || (index1 > 15)){
00736                c.red    = colors1[colorIndex].red   << 8;
00737                c.green  = colors1[colorIndex].green << 8;
00738                c.blue   = colors1[colorIndex].blue  << 8;
00739                c.flags  = DoRed | DoGreen | DoBlue;
00740                c.pixel  = index1;
00741                g->cmapColors[0][index1] = c;
00742                g->cmapColors[1][index1] = c;
00743                colors1[colorIndex].value = index1;
00744 
00745                colors1[colorIndex].stipple =(int)((double)NUMSTIPPLES *
00746                ((double)sqrt((double)(
00747                (double)colors1[colorIndex].red *
00748                (double)colors1[colorIndex].red +
00749                (double)colors1[colorIndex].green *
00750                (double)colors1[colorIndex].green +
00751                (double)colors1[colorIndex].blue  *
00752                (double)colors1[colorIndex].blue))
00753                / MAXCOLORDIST));
00754 
00755                colorIndex++;
00756                }
00757             index1++;
00758             }
00759       }else{
00760          index1 = 17;
00761          index2 = 0;
00762          redIndex   = 0;
00763          greenIndex = 0;
00764          blueIndex  = 0;
00765 
00766 /* Otherwise use a default lot */
00767 
00768          while(blueIndex < MAXVALUE){
00769             c.red    = (redIndex * VALUESCALE) << 8;
00770             c.green  = (greenIndex * VALUESCALE) << 8;
00771             c.blue   = (blueIndex * VALUESCALE) << 8;
00772             c.flags  = DoRed | DoGreen | DoBlue;
00773             c.pixel  = index1;
00774             g->cmapColors[0][index1] = c;
00775             g->cmapColors[1][index1] = c;
00776 
00777             redIndex++;
00778 
00779             if(redIndex >= MAXVALUE){
00780                redIndex = 0;
00781                greenIndex++;
00782                }
00783 
00784             if(greenIndex >= MAXVALUE){
00785                greenIndex = 0;
00786                blueIndex++;
00787                }
00788             index1++;
00789             }
00790 
00791          for(index1 = 0; index1 < numColors; index1++){
00792             colors1[index1].value = colors1[index1].red * 36 +
00793                colors1[index1].green * 6 + colors1[index1].blue + 17;
00794 
00795             colors1[colorIndex].stipple =(int)((double)NUMSTIPPLES *
00796             ((double)sqrt((double)(
00797             (double)colors1[colorIndex].red *
00798             (double)colors1[colorIndex].red +
00799             (double)colors1[colorIndex].green *
00800             (double)colors1[colorIndex].green +
00801             (double)colors1[colorIndex].blue  *
00802             (double)colors1[colorIndex].blue))
00803             / MAXCOLORDIST));
00804 
00805             }
00806          }
00807       }
00808 
00809 /* Set the colors for the special fast colormap double buffer */
00810 
00811    index1 = 0;
00812    for(redIndex = 0; redIndex < 4; redIndex++){
00813       for(blueIndex = 0; blueIndex < 4; blueIndex++){
00814           if(redIndex != blueIndex){
00815              g->wireframeColors[0][index1] =
00816                 g->cmapColors[0][(redIndex + 12) * 16 + (blueIndex + 12)];
00817              g->wireframeColors[1][index1] =
00818                 g->cmapColors[1][(redIndex + 12) * 16 + (blueIndex + 12)];
00819              index1++;
00820              }
00821           }
00822       }
00823 
00824 /* Just in case set the rest of the colors */
00825 
00826    for(index1 = 13; index1 < 256; index1++){
00827       g->wireframeColors[0][index1] = g->wireframeColors[0][3];
00828       g->wireframeColors[1][index1] = g->wireframeColors[1][3];
00829       }
00830 
00831 /* Set the colors for the pix stereo mode */
00832 
00833    for(redIndex = 0; redIndex < 15; redIndex++){
00834       for(blueIndex = 0; blueIndex < 15; blueIndex++){
00835          c.red    = (redIndex * 17) << 8;
00836          c.green  = 0;
00837          c.blue   = (blueIndex * 17) << 8;
00838          c.flags  = DoRed | DoGreen | DoBlue;
00839          c.pixel  = (redIndex + 1) * 16 + (blueIndex + 1);
00840          g->cmapColors[2][c.pixel] = c;
00841          }
00842       }
00843 
00844 /* Set stereoColor to nearest color */
00845 
00846    for(index1 = 0; index1 < numColors; index1++){
00847       colorIndex = (int)((double)15 *
00848       ((double)sqrt((double)((double)colors1[index1].red *
00849       (double)colors1[index1].red + (double)colors1[index1].green *
00850       (double)colors1[index1].green + (double)colors1[index1].blue *
00851       (double)colors1[index1].blue)) / MAXCOLORDIST));
00852 
00853       colors1[index1].stereoColor = (colorIndex + 1) * 16 + (colorIndex + 1);
00854       }
00855 
00856 /* Set various important color values */
00857 
00858    g->stereoBlack  = (0 + 1) * 16 + (0 + 1);
00859    g->redMask  = BUFFER0;
00860    g->blueMask = BUFFER1;
00861    g->Black  = colors1[numColors].value;
00862    g->Red    = colors1[numColors + 1].value;
00863    g->Blue   = colors1[numColors + 2].value;
00864    g->Purple = colors1[numColors + 3].value;
00865 }
00866 
00867 
00868 static void TrueColorSetColors(g)
00869 Ginfo *g;
00870 /******************************************************************************
00871    Set up color information/stipples for TrueColor displays.
00872 ******************************************************************************/
00873 {
00874 int index1, colorValue;
00875 Color *colors1;
00876 int numColors;
00877 
00878    /* On TrueColor displays the color pixel value composed directly of
00879       r, g and b components. The order of the r, g and b and the number
00880       of bits used for each color is specified by the X server and decoded
00881       in the gRedShift, gRedDiv etc. values. Since X3D uses 255 as max
00882       color the div is the number of bits to left shift (divide) from 255.
00883    */
00884 
00885    colors1 = g->colors;
00886    numColors = g->numColors;
00887 
00888    for(index1 = 0; index1 < numColors; index1++){
00889 
00890 /* In TrueColor every color is what it is */
00891 
00892       colors1[index1].value =
00893       (colors1[index1].red >>   gRedDiv)   << gRedShift |
00894       (colors1[index1].green >> gGreenDiv) << gGreenShift |
00895       (colors1[index1].blue >>  gBlueDiv)  << gBlueShift;
00896 
00897 /* Set stipple */
00898 
00899       colors1[index1].stipple =(int)((double)NUMSTIPPLES *
00900       ((double)sqrt((double)(
00901       (double)colors1[index1].red   * (double)colors1[index1].red +
00902       (double)colors1[index1].green * (double)colors1[index1].green +
00903       (double)colors1[index1].blue  * (double)colors1[index1].blue))
00904       / MAXCOLORDIST));
00905 
00906 /* Set stereo color */
00907 
00908       colorValue= (int)((double)(255 >> gRedDiv) *
00909       ((double)sqrt((double)((double)colors1[index1].red *
00910       (double)colors1[index1].red + (double)colors1[index1].green *
00911       (double)colors1[index1].green + (double)colors1[index1].blue *
00912       (double)colors1[index1].blue)) / MAXCOLORDIST));
00913 
00914       colors1[index1].stereoColor = (colorValue << gRedShift) |
00915                                   (colorValue << gBlueShift);
00916       }
00917 
00918 /* Set various important color values */
00919 
00920    g->stereoBlack  = 0;
00921    g->redMask  = (255 >> gRedDiv) << gRedShift;
00922    g->blueMask = (255 >> gBlueDiv) << gBlueShift;
00923    g->Black  = 0;
00924    g->Red    = (255 >> gRedDiv) << gRedShift;
00925    g->Blue   = (255 >> gBlueDiv) << gBlueShift;
00926    g->Purple = g->Red | g->Blue;
00927 }
00928 
00929 
00930 char title[80];
00931 Atom wm_protocols[2];
00932 
00933 static void InitDisplay(o, g, parent)
00934 Oinfo *o;
00935 Ginfo *g;
00936 Window parent;
00937 /******************************************************************************
00938    Set up an X window and our colormap.  We rely on X's own error handling and
00939    reporting for most bad X calls because X buffers requests.
00940 ******************************************************************************/
00941 {
00942 static int stipples[NUMSTIPPLES][NUMSTIPPLES * 2 + 1] = {
00943 {0},
00944 {1, 1, 1},
00945 {2, 0, 2, 2, 1},
00946 {3, 1, 0, 1, 2, 3, 1},
00947 {4, 0, 1, 0, 3, 2, 1, 2, 3},
00948 {5, 0, 0, 0, 2, 2, 0, 2, 3, 3, 2},
00949 {6, 0, 2, 1, 1, 1, 3, 2, 0, 3, 1, 3, 3},
00950 {7, 0, 1, 0, 3, 1, 0, 1, 1, 2, 2, 3, 1, 3, 3},
00951 {8, 0, 1, 0, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 0, 3, 2},
00952 {9, 0, 0, 0, 2, 1, 2, 1, 3, 2, 0, 2, 1, 2, 3, 3, 1, 3, 2},
00953 {10,0, 0, 0, 1, 0, 3, 1, 0, 1, 2, 2, 1, 2, 2, 2, 3, 3, 0, 3, 2},
00954 {11,0, 1, 0, 3, 1, 0, 1, 1, 1, 2, 1, 3, 2, 1, 2, 2, 3, 0, 3, 2, 3, 3},
00955 {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},
00956 {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,
00957  3, 3},
00958 {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,
00959  3, 2, 3, 3},
00960 {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,
00961  3, 1, 3, 2, 3, 3},
00962 {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,
00963  3, 0, 3, 1, 3, 2, 3, 3}
00964 };
00965 
00966 char bits[(STIPPLESIZE * STIPPLESIZE) / BITSPERBYTE];
00967 
00968 GC temp_gc;
00969 XColor oldColormap[MAXCOLORS];
00970 XWindowAttributes attributes;
00971 XSetWindowAttributes attribs;
00972 XWMHints wmhint;
00973 int index1, index2, screen;
00974 Visual *vis;
00975 XSizeHints sizehint;
00976 int x, y, NUMCOLORS;
00977 unsigned int width, height, numSegments;
00978 int useroot = 0;
00979 
00980    if (gDisplay)
00981       useroot = 1;
00982 
00983 
00984    numSegments = o->numSegs;
00985 
00986    if((g->redColors = (long *)calloc(1, (numSegments + 4) * (sizeof(long))))
00987     == NULL){
00988 (void)fprintf(stderr, "Unable to allocate memory for redColors\n"); return;}
00989 
00990    if((g->redSegments = (XSegment *)calloc(1, (numSegments + 4) *
00991    (sizeof(XSegment)))) == NULL){
00992 (void)fprintf(stderr, "Unable to allocate memory for redSegments\n"); return;}
00993 
00994    if((g->blueSegments = (XSegment *)calloc(1, (numSegments + 4) *
00995    sizeof(XSegment))) == (XSegment *)NULL){
00996 (void)fprintf(stderr, "Unable to allocate memory for blueSegments\n"); return;}
00997 
00998 /* Can we connect with the server? */
00999 
01000    if (!useroot)
01001       g->dpy = XOpenDisplay(g->DisplayName);
01002    else
01003       g->dpy = gDisplay;
01004    if(g->dpy == NULL){
01005       fprintf(stderr, "Cannot connect to server\n");
01006       return;
01007    }
01008 
01009    screen = DefaultScreen(g->dpy);
01010    g->black =  (long)BlackPixel(g->dpy, screen);
01011    g->white =  (long)WhitePixel(g->dpy, screen);
01012 
01013 /* Initialize various flags and default values */
01014 
01015    g->requestSize = XMaxRequestSize(g->dpy) / REQUESTFACTOR;
01016    g->dpyX = DisplayWidth(g->dpy, screen);
01017    g->dpyY = DisplayHeight(g->dpy, screen);
01018    g->winX = g->dpyX / 2;
01019    g->winY = g->dpyY / 2 /* - 25 */ ;
01020    g->mono = g->ColorSelect = g->oldPointerX = g->oldPointerY = 0;
01021    g->Block = 1;
01022    g->Relative = 0;
01023 
01024 /* Initialize the fonts */
01025 
01026    if((g->font = XLoadQueryFont(g->dpy, FONT)) == NULL){
01027       fprintf(stderr, "Unable to load font: %s ... trying fixed\n", FONT);
01028 
01029       if((g->font = XLoadQueryFont(g->dpy, FIXED)) == NULL){
01030          fprintf(stderr, "Unable to load font: %s\n", FIXED);
01031          return;
01032          }
01033       }
01034 
01035    if((g->titleFont = XLoadQueryFont(g->dpy, TITLEFONT)) == NULL){
01036       fprintf(stderr, "Unable to load font: %s ... trying fixed\n", TITLEFONT);
01037 
01038       if((g->titleFont = XLoadQueryFont(g->dpy, FIXED)) == NULL){
01039          fprintf(stderr, "Unable to load font: %s\n", FIXED);
01040          return;
01041          }
01042       }
01043 
01044    if((g->boldFont = XLoadQueryFont(g->dpy, BOLDFONT)) == NULL){
01045       fprintf(stderr, "Unable to load font: %s ... trying fixed\n", BOLDFONT);
01046 
01047       if((g->boldFont = XLoadQueryFont(g->dpy, FIXED)) == NULL){
01048          fprintf(stderr, "Unable to load font: %s\n", FIXED);
01049          return;
01050          }
01051       }
01052 
01053 /* Which visual do we get? */
01054 
01055    gRedDiv = gGreenDiv = gBlueDiv = gRedShift = gGreenShift = gBlueShift = -1;
01056    g->depth = DefaultDepth(g->dpy, screen);
01057 
01058    vis = DefaultVisual(g->dpy, screen);
01059    if (g->depth > EIGHT && vis->class == TrueColor) {
01060       int i;
01061       for (i = 0; i < (int)sizeof(vis->blue_mask)*8; i++) {
01062          if (gBlueShift == -1 && ((vis->blue_mask >> i) & 1))
01063             gBlueShift = i;
01064          if ((vis->blue_mask >> i) == 1) {
01065             gBlueDiv = 8 - i - 1 + gBlueShift;  /* max value is 255, i.e. 8 bits */
01066             break;
01067          }
01068       }
01069       for (i = 0; i < (int)sizeof(vis->green_mask)*8; i++) {
01070          if (gGreenShift == -1 && ((vis->green_mask >> i) & 1))
01071             gGreenShift = i;
01072          if ((vis->green_mask >> i) == 1) {
01073             gGreenDiv = 8 - i - 1 + gGreenShift;
01074             break;
01075          }
01076       }
01077       for (i = 0; i < (int)sizeof(vis->red_mask)*8; i++) {
01078          if (gRedShift == -1 && ((vis->red_mask >> i) & 1))
01079             gRedShift = i;
01080          if ((vis->red_mask >> i) == 1) {
01081             gRedDiv = 8 - i - 1 + gRedShift;
01082             break;
01083          }
01084       }
01085       /*
01086       printf("gRedDiv = %d, gGreenDiv = %d, gBlueDiv = %d, gRedShift = %d, gGreenShift = %d, gBlueShift = %d\n",
01087              gRedDiv, gGreenDiv, gBlueDiv, gRedShift, gGreenShift, gBlueShift);
01088       */
01089    } else if (g->depth > EIGHT)
01090       g->depth = EIGHT;
01091 
01092    g->pix = XCreatePixmap(g->dpy, RootWindow(g->dpy,screen), g->winX,
01093    g->winY, g->depth);
01094 
01095 /* Everything else we treat as monochrome whether or not
01096    something better may be supported */
01097 
01098 /* Make a vanilla window */
01099 
01100    g->helpWinX =XTextWidth(g->font, LONGESTSTRING, strlen(LONGESTSTRING));
01101    g->helpWinY = FONTHEIGHT(g->font) * HELPLINES;
01102 
01103    g->helpWin = XCreateSimpleWindow(g->dpy, RootWindow(g->dpy, screen), 0, 0,
01104       g->helpWinX, g->helpWinY, 0, 0, 0);
01105 
01106    if (parent)
01107        g->win = XCreateSimpleWindow(g->dpy, parent, 0, 0,
01108                                     g->winX, g->winY, 0, 0, 0);
01109    else
01110        g->win = XCreateSimpleWindow(g->dpy, RootWindow(g->dpy,screen), 0, 0,
01111                                     g->winX, g->winY, 0, 0, 0);
01112 
01113 /* Any user geometry? */
01114 
01115    if(g->Geometry && !useroot){
01116 
01117       x = 0;
01118       y = 0;
01119       width = g->winX;
01120       height = g->winY;
01121       sizehint.flags = USPosition | USSize;
01122 
01123       XParseGeometry(g->Geometry, &x, &y, &width, &height);
01124 
01125       sizehint.x = x;
01126       sizehint.y = y;
01127       sizehint.width  = width;
01128       sizehint.height = height;
01129       g->winX = width;
01130       g->winY = height;
01131 
01132       XResizeWindow(g->dpy, g->win, width, height);
01133       XSetNormalHints(g->dpy, g->win, &sizehint);
01134       }
01135 
01136 /* Set horizontal and vertical ranges */
01137 
01138    g->winH = (int)(g->winX / 2.0);
01139    g->winV = (int)(g->winY / 2.0);
01140 
01141 /* Make our graphics context */
01142 
01143    g->gc = XCreateGC(g->dpy, g->win, 0x0, NULL);
01144    g->helpGc = XCreateGC(g->dpy, g->helpWin, 0x0, NULL);
01145 
01146 /* Create Tiles for monochrome display */
01147 
01148    for(index1 = 0; index1 < NUMSTIPPLES; index1++){
01149       g->stipple[index1]= XCreateBitmapFromData(g->dpy, g->win, bits,
01150       STIPPLESIZE, STIPPLESIZE);
01151       temp_gc = XCreateGC(g->dpy, g->stipple[index1], 0x0, NULL);
01152       XSetForeground(g->dpy, temp_gc, 0);
01153       XFillRectangle(g->dpy, g->stipple[index1], temp_gc, 0, 0, STIPPLESIZE,
01154       STIPPLESIZE);
01155       XSetForeground(g->dpy, temp_gc, 1);
01156       for(index2 = 0; index2 < stipples[index1][0]; index2++){
01157          XDrawPoint(g->dpy, g->stipple[index1], temp_gc,
01158          stipples[index1][index2 * 2 + 1], stipples[index1][index2 * 2 + 2]);
01159          }
01160       XFreeGC(g->dpy, temp_gc);
01161       }
01162 
01163    if (!useroot) {
01164 /* We want to have the input focus if we can */
01165 
01166       XSetInputFocus(g->dpy, PointerRoot, RevertToNone, CurrentTime);
01167 
01168 /*
01169    Thanks go to Otmar Lendl for the following bit of code that
01170    permits the program to work properly with losing window managers
01171    that don't handle input focus correctly.
01172 */
01173 
01174       wmhint.input = True;
01175       wmhint.flags = InputHint;
01176       XSetWMHints(g->dpy,g->win,&wmhint);
01177    }
01178 
01179 /* Please do not do backing store on the contents of our window */
01180 
01181    attribs.backing_store = NotUseful;
01182    XChangeWindowAttributes(g->dpy, g->win, CWBackingStore, &attribs);
01183 
01184 /* We only want certain kinds of events */
01185 
01186    XSelectInput(g->dpy, g->win, ButtonPressMask | ButtonReleaseMask |
01187       KeyPressMask | Button1MotionMask | Button2MotionMask |
01188       StructureNotifyMask | ExposureMask | ColormapChangeMask);
01189 
01190    XSelectInput(g->dpy, g->helpWin, ButtonPressMask | ButtonReleaseMask |
01191       KeyPressMask | Button1MotionMask | Button2MotionMask |
01192       StructureNotifyMask | ExposureMask | ColormapChangeMask);
01193 
01194    if (!useroot) {
01195 /* Do not generate expose events */
01196 
01197       XSetGraphicsExposures(g->dpy, g->gc, 0);
01198 
01199 /* Name our windows */
01200 
01201       XStoreName(g->dpy, g->win, title);
01202       XStoreName(g->dpy, g->helpWin, "ROOT://X3D/Help");
01203 
01204    }
01205 /* Some window managers are not friendly, explicitly set the background color */
01206 
01207    XSetWindowBackground(g->dpy, g->win, g->black);
01208 
01209    if(g->depth == ONE){
01210       OneBitSetColors(g);
01211       }
01212 
01213    if(g->depth > EIGHT){
01214       TrueColorSetColors(g);
01215       }
01216 
01217    if(g->depth == EIGHT){
01218 
01219       NUMCOLORS = 256;
01220 
01221 /* Make our colormap */
01222 
01223       g->colormap = XCreateColormap(g->dpy, g->win, DefaultVisual(g->dpy,
01224       screen), AllocAll);
01225 
01226 /* Get the current colormap */
01227 
01228       XGetWindowAttributes(g->dpy, RootWindow(g->dpy,screen), &attributes);
01229 
01230 /* Since we only use 16 colors, set all our other entries to the old values.
01231    Hopefully some other windows might display in true colors */
01232 
01233       for(index1 = 0; index1 < NUMCOLORS; index1++)
01234          oldColormap[index1].pixel = index1;
01235 
01236       XQueryColors(g->dpy, attributes.colormap, oldColormap, NUMCOLORS);
01237       XStoreColors(g->dpy, g->colormap, oldColormap, NUMCOLORS);
01238 
01239 /* Set up the colormap */
01240 
01241       EightBitSetColors(g);
01242 
01243 /* Set our special 12 colors to something */
01244 
01245       XStoreColors(g->dpy, g->colormap, g->cmapColors[0], 256);
01246       XSetWindowColormap(g->dpy, g->helpWin, g->colormap);
01247       XSetWindowColormap(g->dpy, g->win, g->colormap);
01248    }
01249 
01250 /* Make the purple rectangle */
01251 
01252    ResetPurpleRectangle(0, 0, g->winX, g->winY, g);
01253 
01254 
01255    if (!useroot) {
01256      /*
01257       *   Set up some window manager properties (see the ICCCM).
01258       */
01259 
01260       wm_protocols[0] = XInternAtom (g->dpy, "WM_DELETE_WINDOW", False);
01261       wm_protocols[1] = XInternAtom (g->dpy, "WM_SAVE_YOURSELF", False);
01262       XSetWMProtocols (g->dpy, g->win, wm_protocols, 2);
01263    }
01264 
01265 /*
01266    Make the windows appear.
01267 */
01268    XMapWindow(g->dpy, g->win);
01269    if (!useroot) DisplayMenu(g);
01270 }
01271 
01272 
01273 
01274 static int CheckEvent(Display *display, XEvent *event, char *arg)
01275 /******************************************************************************
01276    Check an event to see if it is one we are interested in.
01277    This is used by X to wake up our program once some interesting event
01278    happens.  Returns: 1 if we are interested, 0 if we are not.
01279 ******************************************************************************/
01280 {
01281    if (display || arg) { } /* use unused arguments */
01282 
01283    if(event == NULL){
01284       fprintf(stderr, "WARNING: Null event in CheckEvent()!!\n");
01285       return 0;
01286    }
01287 
01288    if((event->type == MotionNotify) || (event->type == KeyPress) ||
01289       (event->type == ConfigureNotify) || (event->type == Expose) ||
01290       (event->type == ColormapNotify) || (event->type == ClientMessage))
01291       return 1;
01292 
01293    return 0;
01294 }
01295 
01296 
01297 
01298 static void GetInput(xevent, pointerX, pointerY, command, same, g)
01299 XEvent *xevent;
01300 int *pointerX, *pointerY;
01301 char *command;
01302 int *same;
01303 Ginfo *g;
01304 /******************************************************************************
01305    Get an interesting event and update the user input information.
01306 
01307    The routine will eventually block waiting for an event if block is 1
01308    and the no events of interest have shown up.
01309 ******************************************************************************/
01310 {
01311 XEvent event;
01312 XSizeHints sizehint;
01313 int  numEvents;
01314 char string[TMPSTRLEN];
01315 
01316 /* set command to a meaningless value (hopefully) */
01317 
01318    *command = '\0';
01319 
01320    if (!xevent) {
01321 
01322       do{
01323           string[0] = '\0';
01324 
01325 /* How many events? */
01326 
01327           numEvents = XEventsQueued(g->dpy, QueuedAfterReading);
01328 
01329 /* Block to obtain an event yet? */
01330 
01331           if((numEvents == 0) && (g->Block)){
01332 
01333 /* If the user falls asleep stop using CPU cycles */
01334 
01335              XIfEvent(g->dpy, &event, CheckEvent, NULL);
01336              numEvents = 1;
01337           }else{
01338 
01339 /* If we have at least one event , fetch the first event off the queue*/
01340 
01341              if(numEvents)
01342                 XNextEvent(g->dpy,&event);
01343           }
01344 
01345       }while((numEvents == 0) && (g->Block));
01346 
01347    } else {
01348       event = *xevent;
01349       numEvents = 1;
01350    }
01351 
01352 /* Process the events we have obtained (if any) */
01353 
01354    while(numEvents){
01355 
01356       switch(event.type){
01357 
01358          case MotionNotify    :
01359             if(numEvents == 1){
01360                *pointerX = (int)event.xmotion.x;
01361                *pointerY = (int)event.xmotion.y;
01362             }
01363             break;
01364 
01365          case KeyPress        :
01366             if(numEvents == 1){
01367                XLookupString(&event.xkey,string,TMPSTRLEN,NULL,NULL);
01368                *command = string[0];
01369                }
01370             break;
01371 
01372          case ConfigureNotify :
01373 
01374             if(event.xconfigure.window == g->win){
01375 
01376                g->winX = event.xconfigure.width;
01377                g->winY = event.xconfigure.height;
01378                g->winH = (int)(g->winX / 2.0);
01379                g->winV = (int)(g->winY / 2.0);
01380                ResetPurpleRectangle(0, 0, g->winX, g->winY, g);
01381                sizehint.flags  = USSize | USPosition;
01382                sizehint.width  = g->winX;
01383                sizehint.height = g->winY;
01384                XSetNormalHints(g->dpy, g->win, &sizehint);
01385 
01386 /* Resize our pix etc... */
01387 
01388                XFreePixmap(g->dpy, g->pix);
01389 
01390                g->pix = XCreatePixmap(g->dpy, g->win, g->winX, g->winY,
01391                g->depth);
01392 
01393                }
01394             if(event.xconfigure.window == g->helpWin){
01395                DisplayMenu(g);
01396                }
01397             g->modeChanged = 1;
01398             *same = 0;
01399             break;
01400 
01401          case Expose          :
01402             if(event.xexpose.window == g->helpWin){
01403                DisplayMenu(g);
01404                }
01405             *same = 0;
01406             break;
01407 
01408          case MapNotify       :
01409 
01410             if(event.xmap.window == g->helpWin){
01411 
01412                sizehint.flags = USPosition | USSize;
01413                XSetNormalHints(g->dpy, g->helpWin, &sizehint);
01414 
01415                DisplayMenu(g);
01416                }
01417             g->modeChanged = 1;
01418             *same = 0;
01419             break;
01420 
01421          case ColormapNotify  :
01422 
01423             if(event.xcolormap.colormap == g->colormap){
01424 
01425                if(event.xcolormap.state == ColormapUninstalled){
01426                   g->mono = 1;
01427                }else{
01428                   g->mono = 0;
01429                   }
01430 
01431               g->modeChanged = 1;
01432               *same = 0;
01433               }
01434             break;
01435 
01436          case ClientMessage:
01437               if (event.xclient.data.l[0] == (long)wm_protocols[0])
01438                   /* WM_DELETE_WINDOW */
01439               {
01440               /*
01441                *   XmbufDestroyBuffers( dpy, window );
01442                *   XDestroyWindow (dpy, window);
01443                *   XCloseDisplay( dpy );
01444                */
01445                   quitApplication = 1;
01446               }
01447               else if (event.xclient.data.l[0] == (long)wm_protocols[1])
01448                   /* WM_SAVE_YOURSELF */
01449               {
01450 
01451               }
01452             break;
01453 
01454 
01455          default:
01456             break;
01457          }
01458 
01459          numEvents--;
01460          if(numEvents)
01461             XNextEvent(g->dpy,&event);
01462       }
01463 }
01464 
01465 
01466 float deltaMove = 0;
01467 
01468 static
01469 int UpdatePosition(event, o, g)
01470 XEvent *event;
01471 Oinfo *o;
01472 Ginfo *g;
01473 /******************************************************************************
01474    Update the scene position information using user input.
01475 
01476    The routine will eventually block waiting for an event if block is True
01477    and the no events of interest show up due to the call to GetInput()
01478 ******************************************************************************/
01479 {
01480 int same, pointerX, pointerY, dx, dy;
01481 char command;
01482 double X, Y, Z;
01483 
01484    X = Y = Z = 0.0;
01485 
01486    same = 1;
01487 
01488    pointerX = g->oldPointerX;
01489    pointerY = g->oldPointerY;
01490 
01491    while(same) {
01492 
01493 /* dx, dy, dz are the amount to step about each axis every frame
01494    We want the scene to continue to rotate even if the user does
01495    not give any new input */
01496 
01497 /* Do not forget to put your automatic update variables into this if
01498    statement.  Be careful somehow you can get MANY bugs with these!  */
01499 
01500       if((o->dX) || (o->dY) || (o->dZ)){
01501          same = 0;
01502          g->Block = 0;
01503       }else
01504          g->Block = 1;
01505 
01506 /* Get the input */
01507 
01508       GetInput(event, &pointerX, &pointerY, &command, &same, g);
01509 
01510 /* Fill in code for your favorite keyboard and pointer controls */
01511 
01512 /* My default controls */
01513 
01514 /* Note: I do not move the origin which the scene is rotated about around.
01515    You may want to do oX += ???; oY += ???; oZ += ???    */
01516 
01517       switch(command){
01518          case ' ' : break;
01519 
01520          case 'm' :
01521          case 'M' : same = 0; g->helpMenu    = !g->helpMenu;
01522              /*
01523              if(g->helpMenu == False){
01524                XUnmapWindow(g->dpy, g->helpWin);
01525              }else{
01526                XMapWindow(g->dpy, g->helpWin);
01527              }
01528              */
01529              break;
01530 
01531          case 's' :
01532          case 'S' : same = 0; g->stereo  = !g->stereo; g->modeChanged = 1;
01533              break;
01534 
01535          case 'd' :
01536          case 'D' : same = 0; g->stereoBlue = !g->stereoBlue; g->modeChanged = 1;
01537              break;
01538 
01539          case 'f' :
01540          case 'F' : same = 0; g->buffer = !g->buffer; g->modeChanged = 1;
01541              break;
01542 
01543          case 'o' :
01544          case 'O' : same = 0; g->Relative = !g->Relative; break;
01545 
01546          case 'w' :
01547          case 'W' : same = 0; g->renderMode = WIREFRAME; g->modeChanged = 1;
01548              break;
01549 
01550          case 'e' :
01551          case 'E' : if(o->numPolys) {
01552                       same = 0; g->renderMode = HIDDENLINE; g->modeChanged = 1;
01553                     }
01554              break;
01555 
01556          case 'r' :
01557          case 'R' : if(o->numPolys) {
01558                       same = 0; g->renderMode = SOLID; g->modeChanged = 1;
01559                     }
01560              break;
01561 
01562          case 'l' : same = 0; o->tX  -= deltaMove; break;
01563          case 'j' : same = 0; o->tY  -= deltaMove; break;
01564          case 'k' : same = 0; o->tY  += deltaMove; break;
01565          case 'h' : same = 0; o->tX  += deltaMove; break;
01566          case 'i' : same = 0; o->tZ  += deltaMove; break;
01567          case 'u' : same = 0; o->tZ  -= deltaMove; break;
01568          case 'L' : same = 0; o->tX  -= 5*deltaMove; break;
01569          case 'J' : same = 0; o->tY  -= 5*deltaMove; break;
01570          case 'K' : same = 0; o->tY  += 5*deltaMove; break;
01571          case 'H' : same = 0; o->tX  += 5*deltaMove; break;
01572          case 'I' : same = 0; o->tZ  += 5*deltaMove; break;
01573          case 'U' : same = 0; o->tZ  -= 5*deltaMove; break;
01574          case '1' : same = 0; o->dX += 0.02; break;
01575          case '2' : same = 0; o->dX =  0.0 ; break;
01576          case '3' : same = 0; o->dX -= 0.02; break;
01577          case '4' : same = 0; o->dY -= 0.02; break;
01578          case '5' : same = 0; o->dY =  0.0 ; break;
01579          case '6' : same = 0; o->dY += 0.02; break;
01580          case '7' : same = 0; o->dZ += 0.02; break;
01581          case '8' : same = 0; o->dZ =  0.0 ; break;
01582          case '9' : same = 0; o->dZ -= 0.02; break;
01583          case 'x' : same = 0; X -= 0.03; break;
01584          case 'X' : same = 0; X += 0.03; break;
01585          case 'y' : same = 0; Y += 0.03; break;
01586          case 'Y' : same = 0; Y -= 0.03; break;
01587          case 'z' : same = 0; Z -= 0.03; break;
01588          case 'Z' : same = 0; Z += 0.03; break;
01589          case 'a' : same = 0; X -= 0.05; break;
01590          case 'A' : same = 0; X += 0.05; break;
01591          case 'b' : same = 0; Y += 0.05; break;
01592          case 'B' : same = 0; Y -= 0.05; break;
01593          case 'c' : same = 0; Z -= 0.05; break;
01594          case 'C' : same = 0; Z += 0.05; break;
01595          case '[' : same = 0;
01596                     o->focus += 0.1;
01597                     if((o->focus > 1.8))
01598                        o->focus = 1.8;
01599                     break;
01600          case ']' : same = 0;
01601                     o->focus -= 0.1;
01602                     if((o->focus < -0.8))
01603                        o->focus = -0.8;
01604                     break;
01605          case '{' : same = 0; o->BViewpointX -= 4.0; break;
01606          case '}' : same = 0; o->BViewpointX += 4.0; break;
01607 
01608          case 'q' :
01609          case 'Q' : return(1);
01610 
01611          default : {
01612 
01613 /* My pointer movement stuff */
01614 
01615 /* Only update if the movement was reasonably small */
01616 
01617             dx = pointerX - g->oldPointerX;
01618             dy = pointerY - g->oldPointerY;
01619 
01620             if((dy * dy <= SMALLMOVEMENT) &&
01621                (dx * dx <= SMALLMOVEMENT)){
01622 
01623 /* Rotate proportionally with the amount the pointer moved */
01624 /* Note: I only control the X and Z axes by the pointer */
01625 
01626                X -= (dy * POINTERRATIO);
01627                Z -= (dx * POINTERRATIO);
01628                same = 0;
01629                }
01630 
01631             g->oldPointerY = pointerY;
01632             g->oldPointerX = pointerX;
01633             }
01634          }
01635       }
01636 
01637 /* Keep angles 0 - 6.28 */
01638    X = fmod(X + o->dX, TWOPI);
01639    Y = fmod(Y + o->dY, TWOPI);
01640    Z = fmod(Z + o->dZ, TWOPI);
01641 
01642 /* Fix up the angles */
01643 
01644    if(g->Relative){
01645       o->X = fmod(X + o->X, TWOPI);
01646       o->Y = fmod(Y + o->Y, TWOPI);
01647       o->Z = fmod(Z + o->Z, TWOPI);
01648    }else{
01649       CalculateAngles(&(o->X), &(o->Y), &(o->Z), X, Y, Z);
01650       }
01651 
01652    return quitApplication;
01653 }
01654 
01655 
01656 
01657 static int clipSegment(pX, pY, qX, qY, Pclip, Qclip, H, V)
01658 float *pX, *pY, *qX, *qY;
01659 int Pclip, Qclip;
01660 float H,V;
01661 /******************************************************************************
01662    Calculate the portion of the projected line segment that is visible.
01663 ******************************************************************************/
01664 {
01665 register float PX, PY, QX, QY, dx, dy;
01666 
01667    PX = *pX; QX = *qX;
01668    PY = *pY; QY = *qY;
01669 
01670    dx = QX - PX;
01671    dy = QY - PY;
01672 
01673 /* Clip P first so it will be somewhere on the screen,
01674    if we cannot move P on screen the segment is not visible */
01675 
01676 /* See x3d.h for the meaning of the clipping flags */
01677 
01678    switch(Pclip){
01679 
01680       case 1 :                   /*  00001  */
01681          clipWithTop(PX, PY, dx, dy, V)
01682          if((PX < -H) || (PX > H))
01683             return 0;
01684          break;
01685 
01686       case 2 :                   /*  00010  */
01687          clipWithBottom(PX, PY, dx, dy, V)
01688          if((PX < -H) || (PX > H))
01689             return 0;
01690          break;
01691 
01692       case 4 :                   /*  00100  */
01693          clipWithLeftSide(PX, PY, dx, dy, H)
01694          if((PY < -V) || (PY > V))
01695             return 0;
01696          break;
01697 
01698       case 5 :                   /*  00101  */
01699          clipWithTop(PX, PY, dx, dy, V)
01700          if((PX < -H) || (PX > H)){
01701             clipWithLeftSide(PX, PY, dx, dy, H)
01702             if((PY < -V) || (PY > V))
01703                return 0;
01704             }
01705          break;
01706 
01707       case 6 :                   /*  00110  */
01708          clipWithBottom(PX, PY, dx, dy, V)
01709          if((PX < -H) || (PX > H)){
01710             clipWithLeftSide(PX, PY, dx, dy, H)
01711             if((PY < -V) || (PY > V))
01712                return 0;
01713             }
01714          break;
01715 
01716       case 8 :                   /*  01000  */
01717          clipWithRightSide(PX, PY, dx, dy, H)
01718          if((PY < -V) || (PY > V))
01719             return 0;
01720          break;
01721 
01722       case 9 :                   /*  01001  */
01723          clipWithTop(PX, PY, dx, dy, V)
01724          if((PX < -H) || (PX > H)){
01725             clipWithRightSide(PX, PY, dx, dy, H)
01726             if((PY < -V) || (PY > V))
01727                return 0;
01728             }
01729          break;
01730 
01731       case 10 :                  /*  01010  */
01732          clipWithBottom(PX, PY, dx, dy, V)
01733          if((PX < -H) || (PX > H)){
01734             clipWithRightSide(PX, PY, dx, dy, H)
01735             if((PY < -V) || (PY > V))
01736                return 0;
01737             }
01738          break;
01739 
01740    }
01741 
01742 /* P is now somewhere on screen, calculate where Q should be */
01743 
01744    switch(Qclip){
01745 
01746       case 1 :           /*  00001  */
01747          clipWithTop(QX, QY, dx, dy, V)
01748          break;
01749 
01750       case 2 :           /*  00010  */
01751          clipWithBottom(QX, QY, dx, dy, V)
01752          break;
01753 
01754       case 4 :           /*  00100  */
01755          clipWithLeftSide(QX, QY, dx, dy, H)
01756          break;
01757 
01758       case 5 :           /*  00101  */
01759          clipWithTop(QX, QY, dx, dy, V)
01760          if(QX < -H)
01761             clipWithLeftSide(QX, QY, dx, dy, H)
01762          break;
01763 
01764       case 6 :           /*  00110  */
01765          clipWithBottom(QX, QY, dx, dy, V)
01766          if(QX < -H)
01767             clipWithLeftSide(QX, QY, dx, dy, H)
01768          break;
01769 
01770       case 8 :           /*  01000  */
01771          clipWithRightSide(QX, QY, dx, dy, H)
01772          break;
01773 
01774       case 9 :           /*  01001  */
01775          clipWithTop(QX, QY, dx, dy, V)
01776          if(QX > H)
01777             clipWithRightSide(QX, QY, dx, dy, H)
01778          break;
01779 
01780       case 10 :                  /*  01010  */
01781          clipWithBottom(QX, QY, dx, dy, V)
01782          if(QX > H)
01783             clipWithRightSide(QX, QY, dx, dy, H)
01784          break;
01785 
01786       case 21 :                  /*  10101  */
01787          clipWithTop(QX, QY, dx, dy, V)
01788          if(QX < -H)
01789             clipWithLeftSide(QX, QY, dx, dy, H)
01790          break;
01791 
01792       case 22 :                  /*  10110  */
01793          clipWithBottom(QX, QY, dx, dy, V)
01794          if(QX < -H)
01795             clipWithLeftSide(QX, QY, dx, dy, H)
01796          break;
01797 
01798       case 23 :                  /*  10111  */
01799          if(QY < PY)
01800             clipWithTop(QX, QY, dx, dy, V)
01801          else
01802             clipWithBottom(QX, QY, dx, dy, V)
01803          if(QX < -H)
01804             clipWithLeftSide(QX, QY, dx, dy, H)
01805          break;
01806 
01807       case 25 :                  /*  11001  */
01808          clipWithTop(QX, QY, dx, dy, V)
01809          if(QX > H)
01810             clipWithRightSide(QX, QY, dx, dy, H)
01811          break;
01812 
01813       case 26 :                  /*  11010  */
01814          clipWithBottom(QX, QY, dx, dy, V)
01815          if(QX > H)
01816             clipWithRightSide(QX, QY, dx, dy, H)
01817          break;
01818 
01819       case 27 :                  /*  11011  */
01820          if(QY < PY)
01821             clipWithTop(QX, QY, dx, dy, V)
01822          else
01823             clipWithBottom(QX, QY, dx, dy, V)
01824          if(QX > H)
01825             clipWithRightSide(QX, QY, dx, dy, H)
01826          break;
01827 
01828       case 29 :                  /*  11101  */
01829          if(QX < PX)
01830             clipWithRightSide(QX, QY, dx, dy, H)
01831          else
01832             clipWithLeftSide(QX, QY, dx, dy, H)
01833          if(QY > V)
01834             clipWithTop(QX, QY, dx, dy, V)
01835          break;
01836 
01837       case 30 :                  /*  11110  */
01838          if(QX < PX)
01839             clipWithRightSide(QX, QY, dx, dy, H)
01840          else
01841             clipWithLeftSide(QX, QY, dx, dy, H)
01842          if(QY < -V)
01843             clipWithBottom(QX, QY, dx, dy, V)
01844          break;
01845 
01846       case 31 :                  /*  11111  */
01847          if(QX < PX)
01848             clipWithRightSide(QX, QY, dx, dy, H)
01849          else
01850             clipWithLeftSide(QX, QY, dx, dy, H)
01851 
01852          if((QY < -V) || (QY > V)) {
01853             if(*qY < PY)
01854                clipWithTop(QX, QY, dx, dy, V)
01855             else
01856                clipWithBottom(QX, QY, dx, dy, V)
01857          }
01858          break;
01859 
01860    }
01861 
01862    *pX = PX; *qX = QX;
01863    *pY = PY; *qY = QY;
01864    return 1;
01865 }
01866 
01867 
01868 
01869 static void clip(o, g)
01870 Oinfo *o;
01871 Ginfo *g;
01872 /******************************************************************************
01873    Clip a list of segments.
01874 ******************************************************************************/
01875 {
01876 register int PClipFlags, QClipFlags, Pclip, Qclip, Tclip;
01877 register float H, V;
01878 register short pX, pY, qX, qY;
01879 float PX, PY, QX, QY;
01880 segment *seg, *lastSeg;
01881 point *P, *Q, *T;
01882 XSegment *red, *blue;
01883 long *redCol;
01884 
01885    lastSeg = &(o->segs[o->numSegs]);
01886        seg = o->segs;
01887 
01888    H = (float)g->winH;
01889    V = (float)g->winV;
01890 
01891    red  = &(g->redSegments[g->numberRed]);
01892    redCol = &(g->redColors[g->numRedColors]);
01893 
01894    if((g->mono) || ((g->stereo) && (!(g->stereoBlue))) ||
01895    ((g->renderMode == WIREFRAME) && (!g->stereo))){
01896 
01897       if(o->objClip){
01898 
01899 /* For every segment ... */
01900 
01901          while(seg < lastSeg){
01902 
01903             P = seg->P;
01904             if (P == 0) continue;
01905             PClipFlags = P->ClipFlags;
01906             Q = seg->Q;
01907             if (Q == 0) continue;
01908             QClipFlags = Q->ClipFlags;
01909 
01910 /* Optimization for best case */
01911 
01912             if((PClipFlags | QClipFlags) == 0){
01913                if (seg->color) *redCol = seg->color->value;
01914                else            *redCol = 0;
01915                redCol++;
01916                ((xsegment *)red)->P = P->R;
01917                ((xsegment *)red)->Q = Q->R;
01918                red++;
01919             }else{
01920 
01921 /* Red segments */
01922 
01923 /* Shuffle the bits around so we get the right configuration
01924    for the clipping function */
01925 
01926                Pclip = (PClipFlags & RBmask) | ((PClipFlags & RLeftRight) >> 3);
01927                Qclip = (QClipFlags & RBmask) | ((QClipFlags & RLeftRight) >> 3);
01928 
01929                if((Qclip | Pclip) == 0){
01930 
01931                if (seg->color) *redCol = seg->color->value;
01932                else            *redCol = 0;
01933                redCol++;
01934                red->x1 = P->R.x;
01935                red->y1 = P->R.y;
01936                red->x2 = Q->R.x;
01937                red->y2 = Q->R.y;
01938                red++;
01939 
01940                }else{
01941 
01942                   if((Qclip & Pclip) == 0){
01943 
01944 /* We make P be a point in front of us if there is one in front,
01945    (it simplifies the code) */
01946 
01947                      if((Pclip > Qclip) || (Pclip & Behind)){
01948                         T = P; P = Q; Q = T;
01949                         Tclip = Pclip; Pclip = Qclip; Qclip = Tclip;
01950                         }
01951 
01952                      PX = P->RX - H; PY = -(P->Y - V);
01953                      QX = Q->RX - H; QY = -(Q->Y - V);
01954 
01955                      if(clipSegment(&PX, &PY, &QX, &QY, Pclip, Qclip, H, V)){
01956 
01957                         if (seg->color) *redCol = seg->color->value;
01958                         else            *redCol = 0;
01959                         redCol++;
01960                         red->x1 = (short)(PX + H);
01961                         red->y1 = (short)(V - PY);
01962                         red->x2 = (short)(QX + H);
01963                         red->y2 = (short)(V - QY);
01964                         red++;
01965 
01966                         }
01967                      }
01968                   }
01969                }
01970          seg++;
01971          }
01972       }else{
01973 
01974 /* Optimization for object completely visible */
01975 
01976          if((g->renderMode == WIREFRAME) && (g->stereo)){
01977             while(seg < lastSeg){
01978                   ((xsegment *)red)->P = seg->P->R;
01979                   ((xsegment *)red)->Q = seg->Q->R;
01980                   red++;
01981                   seg++;
01982                }
01983          }else{
01984             while(seg < lastSeg){
01985 
01986                   if (seg->color) *redCol = seg->color->value;
01987                   else            {*redCol = 0; break;}
01988                   redCol++;
01989                   ((xsegment *)red)->P = seg->P->R;
01990                   ((xsegment *)red)->Q = seg->Q->R;
01991                   red++;
01992                   seg++;
01993                }
01994             }
01995          }
01996    }else{
01997       blue = &(g->blueSegments[g->numberBlue]);
01998 
01999       if(o->objClip){
02000          while(seg < lastSeg){
02001 
02002             P = seg->P; Q = seg->Q;
02003             PClipFlags = P->ClipFlags;
02004             QClipFlags = Q->ClipFlags;
02005 
02006 /* Optimization for best case */
02007 
02008             if((PClipFlags | QClipFlags) == 0){
02009 
02010                pX = P->R.x; pY = P->R.y;
02011                qX = Q->R.x; qY = Q->R.y;
02012                red->x1 = pX;
02013                red->y1 = pY;
02014                red->x2 = qX;
02015                red->y2 = qY;
02016                red++;
02017                pX = P->sBX; qX = Q->sBX;
02018                blue->x1 = pX;
02019                blue->y1 = pY;
02020                blue->x2 = qX;
02021                blue->y2 = qY;
02022                blue++;
02023 
02024             }else{
02025 
02026 /* Red segments */
02027 
02028 /* Shuffle the bits around so we get the right configuration
02029    for the clipping function */
02030 
02031                Pclip = (PClipFlags & RBmask) | ((PClipFlags & RLeftRight) >> 3);
02032                Qclip = (QClipFlags & RBmask) | ((QClipFlags & RLeftRight) >> 3);
02033 
02034                if((Qclip | Pclip) == 0){
02035 
02036                red->x1 = P->R.x;
02037                red->y1 = P->R.y;
02038                red->x2 = Q->R.x;
02039                red->y2 = Q->R.y;
02040                red++;
02041 
02042                }else{
02043 
02044                   if((Qclip & Pclip) == 0){
02045 
02046 /* We make P be a point in front of us if there is one in front,
02047    (it simplifies the code) */
02048 
02049                      if((Pclip > Qclip) || (Pclip & Behind)){
02050                         T = P; P = Q; Q = T;
02051                         Tclip = Pclip; Pclip = Qclip; Qclip = Tclip;
02052                         }
02053 
02054                      PX = P->RX - H; PY = -(P->Y - V);
02055                      QX = Q->RX - H; QY = -(Q->Y - V);
02056 
02057                      if(clipSegment(&PX, &PY, &QX, &QY, Pclip, Qclip, H, V)){
02058 
02059                         red->x1 = (short)(PX + H);
02060                         red->y1 = (short)(V - PY);
02061                         red->x2 = (short)(QX + H);
02062                         red->y2 = (short)(V - QY);
02063                         red++;
02064 
02065                         }
02066 
02067                      }
02068                   }
02069 
02070 /* Blue segments */
02071 
02072                PClipFlags = P->ClipFlags;
02073                QClipFlags = Q->ClipFlags;
02074 
02075 /* Shuffle the bits around so we get the right configuration
02076    for the clipping function */
02077 
02078                Pclip = (PClipFlags & Rmask);
02079                Qclip = (QClipFlags & Rmask);
02080 
02081                if((Qclip | Pclip) == 0){
02082 
02083                   blue->x1 = P->sBX;
02084                   blue->y1 = P->R.y;
02085                   blue->x2 = Q->sBX;
02086                   blue->y2 = Q->R.y;
02087                   blue++;
02088 
02089                }else{
02090                   if((Qclip & Pclip) == 0){
02091 
02092 /* We make P be a point in front of us if there is one in front,
02093    (it simplifies the code) */
02094 
02095                      if((Pclip > Qclip) || (Pclip & Behind)){
02096                         T = P; P = Q; Q = T;
02097                         Tclip = Pclip; Pclip = Qclip; Qclip = Tclip;
02098                         }
02099 
02100 /* check the bits, clip if necessary, and add the segment to the
02101    appropriate buffer if visible */
02102 
02103                      PX = P->BX - H; PY = -(P->Y - V);
02104                      QX = Q->BX - H; QY = -(Q->Y - V);
02105 
02106                      if(clipSegment(&PX, &PY, &QX, &QY, Pclip, Qclip, H, V)){
02107 
02108                         blue->x1 = (short)(PX + H);
02109                         blue->y1 = (short)(V - PY);
02110                         blue->x2 = (short)(QX + H);
02111                         blue->y2 = (short)(V - QY);
02112                         blue++;
02113 
02114                         }
02115                      }
02116                   }
02117                }
02118             seg++;
02119          }
02120       }else{
02121 
02122 /* Optimization for object completely visible */
02123 
02124          while(seg < lastSeg){
02125             P = seg->P; Q = seg->Q;
02126             pX = P->R.x; pY = P->R.y;
02127             qX = Q->R.x; qY = Q->R.y;
02128             red->x1 = pX;
02129             red->y1 = pY;
02130             red->x2 = qX;
02131             red->y2 = qY;
02132             red++;
02133             pX = P->sBX; qX = Q->sBX;
02134             blue->x1 = pX;
02135             blue->y1 = pY;
02136             blue->x2 = qX;
02137             blue->y2 = qY;
02138             blue++;
02139             seg++;
02140             }
02141 
02142          }
02143 
02144       g->numberBlue = blue - g->blueSegments;
02145    }
02146 
02147    g->numRedColors = redCol - g->redColors;
02148    g->numberRed = red - g->redSegments;
02149 }
02150 
02151 
02152 #ifdef USE_INTS
02153 
02154 /* The REDROTATE macro does 3 rotates, 2 translates, 1 projection */
02155 
02156 #define REDROTATE                                                         \
02157       r8 = p0->x + c16;                                                   \
02158       r5 = p0->y + c17;                                                   \
02159       r2 = ((r8 * c5 + r5 * c6) >> SHIFT);                                \
02160       r7 = ((r5 * c5 - r8 * c6) >> SHIFT);                                \
02161       r8 = p0->z + c18;                                                   \
02162       r5 = ((r7 * c3 + r8 * c4) >> SHIFT) + c12;                          \
02163       r6 = ((r8 * c3 - r7 * c4) >> SHIFT);                                \
02164       r7 = c7 + ((((r6 * c1 - r2 * c2) >> SHIFT) + c13) * c0) / r5;       \
02165       r8 = c9 - ((((r2 * c1 + r6 * c2) >> SHIFT) + c11) * c0) / r5;       \
02166       r5 = (c0 * 8192) / r5
02167 
02168 /* Project the blue point too */
02169 
02170 #define STEREOROTATE                                                      \
02171       r8 = p0->x + c16;                                                   \
02172       r5 = p0->y + c17;                                                   \
02173       r2 = ((r8 * c5 + r5 * c6) >> SHIFT);                                \
02174       r7 = ((r5 * c5 - r8 * c6) >> SHIFT);                                \
02175       r8 = p0->z + c18;                                                   \
02176       r5 = ((r7 * c3 + r8 * c4) >> SHIFT) + c12;                          \
02177       r6 = ((r8 * c3 - r7 * c4) >> SHIFT);                                \
02178       r7 = c7 + ((((r6 * c1 - r2 * c2) >> SHIFT) + c13) * c0) / r5;       \
02179       r8 = c9 - ((((r2 * c1 + r6 * c2) >> SHIFT) + c11) * c0) / r5;       \
02180       r9 = r8 - c15 - (c0 * c14) / r5;                                    \
02181       r5 = (c0 * 8192) / r5
02182 
02183 #else
02184 
02185 /* The REDROTATE macro does 3 rotates, 2 translates, 1 projection */
02186 
02187 #define REDROTATE                                                         \
02188       r8 = p0->x + c16;                                                   \
02189       r5 = p0->y + c17;                                                   \
02190       r2 = r8 * c5 + r5 * c6;                                             \
02191       r7 = r5 * c5 - r8 * c6;                                             \
02192       r8 = p0->z + c18;                                                   \
02193       r5 = c0 / (r7 * c3 + r8 * c4 + c12);                                \
02194       r6 = r8 *  c3 - r7 * c4;                                            \
02195       r7 = c7 + (r6 * c1 - r2 * c2 + c13) * r5;                           \
02196       r8 = c9 - (r2 * c1 + r6 * c2 + c11) * r5
02197 
02198 #define STEREOROTATE                                                      \
02199       REDROTATE;                                                          \
02200       r9 = r8 - c15 - r5 * c14
02201 
02202 #endif
02203 
02204 
02205 /* Set all the red clipping flags */
02206 
02207 #define REDCLIPFLAGS                                                      \
02208      (r5 > 0) * ALLmask ^ ((r7 < 0) | (r7 > c10) << ClipWithBottom |      \
02209      (r8 > c8) << RClipWithRight    | (r8 <   0) << RClipWithLeft)
02210 
02211 /* Set all the red and blue clipping flags */
02212 
02213 #define STEREOCLIPFLAGS                                                   \
02214      (r5 > 0) * ALLmask ^ ((r7 < 0) | (r7 > c10) << ClipWithBottom |      \
02215      (r8 > c8) << RClipWithRight    | (r8 <   0) << RClipWithLeft  |      \
02216      (r9 > c8) << BClipWithRight    | (r9 <   0) << BClipWithLeft)
02217 
02218 
02219 
02220 static void rotate(o, g)
02221 Oinfo *o;
02222 Ginfo *g;
02223 /******************************************************************************
02224    Rotate, project, and set the clipping flags for a list of points.
02225 ******************************************************************************/
02226 {
02227 register number r2,r5,r6,r7,r8,r9;
02228 register point *p0;
02229 register number c1,c2,c3,c4,c5,c6;
02230 register point  *p1;
02231 register number c0,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16,c17,c18;
02232 register int    objClip;
02233 register short  RX, BX;
02234 
02235    p0 = o->bounds; p1 = &(o->bounds[NUMBOUNDS]); c0 = (number)o->viewpointY;
02236    c1 = (number)(cos(o->Y) * TRIG_ADJ); c2 = (number)(sin(o->Y) * TRIG_ADJ);
02237    c3 = (number)(cos(o->X) * TRIG_ADJ); c4 = (number)(sin(o->X) * TRIG_ADJ);
02238    c5 = (number)(cos(o->Z) * TRIG_ADJ); c6 = (number)(sin(o->Z) * TRIG_ADJ);
02239    c7 = (number)g->winH;              c8 = (number)(2.0 * g->winH);
02240    c9 = (number)g->winV;             c10 = (number)(2.0 * g->winV);
02241   c11 = (number)o->tX;               c12 = (number)(o->tY - o->viewpointY);
02242   c13 = (number)o->tZ;                       c14 = (number)o->BViewpointX;
02243   c15 = (number)(o->BViewpointX * o->focus); c16 = (number)-o->oX;
02244   c17 = (number)-o->oY;                      c18 = (number)-o->oZ;
02245 
02246    objClip = 0;
02247    o->Hmin2 = o->Hmin1; o->Vmin2 = o->Vmin1;
02248    o->Hmax2 = o->Hmax1; o->Vmax2 = o->Vmax1;
02249    o->Hmin1 = o->Hmin; o->Vmin1 = o->Vmin;
02250    o->Hmax1 = o->Hmax; o->Vmax1 = o->Vmax;
02251    o->Hmin = c8; o->Vmin = c10;
02252    o->Hmax =  0; o->Vmax =  0;
02253 
02254 /* What happens to the bounding box? */
02255 
02256    while(p0 != p1){
02257       STEREOROTATE;
02258 
02259       if(STEREOCLIPFLAGS)
02260          objClip = 1;
02261 
02262       if((int)r7 < o->Vmin){ o->Vmin = (int)r7; }
02263       if((int)r7 > o->Vmax){ o->Vmax = (int)r7; }
02264 
02265       if((int)r8 < o->Hmin){ o->Hmin = (int)r8; }
02266       if((int)r8 > o->Hmax){ o->Hmax = (int)r8; }
02267 
02268       if((g->stereo) && (g->stereoBlue)){
02269          if((int)r9 < o->Hmin){ o->Hmin = (int)r9; }
02270          if((int)r9 > o->Hmax){ o->Hmax = (int)r9; }
02271          }
02272 
02273       p0++;
02274       }
02275 
02276 /* Update screen clearing, pix copying variables */
02277 
02278    if((g->modeChanged) || (objClip)){
02279       o->Hmin = o->Hmin1 = o->Hmin2 = 0;
02280       o->Vmin = o->Vmin1 = o->Vmin2 = 0;
02281       o->Hmax = o->Hmax1 = o->Hmax2 = g->winX;
02282       o->Vmax = o->Vmax1 = o->Vmax2 = g->winY;
02283    }else{
02284       if(o->Hmin < 0){o->Hmin = 0;}
02285       if(o->Vmin < 0){o->Vmin = 0;}
02286       if(o->Hmax > c8){o->Hmax = c8;}
02287       if(o->Vmax > c10){o->Vmax = c10;}
02288 
02289       if(o->Hmin1 < o->Hmin2){o->Hmin2 = o->Hmin1;}
02290       if(o->Vmin1 < o->Vmin2){o->Vmin2 = o->Vmin1;}
02291       if(o->Hmax1 > o->Hmax2){o->Hmax2 = o->Hmax1;}
02292       if(o->Vmax1 > o->Vmax2){o->Vmax2 = o->Vmax1;}
02293       }
02294 
02295    o->fillX = o->Hmin2; o->fillY = o->Vmin2;
02296    o->fillWidth  = o->Hmax2 - o->Hmin2 + 1;
02297    o->fillHeight = o->Vmax2 - o->Vmin2 + 1;
02298 
02299    if(o->Hmin < o->Hmin2){o->Hmin2 = o->Hmin;}
02300    if(o->Vmin < o->Vmin2){o->Vmin2 = o->Vmin;}
02301    if(o->Hmax > o->Hmax2){o->Hmax2 = o->Hmax;}
02302    if(o->Vmax > o->Vmax2){o->Vmax2 = o->Vmax;}
02303 
02304    o->copyX = o->Hmin2; o->copyY = o->Vmin2;
02305    o->copyWidth  = o->Hmax2 - o->Hmin2 + 1;
02306    o->copyHeight = o->Vmax2 - o->Vmin2 + 1;
02307 
02308    o->objClip = objClip;
02309    p0 = o->points;
02310    p1 = &(o->points[o->numPoints]);
02311 
02312    if(objClip){
02313 
02314 /* The object is not totally visible, do clipping */
02315 
02316       if((g->stereo) && (g->stereoBlue)){
02317          if(g->renderMode == WIREFRAME){
02318             while(p0 != p1){
02319                STEREOROTATE;
02320                p0->Y  = (float)r7;   p0->R.y = (short)r7;
02321                p0->RX = (float)r8;   p0->R.x = (short)r8;
02322                p0->BX = (float)r9;   p0->sBX = (short)r9;
02323                p0->ClipFlags = STEREOCLIPFLAGS;
02324                p0++;
02325                }
02326          }else{
02327 
02328             while(p0 != p1){
02329                STEREOROTATE;
02330                p0->dist = (float)r5;
02331                p0->Y  = (float)r7;   p0->R.y = (short)r7;
02332                p0->RX = (float)r8;   p0->R.x = (short)r8;
02333                p0->BX = (float)r9;   p0->sBX = (short)r9;
02334                p0->ClipFlags = STEREOCLIPFLAGS;
02335                p0++;
02336                }
02337             }
02338       }else{
02339          if(g->renderMode == WIREFRAME){
02340             while(p0 != p1){
02341                REDROTATE;
02342                p0->Y  = (float)r7;   p0->R.y = (short)r7;
02343                p0->RX = (float)r8;   p0->R.x = (short)r8;
02344                p0->ClipFlags = REDCLIPFLAGS;
02345                p0++;
02346                }
02347          }else{
02348 
02349             while(p0 != p1){
02350                REDROTATE;
02351                p0->dist = (float)r5;
02352                p0->Y  = (float)r7;   p0->R.y = (short)r7;
02353                p0->RX = (float)r8;   p0->R.x = (short)r8;
02354                p0->ClipFlags = REDCLIPFLAGS;
02355                p0++;
02356                }
02357             }
02358          }
02359    }else{
02360 
02361 /* The object is totally visible, skip clipping */
02362 
02363       if((g->stereo) && (g->stereoBlue)){
02364          if(g->renderMode == WIREFRAME){
02365             while(p0 != p1){
02366                STEREOROTATE;
02367                p0->R.y = (short)r7;
02368                p0->R.x = (short)r8;
02369                p0->sBX = (short)r9;
02370                p0++;
02371                }
02372          }else{
02373 
02374             while(p0 != p1){
02375                STEREOROTATE;
02376                p0->dist = (float)r5;
02377                p0->R.y = (short)r7;
02378 
02379                RX = r8;
02380                p0->R.x = (float)RX;
02381 
02382                BX = r9;
02383                p0->sBX = (float)BX;
02384 
02385                p0++;
02386                }
02387             }
02388       }else{
02389          if(g->renderMode == WIREFRAME){
02390             while(p0 != p1){
02391                REDROTATE;
02392                p0->R.y = (short)r7;
02393                p0->R.x = (short)r8;
02394                p0++;
02395                }
02396          }else{
02397 
02398             while(p0 != p1){
02399                REDROTATE;
02400                p0->dist = (float)r5;
02401 
02402                p0->R.y = (short)r7;
02403                RX = (short)r8;
02404                p0->R.x = (float)RX;
02405 
02406                p0++;
02407                }
02408             }
02409          }
02410       }
02411 }
02412 
02413 
02414 
02415 
02416 static void DrawSegments(display, win, gc, segs1, numSegs, g)
02417 Display *display;
02418 Window win;
02419 GC gc;
02420 XSegment segs1[];
02421 int numSegs;
02422 Ginfo *g;
02423 /******************************************************************************
02424    Thanks to Mark Cook for the suggestion to pay attention the the
02425    maximum request size of the X server!
02426 ******************************************************************************/
02427 {
02428 int requestSize, evenAmount, remainder1, index1;
02429 
02430    requestSize = g->requestSize;
02431    evenAmount = (numSegs / requestSize) * requestSize;
02432    remainder1  = numSegs - evenAmount;
02433 
02434    index1 = 0;
02435 
02436    while(index1 < evenAmount){
02437       XDrawSegments(display, win, gc, &segs1[index1], requestSize);
02438       index1 += requestSize;
02439       }
02440 
02441    if(remainder1 > 0)
02442       XDrawSegments(display, win, gc, &segs1[index1], remainder1);
02443 }
02444 
02445 
02446 
02447 static void DrawLines(o, g, mode)
02448 Oinfo *o;
02449 Ginfo *g;
02450 int mode;
02451 /******************************************************************************
02452    Draw lines for the three display modes.
02453 ******************************************************************************/
02454 {
02455 Drawable dest;
02456 long lastColor;
02457 int lastChange, index1;
02458 
02459    dest = g->dest;
02460 
02461    switch(mode){
02462 
02463       case BW:
02464          XSetForeground(g->dpy, g->gc, g->black);
02465          XFillRectangle(g->dpy, dest,  g->gc, o->fillX, o->fillY,
02466          o->fillWidth, o->fillHeight);
02467          XSetForeground(g->dpy, g->gc, g->white);
02468          DrawSegments  (g->dpy, dest,  g->gc, g->redSegments, g->numberRed, g);
02469          break;
02470 
02471       case STEREO:
02472 
02473          XSetForeground(g->dpy, g->gc,  (long)g->Black);
02474          XFillRectangle(g->dpy, dest,  g->gc, o->fillX, o->fillY,
02475          o->fillWidth, o->fillHeight);
02476 
02477          XSetForeground(g->dpy, g->gc, (long)g->Red);
02478          DrawSegments(g->dpy, dest, g->gc, g->redSegments, g->numberRed, g);
02479 
02480          if(g->stereoBlue){
02481 
02482             XSetFunction  (g->dpy, g->gc,  GXor);
02483 
02484             XSetForeground(g->dpy, g->gc,  (long)g->Blue);
02485             DrawSegments(g->dpy, dest, g->gc, g->blueSegments, g->numberBlue,
02486             g);
02487 
02488             XSetFunction (g->dpy, g->gc, GXcopy);
02489             }
02490 
02491          break;
02492 
02493       case COLOR:
02494 
02495          XSetForeground(g->dpy, g->gc, g->Black);
02496          XFillRectangle(g->dpy, dest,  g->gc, o->fillX, o->fillY,
02497          o->fillWidth, o->fillHeight);
02498 
02499          lastChange = 4;
02500          lastColor = g->redColors[lastChange];
02501 
02502          for(index1 = 5; index1 < g->numberRed; index1++){
02503             if(g->redColors[index1] != lastColor){
02504                XSetForeground(g->dpy, g->gc, lastColor);
02505                DrawSegments(g->dpy, dest,  g->gc, &(g->redSegments[lastChange]),
02506                index1 - lastChange, g);
02507                lastChange = index1;
02508                lastColor = g->redColors[lastChange];
02509                }
02510             }
02511 
02512          XSetForeground(g->dpy, g->gc, lastColor);
02513          DrawSegments(g->dpy, dest,  g->gc, &(g->redSegments[lastChange]),
02514          g->numberRed - lastChange, g);
02515 
02516          break;
02517 
02518       default:
02519          break;
02520       }
02521 }
02522 
02523 
02524 
02525 static void DrawHiddenLines(o, g, mode)
02526 Oinfo *o;
02527 Ginfo *g;
02528 int mode;
02529 /******************************************************************************
02530    Draw polygon outlines using painter algorithm for the three display modes.
02531 ******************************************************************************/
02532 {
02533 register int index1, npoints, numPolys;
02534 register polygon *poly, **list1;
02535 register point  **pointPtr, **lastPointPtr;
02536 Drawable dest;
02537 
02538 _XPoint points1[512], *XPointPtr;
02539    void *ptrp = points1;
02540    dest = g->dest;
02541    numPolys = o->numPolys;
02542    list1     = o->list;
02543 
02544    sort(list1, numPolys);
02545 
02546    switch(mode){
02547 
02548       case BW:
02549 
02550          XSetForeground(g->dpy, g->gc, g->black);
02551          XFillRectangle(g->dpy, dest,  g->gc, o->fillX, o->fillY,
02552          o->fillWidth, o->fillHeight);
02553 
02554          for(index1 = 0; index1 < numPolys; index1++){
02555 
02556             poly = list1[index1];
02557             XPointPtr = points1;
02558             npoints      =   poly->numPoints;
02559             pointPtr     =   poly->points;
02560             lastPointPtr = &(poly->points[npoints]);
02561 
02562             while(pointPtr < lastPointPtr){
02563                *XPointPtr = (*pointPtr)->R;
02564                XPointPtr++;
02565                pointPtr++;
02566                }
02567 
02568             XSetForeground(g->dpy, g->gc, g->black);
02569             XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
02570             CoordModeOrigin);
02571             points1[npoints] = points1[0];
02572             XSetForeground(g->dpy, g->gc, g->white);
02573             XDrawLines(g->dpy, dest, g->gc, ptrp, npoints + 1,
02574             CoordModeOrigin);
02575             }
02576 
02577          XSetFillStyle(g->dpy, g->gc, FillSolid);
02578          break;
02579 
02580       case STEREO:
02581 
02582          XSetForeground(g->dpy, g->gc, g->stereoBlack);
02583          XFillRectangle(g->dpy, dest,  g->gc, o->fillX, o->fillY,
02584          o->fillWidth, o->fillHeight);
02585 
02586          XSetPlaneMask(g->dpy, g->gc, g->redMask);
02587 
02588          for(index1 = 0; index1 < numPolys; index1++){
02589             poly = list1[index1];
02590             XPointPtr = points1;
02591             npoints      =   poly->numPoints;
02592             pointPtr     =   poly->points;
02593             lastPointPtr = &(poly->points[npoints]);
02594 
02595             while(pointPtr < lastPointPtr){
02596                *XPointPtr = (*pointPtr)->R;
02597                XPointPtr++;
02598                pointPtr++;
02599                }
02600 
02601             XSetForeground(g->dpy, g->gc, g->stereoBlack);
02602             XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
02603             CoordModeOrigin);
02604             points1[npoints] = points1[0];
02605             XSetForeground(g->dpy, g->gc, poly->color->stereoColor);
02606             XDrawLines(g->dpy, dest, g->gc, ptrp, npoints + 1,
02607             CoordModeOrigin);
02608             }
02609 
02610          if(g->stereoBlue){
02611             XSetPlaneMask(g->dpy, g->gc, g->blueMask);
02612 
02613             for(index1 = 0; index1 < numPolys; index1++){
02614                poly = list1[index1];
02615                XPointPtr = points1;
02616                npoints      =   poly->numPoints;
02617                pointPtr     =   poly->points;
02618                lastPointPtr = &(poly->points[npoints]);
02619 
02620                while(pointPtr < lastPointPtr){
02621                   XPointPtr->x = (*pointPtr)->sBX;
02622                   XPointPtr->y = (*pointPtr)->R.y;
02623                   XPointPtr++;
02624                   pointPtr++;
02625                   }
02626 
02627                XSetForeground(g->dpy, g->gc, g->stereoBlack);
02628                XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
02629                CoordModeOrigin);
02630                points1[npoints] = points1[0];
02631                XSetForeground(g->dpy, g->gc, poly->color->stereoColor);
02632                XDrawLines(g->dpy, dest, g->gc, ptrp, npoints + 1,
02633                CoordModeOrigin);
02634                }
02635             }
02636             XSetPlaneMask(g->dpy, g->gc, AllPlanes);
02637          break;
02638 
02639       case COLOR:
02640 
02641          XSetForeground(g->dpy, g->gc, g->Black);
02642          XFillRectangle(g->dpy, dest,  g->gc, o->fillX, o->fillY,
02643          o->fillWidth, o->fillHeight);
02644 
02645          for(index1 = 0; index1 < numPolys; index1++){
02646             poly = list1[index1];
02647             XPointPtr = points1;
02648             npoints      =   poly->numPoints;
02649             pointPtr     =   poly->points;
02650             lastPointPtr = &(poly->points[npoints]);
02651 
02652             while(pointPtr < lastPointPtr){
02653                *XPointPtr = (*pointPtr)->R;
02654                XPointPtr++;
02655                pointPtr++;
02656                }
02657 
02658             XSetForeground(g->dpy, g->gc, g->Black);
02659             XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
02660             CoordModeOrigin);
02661 
02662             points1[npoints] = points1[0];
02663             XSetForeground(g->dpy, g->gc, poly->color->value);
02664             XDrawLines(g->dpy, dest, g->gc, ptrp, npoints + 1,
02665             CoordModeOrigin);
02666             }
02667 
02668          break;
02669 
02670       default:
02671          break;
02672       }
02673 }
02674 
02675 
02676 
02677 static void DrawPolys(o, g, mode)
02678 Oinfo *o;
02679 Ginfo *g;
02680 int mode;
02681 /******************************************************************************
02682    Draw polygons using painter algorithm for the three display modes.
02683 ******************************************************************************/
02684 {
02685 register int index1, npoints, numPolys;
02686 register polygon *poly, **list1;
02687 register point  **pointPtr, **lastPointPtr;
02688 Drawable dest;
02689 _XPoint points1[512], *XPointPtr;
02690 long lastColor;
02691 
02692    void *ptrp = points1;
02693    dest = g->dest;
02694    numPolys = o->numPolys;
02695    list1     = o->list;
02696 
02697    sort(list1, numPolys);
02698 
02699    switch(mode){
02700 
02701       case BW:
02702 
02703          XSetForeground(g->dpy, g->gc, g->black);
02704          XFillRectangle(g->dpy, dest,  g->gc, o->fillX, o->fillY,
02705          o->fillWidth, o->fillHeight);
02706          XSetForeground(g->dpy, g->gc, g->white);
02707          XSetBackground(g->dpy, g->gc, g->black);
02708          XSetFillStyle(g->dpy, g->gc, FillOpaqueStippled);
02709 
02710          for(index1 = 0; index1 < numPolys; index1++){
02711 
02712             poly = list1[index1];
02713             XPointPtr = points1;
02714             XSetStipple(g->dpy, g->gc, g->stipple[poly->color->stipple]);
02715             npoints      =   poly->numPoints;
02716             pointPtr     =   poly->points;
02717             lastPointPtr = &(poly->points[npoints]);
02718 
02719             while(pointPtr < lastPointPtr){
02720                *XPointPtr = (*pointPtr)->R;
02721                XPointPtr++;
02722                pointPtr++;
02723                }
02724 
02725             XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
02726             CoordModeOrigin);
02727             }
02728 
02729          XSetFillStyle(g->dpy, g->gc, FillSolid);
02730          break;
02731 
02732       case STEREO:
02733 
02734          XSetForeground(g->dpy, g->gc, g->stereoBlack);
02735          XFillRectangle(g->dpy, dest,  g->gc, o->fillX, o->fillY,
02736          o->fillWidth, o->fillHeight);
02737          lastColor = g->stereoBlack;
02738 
02739          XSetPlaneMask(g->dpy, g->gc, g->redMask);
02740 
02741          for(index1 = 0; index1 < numPolys; index1++){
02742             poly = list1[index1];
02743             XPointPtr = points1;
02744             if(poly->color->stereoColor != lastColor){
02745                XSetForeground(g->dpy, g->gc, poly->color->stereoColor);
02746                lastColor = poly->color->stereoColor;
02747                }
02748             npoints      =   poly->numPoints;
02749             pointPtr     =   poly->points;
02750             lastPointPtr = &(poly->points[npoints]);
02751 
02752             while(pointPtr < lastPointPtr){
02753                *XPointPtr = (*pointPtr)->R;
02754                XPointPtr++;
02755                pointPtr++;
02756                }
02757 
02758             XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
02759             CoordModeOrigin);
02760             }
02761 
02762          if(g->stereoBlue){
02763             XSetPlaneMask(g->dpy, g->gc, g->blueMask);
02764 
02765             for(index1 = 0; index1 < numPolys; index1++){
02766                poly = list1[index1];
02767                XPointPtr = points1;
02768                if(poly->color->stereoColor != lastColor){
02769                   XSetForeground(g->dpy, g->gc, poly->color->stereoColor);
02770                   lastColor = poly->color->stereoColor;
02771                   }
02772                npoints      =   poly->numPoints;
02773                pointPtr     =   poly->points;
02774                lastPointPtr = &(poly->points[npoints]);
02775 
02776                while(pointPtr < lastPointPtr){
02777                   XPointPtr->x = (*pointPtr)->sBX;
02778                   XPointPtr->y = (*pointPtr)->R.y;
02779                   XPointPtr++;
02780                   pointPtr++;
02781                   }
02782 
02783                XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
02784                CoordModeOrigin);
02785                }
02786             }
02787             XSetPlaneMask(g->dpy, g->gc, AllPlanes);
02788          break;
02789 
02790       case COLOR:
02791 
02792          XSetForeground(g->dpy, g->gc, g->Black);
02793          XFillRectangle(g->dpy, dest,  g->gc, o->fillX, o->fillY,
02794          o->fillWidth, o->fillHeight);
02795          lastColor = g->Black;
02796 
02797          for(index1 = 0; index1 < numPolys; index1++){
02798             poly = list1[index1];
02799             XPointPtr = points1;
02800             if(poly->color->value != lastColor){
02801                XSetForeground(g->dpy, g->gc, poly->color->value);
02802                lastColor = poly->color->value;
02803                }
02804             npoints      =   poly->numPoints;
02805             pointPtr     =   poly->points;
02806             lastPointPtr = &(poly->points[npoints]);
02807 
02808             while(pointPtr < lastPointPtr){
02809                *XPointPtr = (*pointPtr)->R;
02810                XPointPtr++;
02811                pointPtr++;
02812                }
02813 
02814             XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
02815             CoordModeOrigin);
02816             }
02817 
02818          break;
02819 
02820       default:
02821          break;
02822       }
02823 }
02824 
02825 
02826 
02827 static void BeginImage(Oinfo *o, Ginfo *g)
02828 /******************************************************************************
02829    Prepare to draw some x3d objects.
02830 ******************************************************************************/
02831 {
02832 
02833 /* Try to get rid of a few of the mode change glitches (several exist yet) */
02834    if (o) { }  /* use unused argument */
02835    if(g->modeChanged){
02836       XSetPlaneMask(g->dpy, g->gc, AllPlanes);
02837       if((g->mono) || (g->depth == ONE)){
02838          XSetForeground(g->dpy, g->gc, g->black);
02839       }else{
02840          if(g->stereo){
02841             XSetForeground(g->dpy, g->gc,  (long)g->Black);
02842          }else{
02843             XSetForeground(g->dpy, g->gc, g->Black);
02844             }
02845          }
02846 
02847       XFillRectangle(g->dpy, g->pix,  g->gc, 0, 0, g->winX, g->winY);
02848       XFillRectangle(g->dpy, g->win,  g->gc, 0, 0, g->winX, g->winY);
02849       }
02850 
02851    if(g->buffer){
02852       if((g->mono) || (g->depth != EIGHT)){
02853          g->dest = g->pix;
02854       }else{
02855          if((g->numColors > BUFFER_CMAP) || (((g->renderMode == SOLID) ||
02856          (g->renderMode == HIDDENLINE)) && (g->stereo))){
02857             g->dest = g->pix;
02858          }else{
02859             g->dest = g->win;
02860 
02861             if(g->ColorSelect){
02862                XSetPlaneMask(g->dpy, g->gc, BUFFER1);
02863             }else{
02864                XSetPlaneMask(g->dpy, g->gc, BUFFER0);
02865                }
02866             }
02867          }
02868    }else{
02869       g->dest = g->win;
02870       }
02871 }
02872 
02873 
02874 
02875 static void DrawObject(o, g)
02876 Oinfo *o;
02877 Ginfo *g;
02878 /******************************************************************************
02879    Draw an x3d objext to the screen.  Be sure to draw the objects back to
02880    front when calling this function.
02881 ******************************************************************************/
02882 {
02883 
02884 /* rotate the object */
02885 
02886    rotate(o, g);
02887 
02888 /* Clip against the screen edges */
02889 
02890    clip(o, g);
02891 
02892 /* Draw in the proper render mode */
02893 
02894    switch(g->renderMode){
02895 
02896       case WIREFRAME:
02897          if((g->mono) || (g->depth == ONE)){
02898             DrawLines(o, g, BW);
02899          }else{
02900             if(g->stereo){
02901                DrawLines(o, g, STEREO);
02902             }else{
02903                DrawLines(o, g, COLOR);
02904                }
02905             }
02906          break;
02907 
02908       case HIDDENLINE:
02909          if((g->mono) || (g->depth == ONE)){
02910             DrawHiddenLines(o, g, BW);
02911          }else{
02912             if(g->stereo){
02913                DrawHiddenLines(o, g, STEREO);
02914             }else{
02915                DrawHiddenLines(o, g, COLOR);
02916                }
02917             }
02918          break;
02919 
02920       case SOLID:
02921          if((g->mono) || (g->depth == ONE)){
02922             DrawPolys(o, g, BW);
02923          }else{
02924             if(g->stereo){
02925                DrawPolys(o, g, STEREO);
02926             }else{
02927                DrawPolys(o, g, COLOR);
02928                }
02929             }
02930          break;
02931 
02932       default :
02933          fprintf(stderr, "Unknown Render Mode!\n");
02934          return;
02935          break;
02936       }
02937 
02938 /* Reset the number of lines (We always keep the purple rectangle) */
02939 
02940    g->numberRed  = 4;
02941    g->numberBlue = 4;
02942    g->numRedColors = 4;
02943    g->modeChanged = 0;
02944 }
02945 
02946 
02947 
02948 static void EndImage(o, g)
02949 Oinfo *o;
02950 Ginfo *g;
02951 /******************************************************************************
02952    Finish drawing x3d objects.
02953 ******************************************************************************/
02954 {
02955 
02956 /* Colormap double buffer? */
02957 
02958    if((g->depth == EIGHT) && (!(g->mono)) && (g->numColors <= BUFFER_CMAP) &&
02959    (!((g->stereo) && (g->renderMode == HIDDENLINE))) &&
02960    (!((g->stereo) && (g->renderMode == SOLID)))){
02961       g->ColorSelect = !g->ColorSelect;
02962 
02963       if((g->stereo) && (g->renderMode == WIREFRAME) && (!(g->modeChanged))){
02964          XStoreColors(g->dpy, g->colormap, g->wireframeColors[g->ColorSelect],
02965          12);
02966       }else{
02967          XStoreColors(g->dpy, g->colormap, g->cmapColors[g->ColorSelect], 256);
02968          }
02969    }else{
02970 
02971 /* Stereo solid, wireframe? */
02972 
02973       if(g->depth == EIGHT){
02974          if(((g->renderMode == SOLID) || (g->renderMode == HIDDENLINE))
02975          && (g->stereo)){
02976             XStoreColors(g->dpy, g->colormap, g->cmapColors[2], 256);
02977          }else{
02978             XStoreColors(g->dpy, g->colormap, g->cmapColors[g->ColorSelect],
02979             256);
02980             }
02981          }
02982 
02983 /* generic */
02984 
02985       if(g->buffer){
02986          XCopyArea(g->dpy, g->pix, g->win, g->gc, o->copyX, o->copyY,
02987          o->copyWidth, o->copyHeight, o->copyX, o->copyY);
02988          }
02989       }
02990 
02991    XFlush(g->dpy);
02992 }
02993 
02994 
02995 
02996 
02997 void MakePolygonArray()
02998 /******************************************************************************
02999    Make polygon pointer array
03000 ******************************************************************************/
03001 {
03002 
03003     /*
03004      *  Make polygon pointer array
03005      */
03006 
03007     int index1, index2, i;
03008     point *prevPoint;
03009     segment *tmpSeg;
03010 
03011 
03012     if (gSize3D.numPolys) {
03013          /* sort use the last space as a place holder */
03014         list = (polygon **) calloc(gSize3D.numPolys+1, sizeof(polygon *));
03015         if(!list){
03016             puts("Unable to allocate memory for pointer list !");
03017             return;
03018         }
03019     }
03020     /* This is only for preventing 'Bus error' */
03021     else list = (polygon **) calloc(2, sizeof(polygon *));
03022 
03023     for(i = 0; i < gSize3D.numPolys; i++)
03024         list[i] = &(polys[i]);
03025 
03026 
03027     /*
03028      *  Update more lists
03029      */
03030 
03031     for(index1 = 0; index1 < gSize3D.numPolys; index1++) {
03032 
03033        index2 = 0;
03034 
03035        if((list[index1]->segs[0]->P == list[index1]->segs[1]->P) ||
03036            (list[index1]->segs[0]->P == list[index1]->segs[1]->Q)) {
03037            prevPoint = list[index1]->segs[0]->Q;
03038        }
03039        else{
03040            prevPoint = list[index1]->segs[0]->P;
03041        }
03042 
03043        while(index2 < list[index1]->numSegs){
03044 
03045            tmpSeg = list[index1]->segs[index2];
03046 
03047            if(tmpSeg->P == prevPoint){
03048                prevPoint = tmpSeg->Q;
03049            }
03050            else{
03051                prevPoint = tmpSeg->P;
03052            }
03053 
03054         /*
03055          *  Update points' polygon lists
03056          */
03057 
03058            if(prevPoint->numPolys == 0){
03059                if((prevPoint->polys = (polygon **)calloc(1, sizeof(polygon *)))== NULL){
03060                    puts("Unable to allocate memory for point polygons !");
03061                    return;
03062                }
03063            }
03064            else {
03065                if((prevPoint->polys = (polygon **)realloc(prevPoint->polys,
03066                    (prevPoint->numPolys + 1) * sizeof(polygon *))) == NULL){
03067                    puts("Unable to allocate memory for point polygons !");
03068                    return;
03069                }
03070            }
03071            prevPoint->polys[prevPoint->numPolys] = &(polys[index1]);
03072            prevPoint->numPolys++;
03073 
03074         /*
03075          *  Update polygons' point lists
03076          */
03077 
03078            if(polys[index1].numPoints == 0){
03079                if((polys[index1].points = (point **)calloc(1, sizeof(point *)))== NULL){
03080                    puts("Unable to allocate memory for polygon points !");
03081                    return;
03082                }
03083            }
03084            else {
03085                if((polys[index1].points = (point **) realloc(
03086                    polys[index1].points, (polys[index1].numPoints + 1) *
03087                    sizeof(point *))) == NULL){
03088                    puts("Unable to allocate memory for point polygons !");
03089                    return;
03090                }
03091            }
03092 
03093            polys[index1].points[polys[index1].numPoints] = prevPoint;
03094            polys[index1].numPoints++;
03095 
03096            index2++;
03097        }
03098     }
03099 }
03100 
03101 
03102 /*****************************************************************************
03103 *                                                                            *
03104 * main procedure                                                             *
03105 *                                                                            *
03106 ******************************************************************************/
03107 unsigned long
03108 x3d_main(longitude, latitude, psi, string, parent)
03109 float   *longitude;
03110 float   *latitude;
03111 float   *psi;
03112 char    *string;
03113 Window   parent;
03114 {
03115     Ginfo *g = NULL;
03116     Oinfo *o = NULL;
03117     int i, j;
03118     FILE *fp;
03119     int export = 0;
03120     char filename[80], *indx;
03121 
03122     float xMin, yMin, zMin, xMax, yMax, zMax, correctionFactor;
03123     float xCenter, yCenter, zCenter;
03124     float xRange, zRange;
03125 
03126     quitApplication = 0;
03127 
03128     if((o = (Oinfo *) calloc(1, sizeof(Oinfo))) == NULL){
03129        (void) fprintf(stderr, "Unable to allocate memory for Object\n");
03130        return 0L;
03131     }
03132     gOInfo = o;
03133 
03134     if((g = (Ginfo *) calloc(1, sizeof(Ginfo))) == NULL){
03135        (void) fprintf(stderr, "Unable to allocate memory for Ginfo\n");
03136        return 0L;
03137     }
03138     gGInfo = g;
03139 
03140     indx = NULL;
03141     strcpy(title, "ROOT://X3D");
03142 
03143 /*
03144  *  Print help
03145  */
03146     if (!strcmp(string, "help")) {
03147                 puts("**** x3d QUICK HELP **************************************\n");
03148         puts(" QUIT                    q Q     MOVE OBJECT DOWN      u U" );
03149         puts(" TOGGLE CONTROLS STYLE   o O     MOVE OBJECT UP        i I" );
03150         puts(" TOGGLE STEREO DISPLAY   s S     MOVE OBJECT RIGHT     h H" );
03151         puts(" TOGGLE BLUE STEREO VIEW d D     MOVE OBJECT BACKWARD  j J" );
03152         puts(" TOGGLE DOUBLE BUFFER    f F     MOVE OBJECT FOREWARD  k K" );
03153         puts(" TOGGLE HELP MENU        m M     MOVE OBJECT LEFT      l L" );
03154         puts(" ROTATE ABOUT X      x X a A     AUTOROTATE ABOUT X  1 2 3" );
03155         puts(" ROTATE ABOUT Y      y Y b B     AUTOROTATE ABOUT Y  4 5 6" );
03156         puts(" ROTATE ABOUT Z      z Z c C     AUTOROTATE ABOUT Z  7 8 9\n");
03157         puts(" ADJUST FOCUS        [ ] { }     HIDDEN LINE MODE      e E" );
03158         puts(" WIREFRAME MODE          w W     HIDDEN SURFACE MODE   r R\n");
03159         puts(" POINTER MOVEMENT WITH LEFT BUTTON :\n");
03160         puts(" ROTATE OBJECT ABOUT X   Vertical" );
03161         puts(" ROTATE OBJECT ABOUT Z   Horizontal\n");
03162 
03163         return 0L;
03164         }
03165         else if ((indx = (char *) strstr(string, "hull:")) != NULL) {
03166             strcpy (filename, indx + 5);
03167             if (strlen(filename)) export = 1;
03168     }
03169         else if ((indx = (char *) strstr(string, "java:")) != NULL) {
03170             strcpy (filename, indx + 5);
03171             if (strlen(filename)) export = 2;
03172     }
03173         else if (string) {
03174             strcat(title, "/");
03175             strcat(title, string);
03176         }
03177 
03178     switch( export ) {
03179         case 1: /* hull */
03180 
03181             if (gSize3D.numPolys) {
03182                 fp = fopen (filename, "w");
03183                 if (fp != NULL) {
03184                     for (i = 0; i < gSize3D.numPolys; i++) {
03185                         fprintf (fp, "\n# polygon No. %d color ( R G B )\n", i);
03186                         fprintf (fp, "%5d%5d%5d\n\n", polys[i].color->red, polys[i].color->green, polys[i].color->blue);
03187                         for (j = 0; j < polys[i].numSegs; j++) {
03188                             fprintf (fp, "%20.6f%20.6f%20.6f\n", polys[i].segs[j]->P->x, polys[i].segs[j]->P->y, polys[i].segs[j]->P->z);
03189                         }
03190                     }
03191                     fclose (fp);
03192                 }
03193             }
03194             else puts ("Can't export (number of polygons=0)");
03195             break;
03196 
03197         case 2: /* java */
03198 
03199             if( gSize3D.numSegs ) {
03200                 fp = fopen( filename, "w" );
03201                 if( fp != NULL ) {
03202                     for( i = 0; i < gSize3D.numSegs; i++ ) {
03203                         fprintf( fp, "v %20.6f%20.6f%20.6f\n", segs[i].P->x, segs[i].P->y, segs[i].P->z);
03204                         fprintf( fp, "v %20.6f%20.6f%20.6f\n", segs[i].Q->x, segs[i].Q->y, segs[i].Q->z);
03205                         fprintf( fp, "l %6d%6d\n", i*2+1, i*2+2 );
03206                     }
03207                     fclose (fp);
03208                 }
03209             }
03210             break;
03211 
03212         default:
03213             break;
03214     }
03215 
03216 /*
03217  *  Try to find the boundaries of the object
03218  */
03219 
03220     xMin = yMin = zMin =  999999;
03221     xMax = yMax = zMax = -999999;
03222 
03223         for (i = 0; i < gSize3D.numPoints; i++) {
03224             xMin = xMin <= points[i].x ? xMin : points[i].x;
03225             xMax = xMax >= points[i].x ? xMax : points[i].x;
03226 
03227             yMin = yMin <= points[i].y ? yMin : points[i].y;
03228             yMax = yMax >= points[i].y ? yMax : points[i].y;
03229 
03230             zMin = zMin <= points[i].z ? zMin : points[i].z;
03231             zMax = zMax >= points[i].z ? zMax : points[i].z;
03232         }
03233 
03234 /*
03235  *  Compute the range & center of the object
03236  */
03237 
03238     xRange  = fabs(xMax - xMin);
03239     zRange  = fabs(zMax - zMin);
03240 
03241     xCenter = (xMax + xMin) / 2.0;
03242     yCenter = (yMax + yMin) / 2.0;
03243     zCenter = (zMax + zMin) / 2.0;
03244 
03245 /*
03246  *  Compute the correctionFactor, rescale & put the object in the center
03247  */
03248         correctionFactor = 6000.0 / (xRange > zRange ? xRange : zRange);
03249 
03250         for (i = 0; i < gSize3D.numPoints; i++) {
03251             points[i].x = (points[i].x - xCenter) * correctionFactor;
03252             points[i].y = (points[i].y - yCenter) * correctionFactor;
03253             points[i].z = (points[i].z - zCenter) * correctionFactor;
03254         }
03255 
03256         deltaMove = (float) (xRange >= zRange ? xRange : zRange) / 20.0 * correctionFactor;
03257 
03258 /*
03259  *  Calculate the bounding cube
03260  */
03261 
03262     bounds = NULL;
03263     bounds = (point *) calloc(8, sizeof(point));
03264 
03265     if (!bounds)
03266         (void) fprintf(stderr, "Unable to allocate memory for bounding cube.\n");
03267 
03268     xMin = (xMin - xCenter) * correctionFactor;
03269     xMax = (xMax - xCenter) * correctionFactor;
03270     yMin = (yMin - yCenter) * correctionFactor;
03271     yMax = (yMax - yCenter) * correctionFactor;
03272     zMin = (zMin - zCenter) * correctionFactor;
03273     zMax = (zMax - zCenter) * correctionFactor;
03274 
03275     if (bounds) {
03276         bounds[0].x = xMin; bounds[0].y = yMin; bounds[0].z = zMin;
03277         bounds[1].x = xMin; bounds[1].y = yMin; bounds[1].z = zMax;
03278         bounds[2].x = xMin; bounds[2].y = yMax; bounds[2].z = zMin;
03279         bounds[3].x = xMin; bounds[3].y = yMax; bounds[3].z = zMax;
03280         bounds[4].x = xMax; bounds[4].y = yMin; bounds[4].z = zMin;
03281         bounds[5].x = xMax; bounds[5].y = yMin; bounds[5].z = zMax;
03282         bounds[6].x = xMax; bounds[6].y = yMax; bounds[6].z = zMin;
03283         bounds[7].x = xMax; bounds[7].y = yMax; bounds[7].z = zMax;
03284     }
03285 
03286 /*
03287  *  Make polygon pointer array
03288  */
03289 
03290     MakePolygonArray();
03291 
03292     g->Geometry    = "800x600";
03293     g->DisplayName = NULL;
03294     g->renderMode  = WIREFRAME;
03295     g->buffer      = 1;
03296     g->mono        = 0;
03297     g->stereo      = 0;
03298     g->stereoBlue  = 1;
03299     g->colors      = colors;
03300     g->numColors   = 28;
03301     g->win         = 0;
03302     o->points      = points;
03303     o->numPoints   = gSize3D.numPoints;
03304     o->segs        = segs;
03305     o->numSegs     = gSize3D.numSegs;
03306     o->polys       = polys;
03307     o->numPolys    = gSize3D.numPolys;
03308     o->list        = list;
03309     o->bounds      = bounds;
03310 
03311 
03312     if (!export && bounds) {
03313 
03314     /* Define viewing parameters */
03315 
03316        o->BViewpointX = 100.0;                   /* stereo separation factor */
03317        o->viewpointY  = -650.0;                  /* view point               */
03318        o->tX          = 640.0;                   /* observer X coordinate    */
03319        o->tY          = 6000.0;                  /* observer Y coordinate    */
03320        o->tZ          = 490.0;                   /* observer Z coordinate    */
03321        o->oX          = 0.0;                     /* origin X coordinate      */
03322        o->oY          = 0.0;                     /* origin Y coordinate      */
03323        o->oZ          = 0.0;                     /* origin Z coordinate      */
03324        o->X           = (double) (*latitude);    /* rotate angle around X    */
03325        o->Y           = (double) (*psi);         /* rotate angle around Y    */
03326        o->Z           = (double) (*longitude);   /* rotate angle around Z    */
03327        o->dX          = 0.0;                     /* autorotate around X      */
03328        o->dY          = 0.0;                     /* autorotate around Y      */
03329        o->dZ          = 0.0;                     /* autorotate around Z      */
03330        o->focus       = 0.2;
03331 
03332 
03333     /* Initialize the display */
03334 
03335 
03336        InitDisplay(o, g, parent);
03337 
03338        return g->win;
03339     }
03340     return 0;
03341 }
03342 
03343 void x3d_update()
03344 {
03345    Ginfo *g = gGInfo;
03346    Oinfo *o = gOInfo;
03347 
03348    BeginImage(o, g);
03349    DrawObject(o, g);
03350    EndImage(o, g);
03351 }
03352 
03353 int x3d_dispatch_event(unsigned long evnt)
03354 {
03355 
03356    XEvent *event = (XEvent *)evnt;
03357    Ginfo *g = gGInfo;
03358    Oinfo *o = gOInfo;
03359 
03360    UpdatePosition(event, o, g);
03361 
03362    x3d_update();
03363 
03364    return 1;
03365 }
03366 
03367 void x3d_get_position(float *longitude, float *latitude, float *psi)
03368 {
03369    Oinfo *o = gOInfo;
03370 
03371    /* Update longitude and latitude */
03372    *latitude  =  (float) (o->X);
03373    *psi       =  (float) (o->Y);
03374    *longitude =  (float) (o->Z);
03375 }
03376 
03377 void x3d_terminate()
03378 {
03379    int i;
03380    Ginfo *g = gGInfo;
03381    Oinfo *o = gOInfo;
03382 
03383    if (g->win) {
03384     /* Destroy windows */
03385        XDestroyWindow(g->dpy, g->win);
03386        XDestroyWindow(g->dpy, g->helpWin);
03387 
03388     /* Destroy graphics contexts */
03389        XFreeGC(g->dpy, g->gc);
03390        XFreeGC(g->dpy, g->helpGc);
03391 
03392     /* Free pixmap */
03393        XFreePixmap(g->dpy, g->pix);
03394 
03395     /* Close display */
03396 
03397        if (!gDisplay) {
03398           XSetCloseDownMode(g->dpy, DestroyAll);
03399           XCloseDisplay(g->dpy);
03400        }
03401 
03402     /* Free allocated memory */
03403        if (g->redColors)    free (g->redColors);
03404        if (g->redSegments)  free (g->redSegments);
03405        if (g->blueSegments) free (g->blueSegments);
03406        if (o)               free (o);
03407        if (g)               free (g);
03408 
03409     }
03410 
03411 /*
03412  *  Free allocated memory & reset counters
03413  */
03414     currPoint = currSeg = currPoly = 0;
03415 
03416     for (i = 0; i < gSize3D.numPolys; i++) {
03417 /*
03418  *       for (j = 0; j < polys[i].numPoints; j++) {
03419  *           if (polys[i].points[j]->polys)
03420  *               free (polys[i].points[j]->polys);
03421  *       }
03422  */
03423         if (polys[i].points) free (polys[i].points);
03424     }
03425 
03426     for (i = 0; i < gSize3D.numSegs; i++)
03427         if (segs[i].polys) free (segs[i].polys);
03428 
03429     for (i = 0; i < gSize3D.numPoints; i++)
03430         if (points[i].segs) free (points[i].segs);
03431 
03432     if (points) free (points);
03433     if (colors) free (colors);
03434     if (segs)   free (segs);
03435     if (polys)  free (polys);
03436     if (list)   free (list);
03437     if (bounds) free (bounds);
03438 }
03439 
03440 void x3d_set_display(unsigned long disp)
03441 {
03442    gDisplay = (Display*) disp;
03443 }
03444 
03445 int x3d_exec_command(int pointerX, int pointerY, char command)
03446 /******************************************************************************
03447    Update the scene position information using user input.
03448 
03449    The routine will eventually block waiting for an event if block is True
03450    and the no events of interest show up due to the call to GetInput()
03451 ******************************************************************************/
03452 {
03453 int same, dx, dy;
03454 double X, Y, Z;
03455 
03456    Ginfo *g = gGInfo;
03457    Oinfo *o = gOInfo;
03458 
03459    X = Y = Z = 0.0;
03460 
03461    same = 1;
03462 
03463 /* dx, dy, dz are the amount to step about each axis every frame
03464    We want the scene to continue to rotate even if the user does
03465    not give any new input */
03466 
03467 /* Do not forget to put your automatic update variables into this if
03468    statement.  Be careful somehow you can get MANY bugs with these!  */
03469 
03470       g->Block = 1;
03471 
03472 /* Note: I do not move the origin which the scene is rotated about around.
03473    You may want to do oX += ???; oY += ???; oZ += ???    */
03474 
03475       switch(command){
03476          case ' ' : break;
03477 
03478          case 'm' :
03479          case 'M' : same = 0; g->helpMenu    = !g->helpMenu;
03480              /*
03481              if(g->helpMenu == False){
03482                XUnmapWindow(g->dpy, g->helpWin);
03483              }else{
03484                XMapWindow(g->dpy, g->helpWin);
03485              }
03486              */
03487              break;
03488 
03489          case 's' :
03490          case 'S' : same = 0; g->stereo  = !g->stereo; g->modeChanged = 1;
03491              break;
03492 
03493          case 'd' :
03494          case 'D' : same = 0; g->stereoBlue = !g->stereoBlue; g->modeChanged = 1;
03495              break;
03496 
03497          case 'f' :
03498          case 'F' : same = 0; g->buffer = !g->buffer; g->modeChanged = 1;
03499              break;
03500 
03501          case 'o' :
03502          case 'O' : same = 0; g->Relative = !g->Relative; break;
03503 
03504          case 'w' :
03505          case 'W' : same = 0; g->renderMode = WIREFRAME; g->modeChanged = 1;
03506              break;
03507 
03508          case 'e' :
03509          case 'E' : if(o->numPolys) {
03510                       same = 0; g->renderMode = HIDDENLINE; g->modeChanged = 1;
03511                     }
03512              break;
03513 
03514          case 'r' :
03515          case 'R' : if(o->numPolys) {
03516                       same = 0; g->renderMode = SOLID; g->modeChanged = 1;
03517                     }
03518              break;
03519 
03520          case 'l' : same = 0; o->tX  -= deltaMove; break;
03521          case 'j' : same = 0; o->tY  -= deltaMove; break;
03522          case 'k' : same = 0; o->tY  += deltaMove; break;
03523          case 'h' : same = 0; o->tX  += deltaMove; break;
03524          case 'i' : same = 0; o->tZ  += deltaMove; break;
03525          case 'u' : same = 0; o->tZ  -= deltaMove; break;
03526          case 'L' : same = 0; o->tX  -= 5*deltaMove; break;
03527          case 'J' : same = 0; o->tY  -= 5*deltaMove; break;
03528          case 'K' : same = 0; o->tY  += 5*deltaMove; break;
03529          case 'H' : same = 0; o->tX  += 5*deltaMove; break;
03530          case 'I' : same = 0; o->tZ  += 5*deltaMove; break;
03531          case 'U' : same = 0; o->tZ  -= 5*deltaMove; break;
03532          case '1' : same = 0; o->dX += 0.02; break;
03533          case '2' : same = 0; o->dX =  0.0 ; break;
03534          case '3' : same = 0; o->dX -= 0.02; break;
03535          case '4' : same = 0; o->dY -= 0.02; break;
03536          case '5' : same = 0; o->dY =  0.0 ; break;
03537          case '6' : same = 0; o->dY += 0.02; break;
03538          case '7' : same = 0; o->dZ += 0.02; break;
03539          case '8' : same = 0; o->dZ =  0.0 ; break;
03540          case '9' : same = 0; o->dZ -= 0.02; break;
03541          case 'x' : same = 0; X -= 0.03; break;
03542          case 'X' : same = 0; X += 0.03; break;
03543          case 'y' : same = 0; Y += 0.03; break;
03544          case 'Y' : same = 0; Y -= 0.03; break;
03545          case 'z' : same = 0; Z -= 0.03; break;
03546          case 'Z' : same = 0; Z += 0.03; break;
03547          case 'a' : same = 0; X -= 0.05; break;
03548          case 'A' : same = 0; X += 0.05; break;
03549          case 'b' : same = 0; Y += 0.05; break;
03550          case 'B' : same = 0; Y -= 0.05; break;
03551          case 'c' : same = 0; Z -= 0.05; break;
03552          case 'C' : same = 0; Z += 0.05; break;
03553          case '[' : same = 0;
03554                     o->focus += 0.1;
03555                     if((o->focus > 1.8))
03556                        o->focus = 1.8;
03557                     break;
03558          case ']' : same = 0;
03559                     o->focus -= 0.1;
03560                     if((o->focus < -0.8))
03561                        o->focus = -0.8;
03562                     break;
03563          case '{' : same = 0; o->BViewpointX -= 4.0; break;
03564          case '}' : same = 0; o->BViewpointX += 4.0; break;
03565 
03566          case 'q' :
03567          case 'Q' : return(1);
03568 
03569          default : {
03570 
03571 /* My pointer movement stuff */
03572 
03573 /* Only update if the movement was reasonably small */
03574 
03575             dx = pointerX - g->oldPointerX;
03576             dy = pointerY - g->oldPointerY;
03577 
03578             if((dy * dy <= SMALLMOVEMENT) &&
03579                (dx * dx <= SMALLMOVEMENT)){
03580 
03581 /* Rotate proportionally with the amount the pointer moved */
03582 /* Note: I only control the X and Z axes by the pointer */
03583 
03584                X -= (dy * POINTERRATIO);
03585                Z -= (dx * POINTERRATIO);
03586                same = 0;
03587             }
03588             g->oldPointerY = pointerY;
03589             g->oldPointerX = pointerX;
03590          }
03591       }
03592 /*      } */
03593 
03594 /* Keep angles 0 - 6.28 */
03595 
03596    X = fmod(X + o->dX, TWOPI);
03597    Y = fmod(Y + o->dY, TWOPI);
03598    Z = fmod(Z + o->dZ, TWOPI);
03599 
03600 /* Fix up the angles */
03601 
03602    if(g->Relative){
03603       o->X = fmod(X + o->X, TWOPI);
03604       o->Y = fmod(Y + o->Y, TWOPI);
03605       o->Z = fmod(Z + o->Z, TWOPI);
03606    }else{
03607       CalculateAngles(&(o->X), &(o->Y), &(o->Z), X, Y, Z);
03608    }
03609 
03610    x3d_update();
03611 
03612    return quitApplication;
03613 }
03614 
03615 #endif

Generated on Tue Jul 5 14:19:18 2011 for ROOT_528-00b_version by  doxygen 1.5.1