Logo ROOT  
Reference Guide
x3d.c
Go to the documentation of this file.
1/* @(#)root/x3d:$Id$ */
2/* Author: Mark Spychalla*/
3/*
4 Copyright 1992 Mark Spychalla
5
6 Permission to use, copy, modify, distribute, and sell this software and
7 its documentation for any purpose is hereby granted without fee,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation, and that the name of Mark Spychalla not be used
11 in advertising or publicity pertaining to distribution of the software
12 without specific, written prior permission. Mark Spychalla makes no
13 representations about the suitability of this software for any purpose.
14 It is provided "as is" without express or implied warranty.
15
16 Mark Spychalla disclaims all warranties with regard to this software,
17 including all implied warranties of merchantability and fitness, in no
18 event shall Mark Spychalla be liable for any special, indirect or
19 consequential damages or any damages whatsoever resulting from loss of use,
20 data or profits, whether in an action of contract, negligence or other
21 tortious action, arising out of or in connection with the use or performance
22 of this software.
23*/
24
25
26
27/*
28
29NOTE ON X3D CODING STYLE:
30
31 Don't think I usually code in the gerberized fashion that X3D demonstrates.
32X3D was written for speed at any cost. My goal was to write the fastest 3D
33object viewer that I could, period. Regular programs ought to be written
34with different goals in mind such as:
35
361) A program has excellent documentation that ANYONE can read.
372) A program when released has no strange "features" or bugs.
383) A program is robust and handles ALL extreme and unusual cases.
394) A program is written in phases and modules with hard tests for each one.
405) A program is written for any user who doesn't need special knowledge
41 to use the program.
426) A program has well defined user requirements and functional specifications.
437) A program is written with regard to future expansion and integreation
44 with other systems (portability).
45
46When programming following these additional principles make programs easier
47to maintain.
48
49A) Choose variable names that accurately describes what the variable does/is.
50B) Write comments to inform someone faced with the task of modifying your code.
51C) Avoid excessive comments. Write the code so that it says what it does.
52D) Follow a strict one-in, one-out flow of control structues except in the
53 case of fatal error conditions.
54E) Avoid using global variables.
55F) Do not cause side effects to variables that were not parameters to a
56 function.
57G) Have a single function perform a single purpose.
58H) Select a single indentation style and stick with it.
59I) Use a consistent naming convention.
60
61The following principles help me when I try optimizing code:
62
63a) If optimizing, use a profiler to determine which sections of code most of
64 the time is spent in. Spend most of your effort in the most used sections.
65 Don't bother optimizing a procedure using less than 10% of the time.
66
67b) High level optimizations are far more effective than cycle shaving.
68 (e.g. use quick sort instead of optimizing a bubble sort.)
69
70c) Be flexible in your approach to solving a problem. List exactly what you
71 need as a result at a minimum. Get rid of unnecessary assumptions.
72
73d) Become familiar with sets of operations that are equivalent, or nearly so.
74 Learn the relative expense of basic operations.
75
76e) If possible, be careful not to needlessly sacrifice significant readability
77 of the code for a cycle or two.
78
79-- Spy
80
81*/
82
83
84#ifndef WIN32
85#include "x3d.h"
86#include "X3DBuffer.h"
87#endif
88
89#ifdef WIN32
90
91unsigned long x3d_main(float *longitude, float *latitude, float *psi,
92 const char *string) { return 0L; }
93void x3d_terminate() { }
94void x3d_get_position(float *longitude, float *latitude, float *psi) { }
95int x3d_dispatch_event(unsigned long event) { return 0; }
96void x3d_set_display(unsigned long display) { }
97void x3d_update() { }
98
99#else
100
101
102#include <stdio.h>
103#include <math.h>
104#include <string.h>
105#include <stdlib.h>
106#include <X11/Xlib.h>
107#include <X11/Xatom.h>
108#include <X11/Xutil.h>
109#include <X11/X.h>
110
111
112extern Color *colors;
113extern point *points;
114extern segment *segs;
115extern polygon *polys;
116
118
119static polygon **list;
120static point *bounds;
121static int quitApplication = 0;
122static Display *gDisplay = NULL;
123static Ginfo *gGInfo = NULL;
124static Oinfo *gOInfo = NULL;
125
127
128
129
130static void sort(polygon **list1, int numPolys)
131/*****************************************************************************
132 Specialized quick sort for painter algorithm.
133*****************************************************************************/
134{
135polygon **v0, **v1, **v2, **v3, **v4, **v5, **v6, *poly;
136register int stackIndex, stackNotSet, length, start, end, high;
137float dist;
138int numPoints;
140point **Point, **lastPoint;
141
142 v0 = list1;
143 v1 = &(list1[numPolys]);
144
145/* Set the key value to be the average of the vertices' distances */
146
147 while(v0 < v1){
148 poly = *v0;
149 numPoints = poly->numPoints;
150 Point = poly->points;
151 lastPoint = Point + numPoints;
152 dist = 0.0;
153
154 do{
155 dist += (*Point)->dist;
156 Point++;
157 }while(Point < lastPoint);
158
159 poly->dist = dist / ((float)numPoints);
160 v0++;
161 }
162
163/* Initialize for the qsort() */
164
165 stackIndex = 1;
166 stackNotSet = 0;
167 start = 0;
168 end = numPolys - 1;
169
170/* Do Qsort */
171
172 while(stackIndex){
173
174 if(stackNotSet){
175 start = stack[stackIndex].start;
176 end = stack[stackIndex].end;
177 }
178
179 stackIndex--;
180 stackNotSet = 1;
181 length = end - start;
182
183/* Big enough to qsort ? */
184
185 if(length > STOP){
186 v1 = &(list1[start]);
187 v2 = &(list1[start + (length / 4)]);
188 v3 = &(list1[start + (length / 2)]);
189 v4 = &(list1[start + ((length * 3) / 4)]);
190 v5 = &(list1[end]);
191 v6 = v1;
192
193 median5(v1,v2,v3,v4,v5)
194
195 *v0 = *v3;
196 *v3 = *v6;
197 *v6 = *v0;
198
199 v1 = &(list1[start + 1]);
200 v2 = &(list1[end]);
201
202/* Split */
203
204 dist = (*v6)->dist;
205 while((*v2)->dist < dist) v2--;
206 while((*v1)->dist > dist) v1++;
207
208 v5 = v0;
209
210 while(v1 < v2){
211
212 *v5 = *v2;
213 *v2 = *v1;
214
215 v5 = v1;
216
217 do{
218 v2--;
219 }while(((*v2)->dist < dist) && (v1 < v2));
220 if (v2 <= v1) break;
221
222 do{
223 v1++;
224 }while(((*v1)->dist > dist) && (v1 < v2));
225 if (v2 <= v1) break;
226 }
227
228 v2 = v1 - 1;
229
230 *v5 = *v2;
231 *v2 = *v6;
232 *v6 = *v0;
233
234 high = v2 - list1;
235
236/* Put sublists on the stack, smallest on top */
237
238 if((high - start) > (end - high)){
239 stack[++stackIndex].start = start;
240 stack[stackIndex].end = high - 1;
241 ++stackIndex;
242 start = high + 1;
243 stackNotSet = 0;
244 }else{
245 stack[++stackIndex].start = high + 1;
246 stack[stackIndex].end = end;
247 ++stackIndex;
248 end = high - 1;
249 stackNotSet = 0;
250 }
251 }
252 }
253
254/* insertion sort all the remaining sublists at once */
255
256 v2 = list1;
257 v3 = &(list1[numPolys - 1]);
258 v4 = v2 + 1;
259
260 while(v4 <= v3){
261
262 *v0 = *v4;
263 v1 = v4 - 1;
264
265 while((v1 >= v2) && ((*v1)->dist < (*v0)->dist)){
266 *(v1 + 1) = *v1;
267 v1--;
268 }
269
270 *(v1 + 1) = *v0;
271 v4++;
272 }
273}
274
275
276
277static void Rotate(anglePoint *points1, double cx, double cy, double cz, double sx, double sy, double sz)
278/******************************************************************************
279 Rotate about Z, X, then Y, for two points.
280******************************************************************************/
281{
282int index1;
283double x, y, z, t;
284
285 for(index1 = 0; index1 < 2; index1++){
286 x = points1[index1].x;
287 y = points1[index1].y;
288 z = points1[index1].z;
289
290 t = x * cz + y * sz;
291 y = y * cz - x * sz;
292 x = t;
293
294 points1[index1].y = y * cx + z * sx;
295
296 z = z * cx - y * sx;
297
298 points1[index1].x = x * cy + z * sy;
299 points1[index1].z = z * cy - x * sy;
300 }
301}
302
303
304
305static double DotProduct(double x1, double Y1, double x2, double y2)
306/******************************************************************************
307 Dot product (calculate the cosine of the angle between two vectors).
308******************************************************************************/
309{
310double temp;
311
312 if((x1 == 0.0 && Y1 == 0.0)){
313 return 1.0;
314 }
315
316 temp = sqrt(x1 * x1 + Y1 * Y1);
317 x1 = x1 / temp;
318 Y1 = Y1 / temp;
319
320 temp = x1 * x2 + Y1 * y2;
321
322 if(temp > 1.0)
323 temp = fmod(temp, 1.0);
324
325 if(temp < -1.0)
326 temp = -fmod(-temp, 1.0);
327
328 return(temp);
329}
330
331
332
333static void CalculateAngles(double *X, double *Y, double *Z, double X1, double Y1, double Z1)
334/******************************************************************************
335 Calculate what the result of the angle changes of X1, Y1, and Z1 are
336 in my weird coordinate system.
337******************************************************************************/
338{
339anglePoint points1[2];
340
341 points1[0].x = 0.0; points1[0].y = 0.0; points1[0].z = 1.0;
342 points1[1].x = 1.0; points1[1].y = 0.0; points1[1].z = 0.0;
343
344 Rotate(points1, cos(*X), cos(*Y), cos(*Z), sin(*X), sin(*Y), sin(*Z));
345 Rotate(points1, cos(X1), cos(Y1), cos(Z1), sin(X1), sin(Y1), sin(Z1));
346
347 *Y = acos(DotProduct(points1[0].x, points1[0].z, 0.0, 1.0));
348
349 if(points1[0].x < 0.0)
350 *Y = -*Y;
351
352 Rotate(points1, 1.0, cos(-*Y), 1.0, 0.0, sin(-*Y), 0.0);
353 *X = acos(DotProduct(points1[0].y, points1[0].z, 0.0, 1.0));
354
355 if(points1[0].y < 0.0)
356 *X = -*X;
357
358 Rotate(points1, cos(-*X), 1.0, 1.0, sin(-*X), 0.0, 0.0);
359 *Z = acos(DotProduct(points1[1].x, points1[1].y, 1.0, 0.0));
360
361 if(!(points1[1].y < 0.0))
362 *Z = -*Z;
363}
364
365
366
367static void DrawLogo(Ginfo *g, int x, int y)
368/******************************************************************************
369 Display the Logo.
370******************************************************************************/
371{
372int hUnit, vUnit;
373 _XPoint points1[512];
374 void *ptrp = points1;
375
376 hUnit = XTextWidth(g->font, LONGESTSTRING, strlen(LONGESTSTRING)) /
377 strlen(LONGESTSTRING);
378 vUnit = FONTHEIGHT(g->font);
379
380/* X */
381
382 points1[0].x = 9 * hUnit + x; points1[0].y = 1 * vUnit + y;
383 points1[1].x = 9 * hUnit + vUnit + x; points1[1].y = 1 * vUnit + y;
384 points1[2].x = 14 * hUnit + vUnit + x; points1[2].y = 6 * vUnit + y;
385 points1[3].x = 14 * hUnit + x; points1[3].y = 6 * vUnit + y;
386
387 XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
388 CoordModeOrigin);
389
390 points1[0].x = 14 * hUnit + vUnit + x; points1[0].y = 1 * vUnit + y;
391 points1[1].x = 14 * hUnit + x; points1[1].y = 1 * vUnit + y;
392 points1[2].x = 9 * hUnit + x; points1[2].y = 6 * vUnit + y;
393 points1[3].x = 9 * hUnit + vUnit + x; points1[3].y = 6 * vUnit + y;
394
395 XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
396 CoordModeOrigin);
397
398/* 3 */
399
400 points1[0].x = 18 * hUnit + x; points1[0].y = 1 * vUnit + y;
401 points1[1].x = 22 * hUnit + x; points1[1].y = 1 * vUnit + y;
402 points1[2].x = 23 * hUnit + x; points1[2].y = 2 * vUnit + y;
403 points1[3].x = 18 * hUnit + x; points1[3].y = 2 * vUnit + y;
404
405 XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
406 CoordModeOrigin);
407
408 points1[0].x = 23 * hUnit - vUnit + x; points1[0].y = 2 * vUnit + y;
409 points1[1].x = 23 * hUnit + x; points1[1].y = 2 * vUnit + y;
410 points1[2].x = 23 * hUnit + x; points1[2].y = 3 * vUnit + y;
411 points1[3].x = 23 * hUnit - vUnit + x; points1[3].y = 4 * vUnit + y;
412
413 XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
414 CoordModeOrigin);
415
416 points1[0].x = 23 * hUnit - vUnit + x; points1[0].y = 3 * vUnit + y;
417 points1[1].x = 23 * hUnit + x; points1[1].y = 4 * vUnit + y;
418 points1[2].x = 23 * hUnit + x; points1[2].y = 5 * vUnit + y;
419 points1[3].x = 23 * hUnit - vUnit + x; points1[3].y = 5 * vUnit + y;
420
421 XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
422 CoordModeOrigin);
423
424 points1[0].x = 18 * hUnit + x; points1[0].y = 5 * vUnit + y;
425 points1[1].x = 23 * hUnit + x; points1[1].y = 5 * vUnit + y;
426 points1[2].x = 22 * hUnit + x; points1[2].y = 6 * vUnit + y;
427 points1[3].x = 18 * hUnit + x; points1[3].y = 6 * vUnit + y;
428
429 XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
430 CoordModeOrigin);
431
432 points1[0].x = 19 * hUnit + x; points[0].y = 3 * vUnit + y;
433 points1[1].x = 23 * hUnit - vUnit + x; points1[1].y = 3 * vUnit + y;
434 points1[2].x = 23 * hUnit - vUnit + x; points1[2].y = 4 * vUnit + y;
435 points1[3].x = 19 * hUnit + x; points1[3].y = 4 * vUnit + y;
436
437 XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
438 CoordModeOrigin);
439
440/* D */
441
442 points1[0].x = 26 * hUnit + x; points1[0].y = 1 * vUnit + y;
443 points1[1].x = 30 * hUnit + x; points1[1].y = 1 * vUnit + y;
444 points1[2].x = 30 * hUnit + vUnit + x; points1[2].y = 2 * vUnit + y;
445 points1[3].x = 26 * hUnit + x; points1[3].y = 2 * vUnit + y;
446
447 XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
448 CoordModeOrigin);
449
450 points1[0].x = 26 * hUnit + x; points1[0].y = 5 * vUnit + y;
451 points1[1].x = 30 * hUnit + vUnit + x; points1[1].y = 5 * vUnit + y;
452 points1[2].x = 30 * hUnit + x; points1[2].y = 6 * vUnit + y;
453 points1[3].x = 26 * hUnit + x; points1[3].y = 6 * vUnit + y;
454
455 XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
456 CoordModeOrigin);
457
458 points1[0].x = 26 * hUnit + x; points1[0].y = 1 * vUnit + y;
459 points1[1].x = 26 * hUnit + vUnit + x; points1[1].y = 1 * vUnit + y;
460 points1[2].x = 26 * hUnit + vUnit + x; points1[2].y = 6 * vUnit + y;
461 points1[3].x = 26 * hUnit + x; points1[3].y = 6 * vUnit + y;
462
463 XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
464 CoordModeOrigin);
465
466 points1[0].x = 30 * hUnit + x; points1[0].y = 2 * vUnit + y;
467 points1[1].x = 30 * hUnit + vUnit + x; points1[1].y = 2 * vUnit + y;
468 points1[2].x = 30 * hUnit + vUnit + x; points1[2].y = 5 * vUnit + y;
469 points1[3].x = 30 * hUnit + x; points1[3].y = 5 * vUnit + y;
470
471 XFillPolygon(g->dpy, g->helpWin, g->helpGc, ptrp, 4, Convex,
472 CoordModeOrigin);
473}
474
475
476
477static void DisplayMenu(Ginfo *g)
478/******************************************************************************
479 Display the help menu.
480******************************************************************************/
481{
482int x = 5, y = 5;
483
484 XSetFont(g->dpy, g->helpGc, g->font->fid );
485
486 XSetWindowBackground(g->dpy, g->helpWin, g->black);
487 XSetForeground(g->dpy, g->helpGc, g->white);
488 XSetBackground(g->dpy, g->helpGc, g->black);
489
490 XSetStipple(g->dpy, g->helpGc, g->stipple[NUMSTIPPLES / 3]);
491 XSetFillStyle(g->dpy, g->helpGc, FillOpaqueStippled);
492
493 DrawLogo(g, (XTextWidth(g->font, LONGESTSTRING, strlen(LONGESTSTRING)) /
494 (int)strlen(LONGESTSTRING)) / 2, FONTHEIGHT(g->font) / 3);
495
496 XSetFillStyle(g->dpy, g->helpGc, FillSolid);
497
498 DrawLogo(g, 0, 0);
499
500 HelpPrint(g,x,y,"");
501 HelpPrint(g,x,y,"");
502 HelpPrint(g,x,y,"");
503 HelpPrint(g,x,y,"");
504 HelpPrint(g,x,y,"");
505 HelpPrint(g,x,y,"");
506 HelpPrint(g,x,y,"");
507 HelpPrint(g,x,y," VERSION 2.2");
508 HelpPrint(g,x,y,"");
509 HelpPrint(g,x,y," CONTROLS SUMMARY");
510 HelpPrint(g,x,y,"");
511 HelpPrint(g,x,y," QUIT q Q");
512 HelpPrint(g,x,y," WIREFRAME MODE w W");
513 HelpPrint(g,x,y," HIDDEN LINE MODE e E");
514 HelpPrint(g,x,y," HIDDEN SURFACE MODE r R");
515 HelpPrint(g,x,y," MOVE OBJECT DOWN u U");
516 HelpPrint(g,x,y," MOVE OBJECT UP i I");
517 HelpPrint(g,x,y," TOGGLE CONTROLS STYLE o O");
518 HelpPrint(g,x,y," TOGGLE STEREO DISPLAY s S");
519 HelpPrint(g,x,y," TOGGLE BLUE STEREO VIEW d D");
520 HelpPrint(g,x,y," TOGGLE DOUBLE BUFFER f F");
521 HelpPrint(g,x,y," MOVE OBJECT RIGHT h H");
522 HelpPrint(g,x,y," MOVE OBJECT BACKWARD j J");
523 HelpPrint(g,x,y," MOVE OBJECT FOREWARD k K");
524 HelpPrint(g,x,y," MOVE OBJECT LEFT l L");
525 HelpPrint(g,x,y," TOGGLE HELP MENU m M");
526 HelpPrint(g,x,y," ROTATE ABOUT X x X a A");
527 HelpPrint(g,x,y," ROTATE ABOUT Y y Y b B");
528 HelpPrint(g,x,y," ROTATE ABOUT Z z Z c C");
529 HelpPrint(g,x,y," AUTOROTATE ABOUT X 1 2 3");
530 HelpPrint(g,x,y," AUTOROTATE ABOUT Y 4 5 6");
531 HelpPrint(g,x,y," AUTOROTATE ABOUT Z 7 8 9");
532 HelpPrint(g,x,y," ADJUST FOCUS [ ] { }");
533 HelpPrint(g,x,y,"");
534 HelpPrint(g,x,y," POINTER MOVEMENT WITH LEFT BUTTON :");
535 HelpPrint(g,x,y,"");
536 HelpPrint(g,x,y," ROTATE OBJECT ABOUT X Vertical");
537 HelpPrint(g,x,y," ROTATE OBJECT ABOUT Z Horizontal");
538}
539
540
541
542static void ResetPurpleRectangle(int XL, int YL, int XH, int YH, Ginfo *g)
543/******************************************************************************
544 Reset the vertices of the purple rectangle.
545******************************************************************************/
546{
547 g->redSegments[3].x1 = (XL + MARGIN);
548 g->blueSegments[3].x1 = (XL + MARGIN);
549 g->redSegments[3].y1 = (YL + MARGIN);
550 g->blueSegments[3].y1 = (YL + MARGIN);
551 g->redSegments[3].x2 = (XH - MARGIN);
552 g->blueSegments[3].x2 = (XH - MARGIN);
553 g->redSegments[3].y2 = (YL + MARGIN);
554 g->blueSegments[3].y2 = (YL + MARGIN);
555 g->redSegments[2].x1 = (XH - MARGIN);
556 g->blueSegments[2].x1 = (XH - MARGIN);
557 g->redSegments[2].y1 = (YH - MARGIN);
558 g->blueSegments[2].y1 = (YH - MARGIN);
559 g->redSegments[2].x2 = (XL + MARGIN);
560 g->blueSegments[2].x2 = (XL + MARGIN);
561 g->redSegments[2].y2 = (YH - MARGIN);
562 g->blueSegments[2].y2 = (YH - MARGIN);
563 g->redSegments[1].x1 = (XH - MARGIN);
564 g->blueSegments[1].x1 = (XH - MARGIN);
565 g->redSegments[1].y1 = (YL + MARGIN);
566 g->blueSegments[1].y1 = (YL + MARGIN);
567 g->redSegments[1].x2 = (XH - MARGIN);
568 g->blueSegments[1].x2 = (XH - MARGIN);
569 g->redSegments[1].y2 = (YH - MARGIN);
570 g->blueSegments[1].y2 = (YH - MARGIN);
571 g->redSegments[0].x1 = (XL + MARGIN);
572 g->blueSegments[0].x1 = (XL + MARGIN);
573 g->redSegments[0].y1 = (YL + MARGIN);
574 g->blueSegments[0].y1 = (YL + MARGIN);
575 g->redSegments[0].x2 = (XL + MARGIN);
576 g->blueSegments[0].x2 = (XL + MARGIN);
577 g->redSegments[0].y2 = (YH - MARGIN);
578 g->blueSegments[0].y2 = (YH - MARGIN);
579}
580
581
582
584/******************************************************************************
585 Set up color information/stipples for a one bit display.
586******************************************************************************/
587{
588int index1;
589Color *color;
590int numColors;
591
592 color = g->colors;
593 numColors = g->numColors;
594
595/* Set the colors (may not be used) */
596
597 for(index1 = 0; index1 < numColors; index1++){
598 color[index1].value = 1;
599
600/* Set the stipples */
601
602 color[index1].stipple =(int)((double)NUMSTIPPLES *
603 ((double)sqrt((double)(
604 (double)color[index1].red * (double)color[index1].red +
605 (double)color[index1].green * (double)color[index1].green +
606 (double)color[index1].blue * (double)color[index1].blue))
607 / MAXCOLORDIST));
608 }
609}
610
611
612
614/******************************************************************************
615 Set up color information/stipples for a eight bit display.
616******************************************************************************/
617{
618Color *colors1;
619int numColors;
620int colorIndex = 0;
621int index1, index2, redIndex, blueIndex, greenIndex;
622XColor c;
623
624 colors1 = g->colors;
625 numColors = g->numColors;
626
627/* Put "black" into the place reserved for it in the end */
628
629 colors1[numColors].red = 0;
630 colors1[numColors].green = 0;
631 colors1[numColors].blue = 0;
632
633/* Put "red" into the place reserved for it in the end */
634
635 colors1[numColors + 1].red = 255;
636 colors1[numColors + 1].green = 0;
637 colors1[numColors + 1].blue = 0;
638
639/* Put "blue" into the place reserved for it in the end */
640
641 colors1[numColors + 2].red = 0;
642 colors1[numColors + 2].green = 0;
643 colors1[numColors + 2].blue = 255;
644
645/* Put "purple" into the place reserved for it in the end */
646
647 colors1[numColors + 3].red = 255;
648 colors1[numColors + 3].green = 0;
649 colors1[numColors + 3].blue = 255;
650
651/* Blank out the colormap */
652
653 for(index1 = 0; index1 < 256; index1++){
654 c.red = 0;
655 c.green = 0;
656 c.blue = 0;
657 c.flags = DoRed | DoGreen | DoBlue;
658 c.pixel = 255;
659 c.pad = 0;
660 g->cmapColors[0][index1] = c;
661 g->cmapColors[1][index1] = c;
662 g->cmapColors[2][index1] = c;
663 }
664
665 if(numColors <= BUFFER_CMAP){
666
667 colorIndex= numColors + 3;
668 index1 = 15;
669
670/* Set stipple, and colormap double buffer colors */
671
672 while((index1 > 0) && (colorIndex >= 0)){
673 c.red = colors1[colorIndex].red << 8;
674 c.green = colors1[colorIndex].green << 8;
675 c.blue = colors1[colorIndex].blue << 8;
676 c.flags = DoRed | DoGreen | DoBlue;
677
678 colors1[colorIndex].value = index1 * 16 + index1;
679
680 colors1[colorIndex].stipple =(int)((double)NUMSTIPPLES *
681 ((double)sqrt((double)(
682 (double)colors1[colorIndex].red * (double)colors1[colorIndex].red +
683 (double)colors1[colorIndex].green * (double)colors1[colorIndex].green +
684 (double)colors1[colorIndex].blue * (double)colors1[colorIndex].blue))
685 / MAXCOLORDIST));
686
687 for(index2 = 1; index2 < 16; index2++){
688 c.pixel = index2 * 16 + index1;
689 g->cmapColors[0][index2 * 16 + index1] = c;
690
691 c.pixel = index1 * 16 + index2;
692 g->cmapColors[1][index1 * 16 + index2] = c;
693 }
694
695 index1--;
696 colorIndex--;
697 }
698 }else{
699
700/* Set permanent black, red, blue, purple for cmap double buffer */
701
702 for(index1 = 0; index1 < 4; index1++){
703 c.red = colors1[numColors + index1].red << 8;
704 c.green = colors1[numColors + index1].green << 8;
705 c.blue = colors1[numColors + index1].blue << 8;
706 c.flags = DoRed | DoGreen | DoBlue;
707 c.pixel = 12 + index1;
708 g->cmapColors[0][12 + index1] = c;
709 g->cmapColors[1][12 + index1] = c;
710 colors1[numColors + index1].value = c.pixel;
711 }
712
713 if(numColors <= MAX_COLORS){
714 colorIndex = 0;
715 index1 = 9;
716 index2 = 0;
717
718/* Fill in the rest of the colors */
719
720 while(colorIndex < numColors){
721 if((index1 < 12) || (index1 > 15)){
722 c.red = colors1[colorIndex].red << 8;
723 c.green = colors1[colorIndex].green << 8;
724 c.blue = colors1[colorIndex].blue << 8;
725 c.flags = DoRed | DoGreen | DoBlue;
726 c.pixel = index1;
727 g->cmapColors[0][index1] = c;
728 g->cmapColors[1][index1] = c;
729 colors1[colorIndex].value = index1;
730
731 colors1[colorIndex].stipple =(int)((double)NUMSTIPPLES *
732 ((double)sqrt((double)(
733 (double)colors1[colorIndex].red *
734 (double)colors1[colorIndex].red +
735 (double)colors1[colorIndex].green *
736 (double)colors1[colorIndex].green +
737 (double)colors1[colorIndex].blue *
738 (double)colors1[colorIndex].blue))
739 / MAXCOLORDIST));
740
741 colorIndex++;
742 }
743 index1++;
744 }
745 }else{
746 index1 = 17;
747 index2 = 0;
748 redIndex = 0;
749 greenIndex = 0;
750 blueIndex = 0;
751
752/* Otherwise use a default lot */
753
754 while(blueIndex < MAXVALUE){
755 c.red = (redIndex * VALUESCALE) << 8;
756 c.green = (greenIndex * VALUESCALE) << 8;
757 c.blue = (blueIndex * VALUESCALE) << 8;
758 c.flags = DoRed | DoGreen | DoBlue;
759 c.pixel = index1;
760 g->cmapColors[0][index1] = c;
761 g->cmapColors[1][index1] = c;
762
763 redIndex++;
764
765 if(redIndex >= MAXVALUE){
766 redIndex = 0;
767 greenIndex++;
768 }
769
770 if(greenIndex >= MAXVALUE){
771 greenIndex = 0;
772 blueIndex++;
773 }
774 index1++;
775 }
776
777 for(index1 = 0; index1 < numColors; index1++){
778 colors1[index1].value = colors1[index1].red * 36 +
779 colors1[index1].green * 6 + colors1[index1].blue + 17;
780
781 colors1[colorIndex].stipple =(int)((double)NUMSTIPPLES *
782 ((double)sqrt((double)(
783 (double)colors1[colorIndex].red *
784 (double)colors1[colorIndex].red +
785 (double)colors1[colorIndex].green *
786 (double)colors1[colorIndex].green +
787 (double)colors1[colorIndex].blue *
788 (double)colors1[colorIndex].blue))
789 / MAXCOLORDIST));
790
791 }
792 }
793 }
794
795/* Set the colors for the special fast colormap double buffer */
796
797 index1 = 0;
798 for(redIndex = 0; redIndex < 4; redIndex++){
799 for(blueIndex = 0; blueIndex < 4; blueIndex++){
800 if(redIndex != blueIndex){
801 g->wireframeColors[0][index1] =
802 g->cmapColors[0][(redIndex + 12) * 16 + (blueIndex + 12)];
803 g->wireframeColors[1][index1] =
804 g->cmapColors[1][(redIndex + 12) * 16 + (blueIndex + 12)];
805 index1++;
806 }
807 }
808 }
809
810/* Just in case set the rest of the colors */
811
812 for(index1 = 13; index1 < 256; index1++){
813 g->wireframeColors[0][index1] = g->wireframeColors[0][3];
814 g->wireframeColors[1][index1] = g->wireframeColors[1][3];
815 }
816
817/* Set the colors for the pix stereo mode */
818
819 for(redIndex = 0; redIndex < 15; redIndex++){
820 for(blueIndex = 0; blueIndex < 15; blueIndex++){
821 c.red = (redIndex * 17) << 8;
822 c.green = 0;
823 c.blue = (blueIndex * 17) << 8;
824 c.flags = DoRed | DoGreen | DoBlue;
825 c.pixel = (redIndex + 1) * 16 + (blueIndex + 1);
826 g->cmapColors[2][c.pixel] = c;
827 }
828 }
829
830/* Set stereoColor to nearest color */
831
832 for(index1 = 0; index1 < numColors; index1++){
833 colorIndex = (int)((double)15 *
834 ((double)sqrt((double)((double)colors1[index1].red *
835 (double)colors1[index1].red + (double)colors1[index1].green *
836 (double)colors1[index1].green + (double)colors1[index1].blue *
837 (double)colors1[index1].blue)) / MAXCOLORDIST));
838
839 colors1[index1].stereoColor = (colorIndex + 1) * 16 + (colorIndex + 1);
840 }
841
842/* Set various important color values */
843
844 g->stereoBlack = (0 + 1) * 16 + (0 + 1);
845 g->redMask = BUFFER0;
846 g->blueMask = BUFFER1;
847 g->Black = colors1[numColors].value;
848 g->Red = colors1[numColors + 1].value;
849 g->Blue = colors1[numColors + 2].value;
850 g->Purple = colors1[numColors + 3].value;
851}
852
853
855/******************************************************************************
856 Set up color information/stipples for TrueColor displays.
857******************************************************************************/
858{
859int index1, colorValue;
860Color *colors1;
861int numColors;
862
863 /* On TrueColor displays the color pixel value composed directly of
864 r, g and b components. The order of the r, g and b and the number
865 of bits used for each color is specified by the X server and decoded
866 in the gRedShift, gRedDiv etc. values. Since X3D uses 255 as max
867 color the div is the number of bits to left shift (divide) from 255.
868 */
869
870 colors1 = g->colors;
871 numColors = g->numColors;
872
873 for(index1 = 0; index1 < numColors; index1++){
874
875/* In TrueColor every color is what it is */
876
877 colors1[index1].value =
878 (colors1[index1].red >> gRedDiv) << gRedShift |
879 (colors1[index1].green >> gGreenDiv) << gGreenShift |
880 (colors1[index1].blue >> gBlueDiv) << gBlueShift;
881
882/* Set stipple */
883
884 colors1[index1].stipple =(int)((double)NUMSTIPPLES *
885 ((double)sqrt((double)(
886 (double)colors1[index1].red * (double)colors1[index1].red +
887 (double)colors1[index1].green * (double)colors1[index1].green +
888 (double)colors1[index1].blue * (double)colors1[index1].blue))
889 / MAXCOLORDIST));
890
891/* Set stereo color */
892
893 colorValue= (int)((double)(255 >> gRedDiv) *
894 ((double)sqrt((double)((double)colors1[index1].red *
895 (double)colors1[index1].red + (double)colors1[index1].green *
896 (double)colors1[index1].green + (double)colors1[index1].blue *
897 (double)colors1[index1].blue)) / MAXCOLORDIST));
898
899 colors1[index1].stereoColor = (colorValue << gRedShift) |
900 (colorValue << gBlueShift);
901 }
902
903/* Set various important color values */
904
905 g->stereoBlack = 0;
906 g->redMask = (255 >> gRedDiv) << gRedShift;
907 g->blueMask = (255 >> gBlueDiv) << gBlueShift;
908 g->Black = 0;
909 g->Red = (255 >> gRedDiv) << gRedShift;
910 g->Blue = (255 >> gBlueDiv) << gBlueShift;
911 g->Purple = g->Red | g->Blue;
912}
913
914
915char title[80];
917
918static void InitDisplay(Oinfo *o, Ginfo *g, Window parent)
919/******************************************************************************
920 Set up an X window and our colormap. We rely on X's own error handling and
921 reporting for most bad X calls because X buffers requests.
922******************************************************************************/
923{
924static int stipples[NUMSTIPPLES][NUMSTIPPLES * 2 + 1] = {
925{0},
926{1, 1, 1},
927{2, 0, 2, 2, 1},
928{3, 1, 0, 1, 2, 3, 1},
929{4, 0, 1, 0, 3, 2, 1, 2, 3},
930{5, 0, 0, 0, 2, 2, 0, 2, 3, 3, 2},
931{6, 0, 2, 1, 1, 1, 3, 2, 0, 3, 1, 3, 3},
932{7, 0, 1, 0, 3, 1, 0, 1, 1, 2, 2, 3, 1, 3, 3},
933{8, 0, 1, 0, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 0, 3, 2},
934{9, 0, 0, 0, 2, 1, 2, 1, 3, 2, 0, 2, 1, 2, 3, 3, 1, 3, 2},
935{10,0, 0, 0, 1, 0, 3, 1, 0, 1, 2, 2, 1, 2, 2, 2, 3, 3, 0, 3, 2},
936{11,0, 1, 0, 3, 1, 0, 1, 1, 1, 2, 1, 3, 2, 1, 2, 2, 3, 0, 3, 2, 3, 3},
937{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},
938{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,
939 3, 3},
940{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,
941 3, 2, 3, 3},
942{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,
943 3, 1, 3, 2, 3, 3},
944{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,
945 3, 0, 3, 1, 3, 2, 3, 3}
946};
947
948char bits[(STIPPLESIZE * STIPPLESIZE) / BITSPERBYTE];
949
950GC temp_gc;
951XColor oldColormap[MAXCOLORS];
952XWindowAttributes attributes;
954XWMHints wmhint;
955int index1, index2, screen;
956Visual *vis;
957XSizeHints sizehint;
958int x, y, NUMCOLORS;
959unsigned int width, height, numSegments;
960int useroot = 0;
961
962 if (gDisplay)
963 useroot = 1;
964
965
966 numSegments = o->numSegs;
967
968 if((g->redColors = (long *)calloc(1, (numSegments + 4) * (sizeof(long))))
969 == NULL){
970(void)fprintf(stderr, "Unable to allocate memory for redColors\n"); return;}
971
972 if((g->redSegments = (XSegment *)calloc(1, (numSegments + 4) *
973 (sizeof(XSegment)))) == NULL){
974(void)fprintf(stderr, "Unable to allocate memory for redSegments\n"); return;}
975
976 if((g->blueSegments = (XSegment *)calloc(1, (numSegments + 4) *
977 sizeof(XSegment))) == (XSegment *)NULL){
978(void)fprintf(stderr, "Unable to allocate memory for blueSegments\n"); return;}
979
980/* Can we connect with the server? */
981
982 if (!useroot)
983 g->dpy = XOpenDisplay(g->DisplayName);
984 else
985 g->dpy = gDisplay;
986 if(g->dpy == NULL){
987 fprintf(stderr, "Cannot connect to server\n");
988 return;
989 }
990
991 screen = DefaultScreen(g->dpy);
992 g->black = (long)BlackPixel(g->dpy, screen);
993 g->white = (long)WhitePixel(g->dpy, screen);
994
995/* Initialize various flags and default values */
996
997 g->requestSize = XMaxRequestSize(g->dpy) / REQUESTFACTOR;
998 g->dpyX = DisplayWidth(g->dpy, screen);
999 g->dpyY = DisplayHeight(g->dpy, screen);
1000 g->winX = g->dpyX / 2;
1001 g->winY = g->dpyY / 2 /* - 25 */ ;
1002 g->mono = g->ColorSelect = g->oldPointerX = g->oldPointerY = 0;
1003 g->Block = 1;
1004 g->Relative = 0;
1005
1006/* Initialize the fonts */
1007
1008 if((g->font = XLoadQueryFont(g->dpy, FONT)) == NULL){
1009 fprintf(stderr, "Unable to load font: %s ... trying fixed\n", FONT);
1010
1011 if((g->font = XLoadQueryFont(g->dpy, FIXED)) == NULL){
1012 fprintf(stderr, "Unable to load font: %s\n", FIXED);
1013 return;
1014 }
1015 }
1016
1017 if((g->titleFont = XLoadQueryFont(g->dpy, TITLEFONT)) == NULL){
1018 fprintf(stderr, "Unable to load font: %s ... trying fixed\n", TITLEFONT);
1019
1020 if((g->titleFont = XLoadQueryFont(g->dpy, FIXED)) == NULL){
1021 fprintf(stderr, "Unable to load font: %s\n", FIXED);
1022 return;
1023 }
1024 }
1025
1026 if((g->boldFont = XLoadQueryFont(g->dpy, BOLDFONT)) == NULL){
1027 fprintf(stderr, "Unable to load font: %s ... trying fixed\n", BOLDFONT);
1028
1029 if((g->boldFont = XLoadQueryFont(g->dpy, FIXED)) == NULL){
1030 fprintf(stderr, "Unable to load font: %s\n", FIXED);
1031 return;
1032 }
1033 }
1034
1035/* Which visual do we get? */
1036
1038 g->depth = DefaultDepth(g->dpy, screen);
1039
1040 vis = DefaultVisual(g->dpy, screen);
1041 if (g->depth > EIGHT && vis->class == TrueColor) {
1042 int i;
1043 for (i = 0; i < (int)sizeof(vis->blue_mask)*8; i++) {
1044 if (gBlueShift == -1 && ((vis->blue_mask >> i) & 1))
1045 gBlueShift = i;
1046 if ((vis->blue_mask >> i) == 1) {
1047 gBlueDiv = 8 - i - 1 + gBlueShift; /* max value is 255, i.e. 8 bits */
1048 break;
1049 }
1050 }
1051 for (i = 0; i < (int)sizeof(vis->green_mask)*8; i++) {
1052 if (gGreenShift == -1 && ((vis->green_mask >> i) & 1))
1053 gGreenShift = i;
1054 if ((vis->green_mask >> i) == 1) {
1055 gGreenDiv = 8 - i - 1 + gGreenShift;
1056 break;
1057 }
1058 }
1059 for (i = 0; i < (int)sizeof(vis->red_mask)*8; i++) {
1060 if (gRedShift == -1 && ((vis->red_mask >> i) & 1))
1061 gRedShift = i;
1062 if ((vis->red_mask >> i) == 1) {
1063 gRedDiv = 8 - i - 1 + gRedShift;
1064 break;
1065 }
1066 }
1067 /*
1068 printf("gRedDiv = %d, gGreenDiv = %d, gBlueDiv = %d, gRedShift = %d, gGreenShift = %d, gBlueShift = %d\n",
1069 gRedDiv, gGreenDiv, gBlueDiv, gRedShift, gGreenShift, gBlueShift);
1070 */
1071 } else if (g->depth > EIGHT)
1072 g->depth = EIGHT;
1073
1074 g->pix = XCreatePixmap(g->dpy, RootWindow(g->dpy,screen), g->winX,
1075 g->winY, g->depth);
1076
1077/* Everything else we treat as monochrome whether or not
1078 something better may be supported */
1079
1080/* Make a vanilla window */
1081
1082 g->helpWinX =XTextWidth(g->font, LONGESTSTRING, strlen(LONGESTSTRING));
1083 g->helpWinY = FONTHEIGHT(g->font) * HELPLINES;
1084
1085 g->helpWin = XCreateSimpleWindow(g->dpy, RootWindow(g->dpy, screen), 0, 0,
1086 g->helpWinX, g->helpWinY, 0, 0, 0);
1087
1088 if (parent)
1089 g->win = XCreateSimpleWindow(g->dpy, parent, 0, 0,
1090 g->winX, g->winY, 0, 0, 0);
1091 else
1092 g->win = XCreateSimpleWindow(g->dpy, RootWindow(g->dpy,screen), 0, 0,
1093 g->winX, g->winY, 0, 0, 0);
1094
1095/* Any user geometry? */
1096
1097 if(g->Geometry && !useroot){
1098
1099 x = 0;
1100 y = 0;
1101 width = g->winX;
1102 height = g->winY;
1103 sizehint.flags = USPosition | USSize;
1104
1105 XParseGeometry(g->Geometry, &x, &y, &width, &height);
1106
1107 sizehint.x = x;
1108 sizehint.y = y;
1109 sizehint.width = width;
1110 sizehint.height = height;
1111 g->winX = width;
1112 g->winY = height;
1113
1114 XResizeWindow(g->dpy, g->win, width, height);
1115 XSetNormalHints(g->dpy, g->win, &sizehint);
1116 }
1117
1118/* Set horizontal and vertical ranges */
1119
1120 g->winH = (int)(g->winX / 2.0);
1121 g->winV = (int)(g->winY / 2.0);
1122
1123/* Make our graphics context */
1124
1125 g->gc = XCreateGC(g->dpy, g->win, 0x0, NULL);
1126 g->helpGc = XCreateGC(g->dpy, g->helpWin, 0x0, NULL);
1127
1128/* Create Tiles for monochrome display */
1129
1130 for(index1 = 0; index1 < NUMSTIPPLES; index1++){
1131 g->stipple[index1]= XCreateBitmapFromData(g->dpy, g->win, bits,
1133 temp_gc = XCreateGC(g->dpy, g->stipple[index1], 0x0, NULL);
1134 XSetForeground(g->dpy, temp_gc, 0);
1135 XFillRectangle(g->dpy, g->stipple[index1], temp_gc, 0, 0, STIPPLESIZE,
1136 STIPPLESIZE);
1137 XSetForeground(g->dpy, temp_gc, 1);
1138 for(index2 = 0; index2 < stipples[index1][0]; index2++){
1139 XDrawPoint(g->dpy, g->stipple[index1], temp_gc,
1140 stipples[index1][index2 * 2 + 1], stipples[index1][index2 * 2 + 2]);
1141 }
1142 XFreeGC(g->dpy, temp_gc);
1143 }
1144
1145 if (!useroot) {
1146/* We want to have the input focus if we can */
1147
1148 XSetInputFocus(g->dpy, PointerRoot, RevertToNone, CurrentTime);
1149
1150/*
1151 Thanks go to Otmar Lendl for the following bit of code that
1152 permits the program to work properly with losing window managers
1153 that don't handle input focus correctly.
1154*/
1155
1156 wmhint.input = True;
1157 wmhint.flags = InputHint;
1158 XSetWMHints(g->dpy,g->win,&wmhint);
1159 }
1160
1161/* Please do not do backing store on the contents of our window */
1162
1163 attribs.backing_store = NotUseful;
1164 XChangeWindowAttributes(g->dpy, g->win, CWBackingStore, &attribs);
1165
1166/* We only want certain kinds of events */
1167
1168 XSelectInput(g->dpy, g->win, ButtonPressMask | ButtonReleaseMask |
1169 KeyPressMask | Button1MotionMask | Button2MotionMask |
1170 StructureNotifyMask | ExposureMask | ColormapChangeMask);
1171
1172 XSelectInput(g->dpy, g->helpWin, ButtonPressMask | ButtonReleaseMask |
1173 KeyPressMask | Button1MotionMask | Button2MotionMask |
1174 StructureNotifyMask | ExposureMask | ColormapChangeMask);
1175
1176 if (!useroot) {
1177/* Do not generate expose events */
1178
1179 XSetGraphicsExposures(g->dpy, g->gc, 0);
1180
1181/* Name our windows */
1182
1183 XStoreName(g->dpy, g->win, title);
1184 XStoreName(g->dpy, g->helpWin, "ROOT://X3D/Help");
1185
1186 }
1187/* Some window managers are not friendly, explicitly set the background color */
1188
1189 XSetWindowBackground(g->dpy, g->win, g->black);
1190
1191 if(g->depth == ONE){
1193 }
1194
1195 if(g->depth > EIGHT){
1197 }
1198
1199 if(g->depth == EIGHT){
1200
1201 NUMCOLORS = 256;
1202
1203/* Make our colormap */
1204
1205 g->colormap = XCreateColormap(g->dpy, g->win, DefaultVisual(g->dpy,
1206 screen), AllocAll);
1207
1208/* Get the current colormap */
1209
1210 XGetWindowAttributes(g->dpy, RootWindow(g->dpy,screen), &attributes);
1211
1212/* Since we only use 16 colors, set all our other entries to the old values.
1213 Hopefully some other windows might display in true colors */
1214
1215 for(index1 = 0; index1 < NUMCOLORS; index1++)
1216 oldColormap[index1].pixel = index1;
1217
1218 XQueryColors(g->dpy, attributes.colormap, oldColormap, NUMCOLORS);
1219 XStoreColors(g->dpy, g->colormap, oldColormap, NUMCOLORS);
1220
1221/* Set up the colormap */
1222
1224
1225/* Set our special 12 colors to something */
1226
1227 XStoreColors(g->dpy, g->colormap, g->cmapColors[0], 256);
1228 XSetWindowColormap(g->dpy, g->helpWin, g->colormap);
1229 XSetWindowColormap(g->dpy, g->win, g->colormap);
1230 }
1231
1232/* Make the purple rectangle */
1233
1234 ResetPurpleRectangle(0, 0, g->winX, g->winY, g);
1235
1236
1237 if (!useroot) {
1238 /*
1239 * Set up some window manager properties (see the ICCCM).
1240 */
1241
1242 wm_protocols[0] = XInternAtom (g->dpy, "WM_DELETE_WINDOW", False);
1243 wm_protocols[1] = XInternAtom (g->dpy, "WM_SAVE_YOURSELF", False);
1244 XSetWMProtocols (g->dpy, g->win, wm_protocols, 2);
1245 }
1246
1247/*
1248 Make the windows appear.
1249*/
1250 XMapWindow(g->dpy, g->win);
1251 if (!useroot) DisplayMenu(g);
1252}
1253
1254
1255
1256static int CheckEvent(Display *display, XEvent *event, char *arg)
1257/******************************************************************************
1258 Check an event to see if it is one we are interested in.
1259 This is used by X to wake up our program once some interesting event
1260 happens. Returns: 1 if we are interested, 0 if we are not.
1261******************************************************************************/
1262{
1263 if (display || arg) { } /* use unused arguments */
1264
1265 if(event == NULL){
1266 fprintf(stderr, "WARNING: Null event in CheckEvent()!!\n");
1267 return 0;
1268 }
1269
1270 if((event->type == MotionNotify) || (event->type == KeyPress) ||
1271 (event->type == ConfigureNotify) || (event->type == Expose) ||
1272 (event->type == ColormapNotify) || (event->type == ClientMessage))
1273 return 1;
1274
1275 return 0;
1276}
1277
1278
1279
1280static void GetInput(XEvent *xevent, int *pointerX, int *pointerY, char *command, int *same, Ginfo *g)
1281/******************************************************************************
1282 Get an interesting event and update the user input information.
1283
1284 The routine will eventually block waiting for an event if block is 1
1285 and the no events of interest have shown up.
1286******************************************************************************/
1287{
1288XEvent event;
1289XSizeHints sizehint;
1290int numEvents;
1291char string[TMPSTRLEN];
1292
1293/* set command to a meaningless value (hopefully) */
1294
1295 *command = '\0';
1296
1297 if (!xevent) {
1298
1299 do{
1300 string[0] = '\0';
1301
1302/* How many events? */
1303
1304 numEvents = XEventsQueued(g->dpy, QueuedAfterReading);
1305
1306/* Block to obtain an event yet? */
1307
1308 if((numEvents == 0) && (g->Block)){
1309
1310/* If the user falls asleep stop using CPU cycles */
1311
1312 XIfEvent(g->dpy, &event, CheckEvent, NULL);
1313 numEvents = 1;
1314 }else{
1315
1316/* If we have at least one event , fetch the first event off the queue*/
1317
1318 if(numEvents)
1319 XNextEvent(g->dpy,&event);
1320 }
1321
1322 }while((numEvents == 0) && (g->Block));
1323
1324 } else {
1325 event = *xevent;
1326 numEvents = 1;
1327 }
1328
1329/* Process the events we have obtained (if any) */
1330
1331 while(numEvents){
1332
1333 switch(event.type){
1334
1335 case MotionNotify :
1336 if(numEvents == 1){
1337 *pointerX = (int)event.xmotion.x;
1338 *pointerY = (int)event.xmotion.y;
1339 }
1340 break;
1341
1342 case KeyPress :
1343 if(numEvents == 1){
1344 XLookupString(&event.xkey,string,TMPSTRLEN,NULL,NULL);
1345 *command = string[0];
1346 }
1347 break;
1348
1349 case ConfigureNotify :
1350
1351 if(event.xconfigure.window == g->win){
1352
1353 g->winX = event.xconfigure.width;
1354 g->winY = event.xconfigure.height;
1355 g->winH = (int)(g->winX / 2.0);
1356 g->winV = (int)(g->winY / 2.0);
1357 ResetPurpleRectangle(0, 0, g->winX, g->winY, g);
1358 sizehint.flags = USSize | USPosition;
1359 sizehint.width = g->winX;
1360 sizehint.height = g->winY;
1361 XSetNormalHints(g->dpy, g->win, &sizehint);
1362
1363/* Resize our pix etc... */
1364
1365 XFreePixmap(g->dpy, g->pix);
1366
1367 g->pix = XCreatePixmap(g->dpy, g->win, g->winX, g->winY,
1368 g->depth);
1369
1370 }
1371 if(event.xconfigure.window == g->helpWin){
1372 DisplayMenu(g);
1373 }
1374 g->modeChanged = 1;
1375 *same = 0;
1376 break;
1377
1378 case Expose :
1379 if(event.xexpose.window == g->helpWin){
1380 DisplayMenu(g);
1381 }
1382 *same = 0;
1383 break;
1384
1385 case MapNotify :
1386
1387 if(event.xmap.window == g->helpWin){
1388
1389 sizehint.flags = USPosition | USSize;
1390 XSetNormalHints(g->dpy, g->helpWin, &sizehint);
1391
1392 DisplayMenu(g);
1393 }
1394 g->modeChanged = 1;
1395 *same = 0;
1396 break;
1397
1398 case ColormapNotify :
1399
1400 if(event.xcolormap.colormap == g->colormap){
1401
1402 if(event.xcolormap.state == ColormapUninstalled){
1403 g->mono = 1;
1404 }else{
1405 g->mono = 0;
1406 }
1407
1408 g->modeChanged = 1;
1409 *same = 0;
1410 }
1411 break;
1412
1413 case ClientMessage:
1414 if (event.xclient.data.l[0] == (long)wm_protocols[0])
1415 /* WM_DELETE_WINDOW */
1416 {
1417 /*
1418 * XmbufDestroyBuffers( dpy, window );
1419 * XDestroyWindow (dpy, window);
1420 * XCloseDisplay( dpy );
1421 */
1422 quitApplication = 1;
1423 }
1424 else if (event.xclient.data.l[0] == (long)wm_protocols[1])
1425 /* WM_SAVE_YOURSELF */
1426 {
1427
1428 }
1429 break;
1430
1431
1432 default:
1433 break;
1434 }
1435
1436 numEvents--;
1437 if(numEvents)
1438 XNextEvent(g->dpy,&event);
1439 }
1440}
1441
1442
1443float deltaMove = 0;
1444
1445static int UpdatePosition(XEvent *event, Oinfo *o, Ginfo *g)
1446/******************************************************************************
1447 Update the scene position information using user input.
1448
1449 The routine will eventually block waiting for an event if block is True
1450 and the no events of interest show up due to the call to GetInput()
1451******************************************************************************/
1452{
1453int same, pointerX, pointerY, dx, dy;
1454char command;
1455double X, Y, Z;
1456
1457 X = Y = Z = 0.0;
1458
1459 same = 1;
1460
1461 pointerX = g->oldPointerX;
1462 pointerY = g->oldPointerY;
1463
1464 while(same) {
1465
1466/* dx, dy, dz are the amount to step about each axis every frame
1467 We want the scene to continue to rotate even if the user does
1468 not give any new input */
1469
1470/* Do not forget to put your automatic update variables into this if
1471 statement. Be careful somehow you can get MANY bugs with these! */
1472
1473 if((o->dX) || (o->dY) || (o->dZ)){
1474 same = 0;
1475 g->Block = 0;
1476 }else
1477 g->Block = 1;
1478
1479/* Get the input */
1480
1481 GetInput(event, &pointerX, &pointerY, &command, &same, g);
1482
1483/* Fill in code for your favorite keyboard and pointer controls */
1484
1485/* My default controls */
1486
1487/* Note: I do not move the origin which the scene is rotated about around.
1488 You may want to do oX += ???; oY += ???; oZ += ??? */
1489
1490 switch(command){
1491 case ' ' : break;
1492
1493 case 'm' :
1494 case 'M' : same = 0; g->helpMenu = !g->helpMenu;
1495 /*
1496 if(g->helpMenu == False){
1497 XUnmapWindow(g->dpy, g->helpWin);
1498 }else{
1499 XMapWindow(g->dpy, g->helpWin);
1500 }
1501 */
1502 break;
1503
1504 case 's' :
1505 case 'S' : same = 0; g->stereo = !g->stereo; g->modeChanged = 1;
1506 break;
1507
1508 case 'd' :
1509 case 'D' : same = 0; g->stereoBlue = !g->stereoBlue; g->modeChanged = 1;
1510 break;
1511
1512 case 'f' :
1513 case 'F' : same = 0; g->buffer = !g->buffer; g->modeChanged = 1;
1514 break;
1515
1516 case 'o' :
1517 case 'O' : same = 0; g->Relative = !g->Relative; break;
1518
1519 case 'w' :
1520 case 'W' : same = 0; g->renderMode = WIREFRAME; g->modeChanged = 1;
1521 break;
1522
1523 case 'e' :
1524 case 'E' : if(o->numPolys) {
1525 same = 0; g->renderMode = HIDDENLINE; g->modeChanged = 1;
1526 }
1527 break;
1528
1529 case 'r' :
1530 case 'R' : if(o->numPolys) {
1531 same = 0; g->renderMode = SOLID; g->modeChanged = 1;
1532 }
1533 break;
1534
1535 case 'l' : same = 0; o->tX -= deltaMove; break;
1536 case 'j' : same = 0; o->tY -= deltaMove; break;
1537 case 'k' : same = 0; o->tY += deltaMove; break;
1538 case 'h' : same = 0; o->tX += deltaMove; break;
1539 case 'i' : same = 0; o->tZ += deltaMove; break;
1540 case 'u' : same = 0; o->tZ -= deltaMove; break;
1541 case 'L' : same = 0; o->tX -= 5*deltaMove; break;
1542 case 'J' : same = 0; o->tY -= 5*deltaMove; break;
1543 case 'K' : same = 0; o->tY += 5*deltaMove; break;
1544 case 'H' : same = 0; o->tX += 5*deltaMove; break;
1545 case 'I' : same = 0; o->tZ += 5*deltaMove; break;
1546 case 'U' : same = 0; o->tZ -= 5*deltaMove; break;
1547 case '1' : same = 0; o->dX += 0.02; break;
1548 case '2' : same = 0; o->dX = 0.0 ; break;
1549 case '3' : same = 0; o->dX -= 0.02; break;
1550 case '4' : same = 0; o->dY -= 0.02; break;
1551 case '5' : same = 0; o->dY = 0.0 ; break;
1552 case '6' : same = 0; o->dY += 0.02; break;
1553 case '7' : same = 0; o->dZ += 0.02; break;
1554 case '8' : same = 0; o->dZ = 0.0 ; break;
1555 case '9' : same = 0; o->dZ -= 0.02; break;
1556 case 'x' : same = 0; X -= 0.03; break;
1557 case 'X' : same = 0; X += 0.03; break;
1558 case 'y' : same = 0; Y += 0.03; break;
1559 case 'Y' : same = 0; Y -= 0.03; break;
1560 case 'z' : same = 0; Z -= 0.03; break;
1561 case 'Z' : same = 0; Z += 0.03; break;
1562 case 'a' : same = 0; X -= 0.05; break;
1563 case 'A' : same = 0; X += 0.05; break;
1564 case 'b' : same = 0; Y += 0.05; break;
1565 case 'B' : same = 0; Y -= 0.05; break;
1566 case 'c' : same = 0; Z -= 0.05; break;
1567 case 'C' : same = 0; Z += 0.05; break;
1568 case '[' : same = 0;
1569 o->focus += 0.1;
1570 if((o->focus > 1.8))
1571 o->focus = 1.8;
1572 break;
1573 case ']' : same = 0;
1574 o->focus -= 0.1;
1575 if((o->focus < -0.8))
1576 o->focus = -0.8;
1577 break;
1578 case '{' : same = 0; o->BViewpointX -= 4.0; break;
1579 case '}' : same = 0; o->BViewpointX += 4.0; break;
1580
1581 case 'q' :
1582 case 'Q' : return(1);
1583
1584 default : {
1585
1586/* My pointer movement stuff */
1587
1588/* Only update if the movement was reasonably small */
1589
1590 dx = pointerX - g->oldPointerX;
1591 dy = pointerY - g->oldPointerY;
1592
1593 if((dy * dy <= SMALLMOVEMENT) &&
1594 (dx * dx <= SMALLMOVEMENT)){
1595
1596/* Rotate proportionally with the amount the pointer moved */
1597/* Note: I only control the X and Z axes by the pointer */
1598
1599 X -= (dy * POINTERRATIO);
1600 Z -= (dx * POINTERRATIO);
1601 same = 0;
1602 }
1603
1604 g->oldPointerY = pointerY;
1605 g->oldPointerX = pointerX;
1606 }
1607 }
1608 }
1609
1610/* Keep angles 0 - 6.28 */
1611 X = fmod(X + o->dX, TWOPI);
1612 Y = fmod(Y + o->dY, TWOPI);
1613 Z = fmod(Z + o->dZ, TWOPI);
1614
1615/* Fix up the angles */
1616
1617 if(g->Relative){
1618 o->X = fmod(X + o->X, TWOPI);
1619 o->Y = fmod(Y + o->Y, TWOPI);
1620 o->Z = fmod(Z + o->Z, TWOPI);
1621 }else{
1622 CalculateAngles(&(o->X), &(o->Y), &(o->Z), X, Y, Z);
1623 }
1624
1625 return quitApplication;
1626}
1627
1628
1629
1630static int clipSegment(float *pX, float *pY, float *qX, float *qY, int Pclip, int Qclip, float H, float V)
1631/******************************************************************************
1632 Calculate the portion of the projected line segment that is visible.
1633******************************************************************************/
1634{
1635register float PX, PY, QX, QY, dx, dy;
1636
1637 PX = *pX; QX = *qX;
1638 PY = *pY; QY = *qY;
1639
1640 dx = QX - PX;
1641 dy = QY - PY;
1642
1643/* Clip P first so it will be somewhere on the screen,
1644 if we cannot move P on screen the segment is not visible */
1645
1646/* See x3d.h for the meaning of the clipping flags */
1647
1648 switch(Pclip){
1649
1650 case 1 : /* 00001 */
1651 clipWithTop(PX, PY, dx, dy, V)
1652 if((PX < -H) || (PX > H))
1653 return 0;
1654 break;
1655
1656 case 2 : /* 00010 */
1657 clipWithBottom(PX, PY, dx, dy, V)
1658 if((PX < -H) || (PX > H))
1659 return 0;
1660 break;
1661
1662 case 4 : /* 00100 */
1663 clipWithLeftSide(PX, PY, dx, dy, H)
1664 if((PY < -V) || (PY > V))
1665 return 0;
1666 break;
1667
1668 case 5 : /* 00101 */
1669 clipWithTop(PX, PY, dx, dy, V)
1670 if((PX < -H) || (PX > H)){
1671 clipWithLeftSide(PX, PY, dx, dy, H)
1672 if((PY < -V) || (PY > V))
1673 return 0;
1674 }
1675 break;
1676
1677 case 6 : /* 00110 */
1678 clipWithBottom(PX, PY, dx, dy, V)
1679 if((PX < -H) || (PX > H)){
1680 clipWithLeftSide(PX, PY, dx, dy, H)
1681 if((PY < -V) || (PY > V))
1682 return 0;
1683 }
1684 break;
1685
1686 case 8 : /* 01000 */
1687 clipWithRightSide(PX, PY, dx, dy, H)
1688 if((PY < -V) || (PY > V))
1689 return 0;
1690 break;
1691
1692 case 9 : /* 01001 */
1693 clipWithTop(PX, PY, dx, dy, V)
1694 if((PX < -H) || (PX > H)){
1695 clipWithRightSide(PX, PY, dx, dy, H)
1696 if((PY < -V) || (PY > V))
1697 return 0;
1698 }
1699 break;
1700
1701 case 10 : /* 01010 */
1702 clipWithBottom(PX, PY, dx, dy, V)
1703 if((PX < -H) || (PX > H)){
1704 clipWithRightSide(PX, PY, dx, dy, H)
1705 if((PY < -V) || (PY > V))
1706 return 0;
1707 }
1708 break;
1709
1710 }
1711
1712/* P is now somewhere on screen, calculate where Q should be */
1713
1714 switch(Qclip){
1715
1716 case 1 : /* 00001 */
1717 clipWithTop(QX, QY, dx, dy, V)
1718 break;
1719
1720 case 2 : /* 00010 */
1721 clipWithBottom(QX, QY, dx, dy, V)
1722 break;
1723
1724 case 4 : /* 00100 */
1725 clipWithLeftSide(QX, QY, dx, dy, H)
1726 break;
1727
1728 case 5 : /* 00101 */
1729 clipWithTop(QX, QY, dx, dy, V)
1730 if(QX < -H)
1731 clipWithLeftSide(QX, QY, dx, dy, H)
1732 break;
1733
1734 case 6 : /* 00110 */
1735 clipWithBottom(QX, QY, dx, dy, V)
1736 if(QX < -H)
1737 clipWithLeftSide(QX, QY, dx, dy, H)
1738 break;
1739
1740 case 8 : /* 01000 */
1741 clipWithRightSide(QX, QY, dx, dy, H)
1742 break;
1743
1744 case 9 : /* 01001 */
1745 clipWithTop(QX, QY, dx, dy, V)
1746 if(QX > H)
1747 clipWithRightSide(QX, QY, dx, dy, H)
1748 break;
1749
1750 case 10 : /* 01010 */
1751 clipWithBottom(QX, QY, dx, dy, V)
1752 if(QX > H)
1753 clipWithRightSide(QX, QY, dx, dy, H)
1754 break;
1755
1756 case 21 : /* 10101 */
1757 clipWithTop(QX, QY, dx, dy, V)
1758 if(QX < -H)
1759 clipWithLeftSide(QX, QY, dx, dy, H)
1760 break;
1761
1762 case 22 : /* 10110 */
1763 clipWithBottom(QX, QY, dx, dy, V)
1764 if(QX < -H)
1765 clipWithLeftSide(QX, QY, dx, dy, H)
1766 break;
1767
1768 case 23 : /* 10111 */
1769 if(QY < PY)
1770 clipWithTop(QX, QY, dx, dy, V)
1771 else
1772 clipWithBottom(QX, QY, dx, dy, V)
1773 if(QX < -H)
1774 clipWithLeftSide(QX, QY, dx, dy, H)
1775 break;
1776
1777 case 25 : /* 11001 */
1778 clipWithTop(QX, QY, dx, dy, V)
1779 if(QX > H)
1780 clipWithRightSide(QX, QY, dx, dy, H)
1781 break;
1782
1783 case 26 : /* 11010 */
1784 clipWithBottom(QX, QY, dx, dy, V)
1785 if(QX > H)
1786 clipWithRightSide(QX, QY, dx, dy, H)
1787 break;
1788
1789 case 27 : /* 11011 */
1790 if(QY < PY)
1791 clipWithTop(QX, QY, dx, dy, V)
1792 else
1793 clipWithBottom(QX, QY, dx, dy, V)
1794 if(QX > H)
1795 clipWithRightSide(QX, QY, dx, dy, H)
1796 break;
1797
1798 case 29 : /* 11101 */
1799 if(QX < PX)
1800 clipWithRightSide(QX, QY, dx, dy, H)
1801 else
1802 clipWithLeftSide(QX, QY, dx, dy, H)
1803 if(QY > V)
1804 clipWithTop(QX, QY, dx, dy, V)
1805 break;
1806
1807 case 30 : /* 11110 */
1808 if(QX < PX)
1809 clipWithRightSide(QX, QY, dx, dy, H)
1810 else
1811 clipWithLeftSide(QX, QY, dx, dy, H)
1812 if(QY < -V)
1813 clipWithBottom(QX, QY, dx, dy, V)
1814 break;
1815
1816 case 31 : /* 11111 */
1817 if(QX < PX)
1818 clipWithRightSide(QX, QY, dx, dy, H)
1819 else
1820 clipWithLeftSide(QX, QY, dx, dy, H)
1821
1822 if((QY < -V) || (QY > V)) {
1823 if(*qY < PY)
1824 clipWithTop(QX, QY, dx, dy, V)
1825 else
1826 clipWithBottom(QX, QY, dx, dy, V)
1827 }
1828 break;
1829
1830 }
1831
1832 *pX = PX; *qX = QX;
1833 *pY = PY; *qY = QY;
1834 return 1;
1835}
1836
1837
1838
1839static void clip(Oinfo *o, Ginfo *g)
1840/******************************************************************************
1841 Clip a list of segments.
1842******************************************************************************/
1843{
1844register int PClipFlags, QClipFlags, Pclip, Qclip, Tclip;
1845register float H, V;
1846register short pX, pY, qX, qY;
1847float PX, PY, QX, QY;
1848segment *seg, *lastSeg;
1849point *P, *Q, *T;
1850XSegment *red, *blue;
1851long *redCol;
1852
1853 lastSeg = &(o->segs[o->numSegs]);
1854 seg = o->segs;
1855
1856 H = (float)g->winH;
1857 V = (float)g->winV;
1858
1859 red = &(g->redSegments[g->numberRed]);
1860 redCol = &(g->redColors[g->numRedColors]);
1861
1862 if((g->mono) || ((g->stereo) && (!(g->stereoBlue))) ||
1863 ((g->renderMode == WIREFRAME) && (!g->stereo))){
1864
1865 if(o->objClip){
1866
1867/* For every segment ... */
1868
1869 while(seg < lastSeg){
1870
1871 P = seg->P;
1872 if (P == 0) continue;
1873 PClipFlags = P->ClipFlags;
1874 Q = seg->Q;
1875 if (Q == 0) continue;
1876 QClipFlags = Q->ClipFlags;
1877
1878/* Optimization for best case */
1879
1880 if((PClipFlags | QClipFlags) == 0){
1881 if (seg->color) *redCol = seg->color->value;
1882 else *redCol = 0;
1883 redCol++;
1884 ((xsegment *)red)->P = P->R;
1885 ((xsegment *)red)->Q = Q->R;
1886 red++;
1887 }else{
1888
1889/* Red segments */
1890
1891/* Shuffle the bits around so we get the right configuration
1892 for the clipping function */
1893
1894 Pclip = (PClipFlags & RBmask) | ((PClipFlags & RLeftRight) >> 3);
1895 Qclip = (QClipFlags & RBmask) | ((QClipFlags & RLeftRight) >> 3);
1896
1897 if((Qclip | Pclip) == 0){
1898
1899 if (seg->color) *redCol = seg->color->value;
1900 else *redCol = 0;
1901 redCol++;
1902 red->x1 = P->R.x;
1903 red->y1 = P->R.y;
1904 red->x2 = Q->R.x;
1905 red->y2 = Q->R.y;
1906 red++;
1907
1908 }else{
1909
1910 if((Qclip & Pclip) == 0){
1911
1912/* We make P be a point in front of us if there is one in front,
1913 (it simplifies the code) */
1914
1915 if((Pclip > Qclip) || (Pclip & Behind)){
1916 T = P; P = Q; Q = T;
1917 Tclip = Pclip; Pclip = Qclip; Qclip = Tclip;
1918 }
1919
1920 PX = P->RX - H; PY = -(P->Y - V);
1921 QX = Q->RX - H; QY = -(Q->Y - V);
1922
1923 if(clipSegment(&PX, &PY, &QX, &QY, Pclip, Qclip, H, V)){
1924
1925 if (seg->color) *redCol = seg->color->value;
1926 else *redCol = 0;
1927 redCol++;
1928 red->x1 = (short)(PX + H);
1929 red->y1 = (short)(V - PY);
1930 red->x2 = (short)(QX + H);
1931 red->y2 = (short)(V - QY);
1932 red++;
1933
1934 }
1935 }
1936 }
1937 }
1938 seg++;
1939 }
1940 }else{
1941
1942/* Optimization for object completely visible */
1943
1944 if((g->renderMode == WIREFRAME) && (g->stereo)){
1945 while(seg < lastSeg){
1946 ((xsegment *)red)->P = seg->P->R;
1947 ((xsegment *)red)->Q = seg->Q->R;
1948 red++;
1949 seg++;
1950 }
1951 }else{
1952 while(seg < lastSeg){
1953
1954 if (seg->color) *redCol = seg->color->value;
1955 else {*redCol = 0; break;}
1956 redCol++;
1957 ((xsegment *)red)->P = seg->P->R;
1958 ((xsegment *)red)->Q = seg->Q->R;
1959 red++;
1960 seg++;
1961 }
1962 }
1963 }
1964 }else{
1965 blue = &(g->blueSegments[g->numberBlue]);
1966
1967 if(o->objClip){
1968 while(seg < lastSeg){
1969
1970 P = seg->P; Q = seg->Q;
1971 PClipFlags = P->ClipFlags;
1972 QClipFlags = Q->ClipFlags;
1973
1974/* Optimization for best case */
1975
1976 if((PClipFlags | QClipFlags) == 0){
1977
1978 pX = P->R.x; pY = P->R.y;
1979 qX = Q->R.x; qY = Q->R.y;
1980 red->x1 = pX;
1981 red->y1 = pY;
1982 red->x2 = qX;
1983 red->y2 = qY;
1984 red++;
1985 pX = P->sBX; qX = Q->sBX;
1986 blue->x1 = pX;
1987 blue->y1 = pY;
1988 blue->x2 = qX;
1989 blue->y2 = qY;
1990 blue++;
1991
1992 }else{
1993
1994/* Red segments */
1995
1996/* Shuffle the bits around so we get the right configuration
1997 for the clipping function */
1998
1999 Pclip = (PClipFlags & RBmask) | ((PClipFlags & RLeftRight) >> 3);
2000 Qclip = (QClipFlags & RBmask) | ((QClipFlags & RLeftRight) >> 3);
2001
2002 if((Qclip | Pclip) == 0){
2003
2004 red->x1 = P->R.x;
2005 red->y1 = P->R.y;
2006 red->x2 = Q->R.x;
2007 red->y2 = Q->R.y;
2008 red++;
2009
2010 }else{
2011
2012 if((Qclip & Pclip) == 0){
2013
2014/* We make P be a point in front of us if there is one in front,
2015 (it simplifies the code) */
2016
2017 if((Pclip > Qclip) || (Pclip & Behind)){
2018 T = P; P = Q; Q = T;
2019 Tclip = Pclip; Pclip = Qclip; Qclip = Tclip;
2020 }
2021
2022 PX = P->RX - H; PY = -(P->Y - V);
2023 QX = Q->RX - H; QY = -(Q->Y - V);
2024
2025 if(clipSegment(&PX, &PY, &QX, &QY, Pclip, Qclip, H, V)){
2026
2027 red->x1 = (short)(PX + H);
2028 red->y1 = (short)(V - PY);
2029 red->x2 = (short)(QX + H);
2030 red->y2 = (short)(V - QY);
2031 red++;
2032
2033 }
2034
2035 }
2036 }
2037
2038/* Blue segments */
2039
2040 PClipFlags = P->ClipFlags;
2041 QClipFlags = Q->ClipFlags;
2042
2043/* Shuffle the bits around so we get the right configuration
2044 for the clipping function */
2045
2046 Pclip = (PClipFlags & Rmask);
2047 Qclip = (QClipFlags & Rmask);
2048
2049 if((Qclip | Pclip) == 0){
2050
2051 blue->x1 = P->sBX;
2052 blue->y1 = P->R.y;
2053 blue->x2 = Q->sBX;
2054 blue->y2 = Q->R.y;
2055 blue++;
2056
2057 }else{
2058 if((Qclip & Pclip) == 0){
2059
2060/* We make P be a point in front of us if there is one in front,
2061 (it simplifies the code) */
2062
2063 if((Pclip > Qclip) || (Pclip & Behind)){
2064 T = P; P = Q; Q = T;
2065 Tclip = Pclip; Pclip = Qclip; Qclip = Tclip;
2066 }
2067
2068/* check the bits, clip if necessary, and add the segment to the
2069 appropriate buffer if visible */
2070
2071 PX = P->BX - H; PY = -(P->Y - V);
2072 QX = Q->BX - H; QY = -(Q->Y - V);
2073
2074 if(clipSegment(&PX, &PY, &QX, &QY, Pclip, Qclip, H, V)){
2075
2076 blue->x1 = (short)(PX + H);
2077 blue->y1 = (short)(V - PY);
2078 blue->x2 = (short)(QX + H);
2079 blue->y2 = (short)(V - QY);
2080 blue++;
2081
2082 }
2083 }
2084 }
2085 }
2086 seg++;
2087 }
2088 }else{
2089
2090/* Optimization for object completely visible */
2091
2092 while(seg < lastSeg){
2093 P = seg->P; Q = seg->Q;
2094 pX = P->R.x; pY = P->R.y;
2095 qX = Q->R.x; qY = Q->R.y;
2096 red->x1 = pX;
2097 red->y1 = pY;
2098 red->x2 = qX;
2099 red->y2 = qY;
2100 red++;
2101 pX = P->sBX; qX = Q->sBX;
2102 blue->x1 = pX;
2103 blue->y1 = pY;
2104 blue->x2 = qX;
2105 blue->y2 = qY;
2106 blue++;
2107 seg++;
2108 }
2109
2110 }
2111
2112 g->numberBlue = blue - g->blueSegments;
2113 }
2114
2115 g->numRedColors = redCol - g->redColors;
2116 g->numberRed = red - g->redSegments;
2117}
2118
2119
2120#ifdef USE_INTS
2121
2122/* The REDROTATE macro does 3 rotates, 2 translates, 1 projection */
2123
2124#define REDROTATE \
2125 r8 = p0->x + c16; \
2126 r5 = p0->y + c17; \
2127 r2 = ((r8 * c5 + r5 * c6) >> SHIFT); \
2128 r7 = ((r5 * c5 - r8 * c6) >> SHIFT); \
2129 r8 = p0->z + c18; \
2130 r5 = ((r7 * c3 + r8 * c4) >> SHIFT) + c12; \
2131 r6 = ((r8 * c3 - r7 * c4) >> SHIFT); \
2132 r7 = c7 + ((((r6 * c1 - r2 * c2) >> SHIFT) + c13) * c0) / r5; \
2133 r8 = c9 - ((((r2 * c1 + r6 * c2) >> SHIFT) + c11) * c0) / r5; \
2134 r5 = (c0 * 8192) / r5
2135
2136/* Project the blue point too */
2137
2138#define STEREOROTATE \
2139 r8 = p0->x + c16; \
2140 r5 = p0->y + c17; \
2141 r2 = ((r8 * c5 + r5 * c6) >> SHIFT); \
2142 r7 = ((r5 * c5 - r8 * c6) >> SHIFT); \
2143 r8 = p0->z + c18; \
2144 r5 = ((r7 * c3 + r8 * c4) >> SHIFT) + c12; \
2145 r6 = ((r8 * c3 - r7 * c4) >> SHIFT); \
2146 r7 = c7 + ((((r6 * c1 - r2 * c2) >> SHIFT) + c13) * c0) / r5; \
2147 r8 = c9 - ((((r2 * c1 + r6 * c2) >> SHIFT) + c11) * c0) / r5; \
2148 r9 = r8 - c15 - (c0 * c14) / r5; \
2149 r5 = (c0 * 8192) / r5
2150
2151#else
2152
2153/* The REDROTATE macro does 3 rotates, 2 translates, 1 projection */
2154
2155#define REDROTATE \
2156 r8 = p0->x + c16; \
2157 r5 = p0->y + c17; \
2158 r2 = r8 * c5 + r5 * c6; \
2159 r7 = r5 * c5 - r8 * c6; \
2160 r8 = p0->z + c18; \
2161 r5 = c0 / (r7 * c3 + r8 * c4 + c12); \
2162 r6 = r8 * c3 - r7 * c4; \
2163 r7 = c7 + (r6 * c1 - r2 * c2 + c13) * r5; \
2164 r8 = c9 - (r2 * c1 + r6 * c2 + c11) * r5
2165
2166#define STEREOROTATE \
2167 REDROTATE; \
2168 r9 = r8 - c15 - r5 * c14
2169
2170#endif
2171
2172
2173/* Set all the red clipping flags */
2174
2175#define REDCLIPFLAGS \
2176 (r5 > 0) * ALLmask ^ ((r7 < 0) | (r7 > c10) << ClipWithBottom | \
2177 (r8 > c8) << RClipWithRight | (r8 < 0) << RClipWithLeft)
2178
2179/* Set all the red and blue clipping flags */
2180
2181#define STEREOCLIPFLAGS \
2182 (r5 > 0) * ALLmask ^ ((r7 < 0) | (r7 > c10) << ClipWithBottom | \
2183 (r8 > c8) << RClipWithRight | (r8 < 0) << RClipWithLeft | \
2184 (r9 > c8) << BClipWithRight | (r9 < 0) << BClipWithLeft)
2185
2186
2187
2188static void rotate(Oinfo *o, Ginfo *g)
2189/******************************************************************************
2190 Rotate, project, and set the clipping flags for a list of points.
2191******************************************************************************/
2192{
2193register number r2,r5,r6,r7,r8,r9;
2194register point *p0;
2195register number c1,c2,c3,c4,c5,c6;
2196register point *p1;
2197register number c0,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16,c17,c18;
2198register int objClip;
2199register short RX, BX;
2200
2201 p0 = o->bounds; p1 = &(o->bounds[NUMBOUNDS]); c0 = (number)o->viewpointY;
2202 c1 = (number)(cos(o->Y) * TRIG_ADJ); c2 = (number)(sin(o->Y) * TRIG_ADJ);
2203 c3 = (number)(cos(o->X) * TRIG_ADJ); c4 = (number)(sin(o->X) * TRIG_ADJ);
2204 c5 = (number)(cos(o->Z) * TRIG_ADJ); c6 = (number)(sin(o->Z) * TRIG_ADJ);
2205 c7 = (number)g->winH; c8 = (number)(2.0 * g->winH);
2206 c9 = (number)g->winV; c10 = (number)(2.0 * g->winV);
2207 c11 = (number)o->tX; c12 = (number)(o->tY - o->viewpointY);
2208 c13 = (number)o->tZ; c14 = (number)o->BViewpointX;
2209 c15 = (number)(o->BViewpointX * o->focus); c16 = (number)-o->oX;
2210 c17 = (number)-o->oY; c18 = (number)-o->oZ;
2211
2212 objClip = 0;
2213 o->Hmin2 = o->Hmin1; o->Vmin2 = o->Vmin1;
2214 o->Hmax2 = o->Hmax1; o->Vmax2 = o->Vmax1;
2215 o->Hmin1 = o->Hmin; o->Vmin1 = o->Vmin;
2216 o->Hmax1 = o->Hmax; o->Vmax1 = o->Vmax;
2217 o->Hmin = c8; o->Vmin = c10;
2218 o->Hmax = 0; o->Vmax = 0;
2219
2220/* What happens to the bounding box? */
2221
2222 while(p0 != p1){
2224
2225 if(STEREOCLIPFLAGS)
2226 objClip = 1;
2227
2228 if((int)r7 < o->Vmin){ o->Vmin = (int)r7; }
2229 if((int)r7 > o->Vmax){ o->Vmax = (int)r7; }
2230
2231 if((int)r8 < o->Hmin){ o->Hmin = (int)r8; }
2232 if((int)r8 > o->Hmax){ o->Hmax = (int)r8; }
2233
2234 if((g->stereo) && (g->stereoBlue)){
2235 if((int)r9 < o->Hmin){ o->Hmin = (int)r9; }
2236 if((int)r9 > o->Hmax){ o->Hmax = (int)r9; }
2237 }
2238
2239 p0++;
2240 }
2241
2242/* Update screen clearing, pix copying variables */
2243
2244 if((g->modeChanged) || (objClip)){
2245 o->Hmin = o->Hmin1 = o->Hmin2 = 0;
2246 o->Vmin = o->Vmin1 = o->Vmin2 = 0;
2247 o->Hmax = o->Hmax1 = o->Hmax2 = g->winX;
2248 o->Vmax = o->Vmax1 = o->Vmax2 = g->winY;
2249 }else{
2250 if(o->Hmin < 0){o->Hmin = 0;}
2251 if(o->Vmin < 0){o->Vmin = 0;}
2252 if(o->Hmax > c8){o->Hmax = c8;}
2253 if(o->Vmax > c10){o->Vmax = c10;}
2254
2255 if(o->Hmin1 < o->Hmin2){o->Hmin2 = o->Hmin1;}
2256 if(o->Vmin1 < o->Vmin2){o->Vmin2 = o->Vmin1;}
2257 if(o->Hmax1 > o->Hmax2){o->Hmax2 = o->Hmax1;}
2258 if(o->Vmax1 > o->Vmax2){o->Vmax2 = o->Vmax1;}
2259 }
2260
2261 o->fillX = o->Hmin2; o->fillY = o->Vmin2;
2262 o->fillWidth = o->Hmax2 - o->Hmin2 + 1;
2263 o->fillHeight = o->Vmax2 - o->Vmin2 + 1;
2264
2265 if(o->Hmin < o->Hmin2){o->Hmin2 = o->Hmin;}
2266 if(o->Vmin < o->Vmin2){o->Vmin2 = o->Vmin;}
2267 if(o->Hmax > o->Hmax2){o->Hmax2 = o->Hmax;}
2268 if(o->Vmax > o->Vmax2){o->Vmax2 = o->Vmax;}
2269
2270 o->copyX = o->Hmin2; o->copyY = o->Vmin2;
2271 o->copyWidth = o->Hmax2 - o->Hmin2 + 1;
2272 o->copyHeight = o->Vmax2 - o->Vmin2 + 1;
2273
2274 o->objClip = objClip;
2275 p0 = o->points;
2276 p1 = &(o->points[o->numPoints]);
2277
2278 if(objClip){
2279
2280/* The object is not totally visible, do clipping */
2281
2282 if((g->stereo) && (g->stereoBlue)){
2283 if(g->renderMode == WIREFRAME){
2284 while(p0 != p1){
2286 p0->Y = (float)r7; p0->R.y = (short)r7;
2287 p0->RX = (float)r8; p0->R.x = (short)r8;
2288 p0->BX = (float)r9; p0->sBX = (short)r9;
2289 p0->ClipFlags = STEREOCLIPFLAGS;
2290 p0++;
2291 }
2292 }else{
2293
2294 while(p0 != p1){
2296 p0->dist = (float)r5;
2297 p0->Y = (float)r7; p0->R.y = (short)r7;
2298 p0->RX = (float)r8; p0->R.x = (short)r8;
2299 p0->BX = (float)r9; p0->sBX = (short)r9;
2300 p0->ClipFlags = STEREOCLIPFLAGS;
2301 p0++;
2302 }
2303 }
2304 }else{
2305 if(g->renderMode == WIREFRAME){
2306 while(p0 != p1){
2307 REDROTATE;
2308 p0->Y = (float)r7; p0->R.y = (short)r7;
2309 p0->RX = (float)r8; p0->R.x = (short)r8;
2310 p0->ClipFlags = REDCLIPFLAGS;
2311 p0++;
2312 }
2313 }else{
2314
2315 while(p0 != p1){
2316 REDROTATE;
2317 p0->dist = (float)r5;
2318 p0->Y = (float)r7; p0->R.y = (short)r7;
2319 p0->RX = (float)r8; p0->R.x = (short)r8;
2320 p0->ClipFlags = REDCLIPFLAGS;
2321 p0++;
2322 }
2323 }
2324 }
2325 }else{
2326
2327/* The object is totally visible, skip clipping */
2328
2329 if((g->stereo) && (g->stereoBlue)){
2330 if(g->renderMode == WIREFRAME){
2331 while(p0 != p1){
2333 p0->R.y = (short)r7;
2334 p0->R.x = (short)r8;
2335 p0->sBX = (short)r9;
2336 p0++;
2337 }
2338 }else{
2339
2340 while(p0 != p1){
2342 p0->dist = (float)r5;
2343 p0->R.y = (short)r7;
2344
2345 RX = r8;
2346 p0->R.x = (float)RX;
2347
2348 BX = r9;
2349 p0->sBX = (float)BX;
2350
2351 p0++;
2352 }
2353 }
2354 }else{
2355 if(g->renderMode == WIREFRAME){
2356 while(p0 != p1){
2357 REDROTATE;
2358 p0->R.y = (short)r7;
2359 p0->R.x = (short)r8;
2360 p0++;
2361 }
2362 }else{
2363
2364 while(p0 != p1){
2365 REDROTATE;
2366 p0->dist = (float)r5;
2367
2368 p0->R.y = (short)r7;
2369 RX = (short)r8;
2370 p0->R.x = (float)RX;
2371
2372 p0++;
2373 }
2374 }
2375 }
2376 }
2377}
2378
2379
2380
2381
2382static void DrawSegments(Display *display, Window win, GC gc, XSegment segs1[], int numSegs, Ginfo *g)
2383/******************************************************************************
2384 Thanks to Mark Cook for the suggestion to pay attention the the
2385 maximum request size of the X server!
2386******************************************************************************/
2387{
2388int requestSize, evenAmount, remainder1, index1;
2389
2390 requestSize = g->requestSize;
2391 evenAmount = (numSegs / requestSize) * requestSize;
2392 remainder1 = numSegs - evenAmount;
2393
2394 index1 = 0;
2395
2396 while(index1 < evenAmount){
2397 XDrawSegments(display, win, gc, &segs1[index1], requestSize);
2398 index1 += requestSize;
2399 }
2400
2401 if(remainder1 > 0)
2402 XDrawSegments(display, win, gc, &segs1[index1], remainder1);
2403}
2404
2405
2406
2407static void DrawLines(Oinfo *o, Ginfo *g, int mode)
2408/******************************************************************************
2409 Draw lines for the three display modes.
2410******************************************************************************/
2411{
2413long lastColor;
2414int lastChange, index1;
2415
2416 dest = g->dest;
2417
2418 switch(mode){
2419
2420 case BW:
2421 XSetForeground(g->dpy, g->gc, g->black);
2422 XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
2423 o->fillWidth, o->fillHeight);
2424 XSetForeground(g->dpy, g->gc, g->white);
2425 DrawSegments (g->dpy, dest, g->gc, g->redSegments, g->numberRed, g);
2426 break;
2427
2428 case STEREO:
2429
2430 XSetForeground(g->dpy, g->gc, (long)g->Black);
2431 XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
2432 o->fillWidth, o->fillHeight);
2433
2434 XSetForeground(g->dpy, g->gc, (long)g->Red);
2435 DrawSegments(g->dpy, dest, g->gc, g->redSegments, g->numberRed, g);
2436
2437 if(g->stereoBlue){
2438
2439 XSetFunction (g->dpy, g->gc, GXor);
2440
2441 XSetForeground(g->dpy, g->gc, (long)g->Blue);
2442 DrawSegments(g->dpy, dest, g->gc, g->blueSegments, g->numberBlue,
2443 g);
2444
2445 XSetFunction (g->dpy, g->gc, GXcopy);
2446 }
2447
2448 break;
2449
2450 case COLOR:
2451
2452 XSetForeground(g->dpy, g->gc, g->Black);
2453 XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
2454 o->fillWidth, o->fillHeight);
2455
2456 lastChange = 4;
2457 lastColor = g->redColors[lastChange];
2458
2459 for(index1 = 5; index1 < g->numberRed; index1++){
2460 if(g->redColors[index1] != lastColor){
2461 XSetForeground(g->dpy, g->gc, lastColor);
2462 DrawSegments(g->dpy, dest, g->gc, &(g->redSegments[lastChange]),
2463 index1 - lastChange, g);
2464 lastChange = index1;
2465 lastColor = g->redColors[lastChange];
2466 }
2467 }
2468
2469 XSetForeground(g->dpy, g->gc, lastColor);
2470 DrawSegments(g->dpy, dest, g->gc, &(g->redSegments[lastChange]),
2471 g->numberRed - lastChange, g);
2472
2473 break;
2474
2475 default:
2476 break;
2477 }
2478}
2479
2480
2481
2482static void DrawHiddenLines(Oinfo *o, Ginfo *g, int mode)
2483/******************************************************************************
2484 Draw polygon outlines using painter algorithm for the three display modes.
2485******************************************************************************/
2486{
2487register int index1, npoints, numPolys;
2488register polygon *poly, **list1;
2489register point **pointPtr, **lastPointPtr;
2491
2492_XPoint points1[512], *XPointPtr;
2493 void *ptrp = points1;
2494 dest = g->dest;
2495 numPolys = o->numPolys;
2496 list1 = o->list;
2497
2498 sort(list1, numPolys);
2499
2500 switch(mode){
2501
2502 case BW:
2503
2504 XSetForeground(g->dpy, g->gc, g->black);
2505 XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
2506 o->fillWidth, o->fillHeight);
2507
2508 for(index1 = 0; index1 < numPolys; index1++){
2509
2510 poly = list1[index1];
2511 XPointPtr = points1;
2512 npoints = poly->numPoints;
2513 pointPtr = poly->points;
2514 lastPointPtr = &(poly->points[npoints]);
2515
2516 while(pointPtr < lastPointPtr){
2517 *XPointPtr = (*pointPtr)->R;
2518 XPointPtr++;
2519 pointPtr++;
2520 }
2521
2522 XSetForeground(g->dpy, g->gc, g->black);
2523 XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
2524 CoordModeOrigin);
2525 points1[npoints] = points1[0];
2526 XSetForeground(g->dpy, g->gc, g->white);
2527 XDrawLines(g->dpy, dest, g->gc, ptrp, npoints + 1,
2528 CoordModeOrigin);
2529 }
2530
2531 XSetFillStyle(g->dpy, g->gc, FillSolid);
2532 break;
2533
2534 case STEREO:
2535
2536 XSetForeground(g->dpy, g->gc, g->stereoBlack);
2537 XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
2538 o->fillWidth, o->fillHeight);
2539
2540 XSetPlaneMask(g->dpy, g->gc, g->redMask);
2541
2542 for(index1 = 0; index1 < numPolys; index1++){
2543 poly = list1[index1];
2544 XPointPtr = points1;
2545 npoints = poly->numPoints;
2546 pointPtr = poly->points;
2547 lastPointPtr = &(poly->points[npoints]);
2548
2549 while(pointPtr < lastPointPtr){
2550 *XPointPtr = (*pointPtr)->R;
2551 XPointPtr++;
2552 pointPtr++;
2553 }
2554
2555 XSetForeground(g->dpy, g->gc, g->stereoBlack);
2556 XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
2557 CoordModeOrigin);
2558 points1[npoints] = points1[0];
2559 XSetForeground(g->dpy, g->gc, poly->color->stereoColor);
2560 XDrawLines(g->dpy, dest, g->gc, ptrp, npoints + 1,
2561 CoordModeOrigin);
2562 }
2563
2564 if(g->stereoBlue){
2565 XSetPlaneMask(g->dpy, g->gc, g->blueMask);
2566
2567 for(index1 = 0; index1 < numPolys; index1++){
2568 poly = list1[index1];
2569 XPointPtr = points1;
2570 npoints = poly->numPoints;
2571 pointPtr = poly->points;
2572 lastPointPtr = &(poly->points[npoints]);
2573
2574 while(pointPtr < lastPointPtr){
2575 XPointPtr->x = (*pointPtr)->sBX;
2576 XPointPtr->y = (*pointPtr)->R.y;
2577 XPointPtr++;
2578 pointPtr++;
2579 }
2580
2581 XSetForeground(g->dpy, g->gc, g->stereoBlack);
2582 XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
2583 CoordModeOrigin);
2584 points1[npoints] = points1[0];
2585 XSetForeground(g->dpy, g->gc, poly->color->stereoColor);
2586 XDrawLines(g->dpy, dest, g->gc, ptrp, npoints + 1,
2587 CoordModeOrigin);
2588 }
2589 }
2590 XSetPlaneMask(g->dpy, g->gc, AllPlanes);
2591 break;
2592
2593 case COLOR:
2594
2595 XSetForeground(g->dpy, g->gc, g->Black);
2596 XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
2597 o->fillWidth, o->fillHeight);
2598
2599 for(index1 = 0; index1 < numPolys; index1++){
2600 poly = list1[index1];
2601 XPointPtr = points1;
2602 npoints = poly->numPoints;
2603 pointPtr = poly->points;
2604 lastPointPtr = &(poly->points[npoints]);
2605
2606 while(pointPtr < lastPointPtr){
2607 *XPointPtr = (*pointPtr)->R;
2608 XPointPtr++;
2609 pointPtr++;
2610 }
2611
2612 XSetForeground(g->dpy, g->gc, g->Black);
2613 XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
2614 CoordModeOrigin);
2615
2616 points1[npoints] = points1[0];
2617 XSetForeground(g->dpy, g->gc, poly->color->value);
2618 XDrawLines(g->dpy, dest, g->gc, ptrp, npoints + 1,
2619 CoordModeOrigin);
2620 }
2621
2622 break;
2623
2624 default:
2625 break;
2626 }
2627}
2628
2629
2630
2631static void DrawPolys(Oinfo *o, Ginfo *g, int mode)
2632/******************************************************************************
2633 Draw polygons using painter algorithm for the three display modes.
2634******************************************************************************/
2635{
2636register int index1, npoints, numPolys;
2637register polygon *poly, **list1;
2638register point **pointPtr, **lastPointPtr;
2640_XPoint points1[512], *XPointPtr;
2641long lastColor;
2642
2643 void *ptrp = points1;
2644 dest = g->dest;
2645 numPolys = o->numPolys;
2646 list1 = o->list;
2647
2648 sort(list1, numPolys);
2649
2650 switch(mode){
2651
2652 case BW:
2653
2654 XSetForeground(g->dpy, g->gc, g->black);
2655 XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
2656 o->fillWidth, o->fillHeight);
2657 XSetForeground(g->dpy, g->gc, g->white);
2658 XSetBackground(g->dpy, g->gc, g->black);
2659 XSetFillStyle(g->dpy, g->gc, FillOpaqueStippled);
2660
2661 for(index1 = 0; index1 < numPolys; index1++){
2662
2663 poly = list1[index1];
2664 XPointPtr = points1;
2665 XSetStipple(g->dpy, g->gc, g->stipple[poly->color->stipple]);
2666 npoints = poly->numPoints;
2667 pointPtr = poly->points;
2668 lastPointPtr = &(poly->points[npoints]);
2669
2670 while(pointPtr < lastPointPtr){
2671 *XPointPtr = (*pointPtr)->R;
2672 XPointPtr++;
2673 pointPtr++;
2674 }
2675
2676 XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
2677 CoordModeOrigin);
2678 }
2679
2680 XSetFillStyle(g->dpy, g->gc, FillSolid);
2681 break;
2682
2683 case STEREO:
2684
2685 XSetForeground(g->dpy, g->gc, g->stereoBlack);
2686 XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
2687 o->fillWidth, o->fillHeight);
2688 lastColor = g->stereoBlack;
2689
2690 XSetPlaneMask(g->dpy, g->gc, g->redMask);
2691
2692 for(index1 = 0; index1 < numPolys; index1++){
2693 poly = list1[index1];
2694 XPointPtr = points1;
2695 if(poly->color->stereoColor != lastColor){
2696 XSetForeground(g->dpy, g->gc, poly->color->stereoColor);
2697 lastColor = poly->color->stereoColor;
2698 }
2699 npoints = poly->numPoints;
2700 pointPtr = poly->points;
2701 lastPointPtr = &(poly->points[npoints]);
2702
2703 while(pointPtr < lastPointPtr){
2704 *XPointPtr = (*pointPtr)->R;
2705 XPointPtr++;
2706 pointPtr++;
2707 }
2708
2709 XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
2710 CoordModeOrigin);
2711 }
2712
2713 if(g->stereoBlue){
2714 XSetPlaneMask(g->dpy, g->gc, g->blueMask);
2715
2716 for(index1 = 0; index1 < numPolys; index1++){
2717 poly = list1[index1];
2718 XPointPtr = points1;
2719 if(poly->color->stereoColor != lastColor){
2720 XSetForeground(g->dpy, g->gc, poly->color->stereoColor);
2721 lastColor = poly->color->stereoColor;
2722 }
2723 npoints = poly->numPoints;
2724 pointPtr = poly->points;
2725 lastPointPtr = &(poly->points[npoints]);
2726
2727 while(pointPtr < lastPointPtr){
2728 XPointPtr->x = (*pointPtr)->sBX;
2729 XPointPtr->y = (*pointPtr)->R.y;
2730 XPointPtr++;
2731 pointPtr++;
2732 }
2733
2734 XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
2735 CoordModeOrigin);
2736 }
2737 }
2738 XSetPlaneMask(g->dpy, g->gc, AllPlanes);
2739 break;
2740
2741 case COLOR:
2742
2743 XSetForeground(g->dpy, g->gc, g->Black);
2744 XFillRectangle(g->dpy, dest, g->gc, o->fillX, o->fillY,
2745 o->fillWidth, o->fillHeight);
2746 lastColor = g->Black;
2747
2748 for(index1 = 0; index1 < numPolys; index1++){
2749 poly = list1[index1];
2750 XPointPtr = points1;
2751 if(poly->color->value != lastColor){
2752 XSetForeground(g->dpy, g->gc, poly->color->value);
2753 lastColor = poly->color->value;
2754 }
2755 npoints = poly->numPoints;
2756 pointPtr = poly->points;
2757 lastPointPtr = &(poly->points[npoints]);
2758
2759 while(pointPtr < lastPointPtr){
2760 *XPointPtr = (*pointPtr)->R;
2761 XPointPtr++;
2762 pointPtr++;
2763 }
2764
2765 XFillPolygon(g->dpy, dest, g->gc, ptrp, npoints, Convex,
2766 CoordModeOrigin);
2767 }
2768
2769 break;
2770
2771 default:
2772 break;
2773 }
2774}
2775
2776
2777
2778static void BeginImage(Oinfo *o, Ginfo *g)
2779/******************************************************************************
2780 Prepare to draw some x3d objects.
2781******************************************************************************/
2782{
2783
2784/* Try to get rid of a few of the mode change glitches (several exist yet) */
2785 if (o) { } /* use unused argument */
2786 if(g->modeChanged){
2787 XSetPlaneMask(g->dpy, g->gc, AllPlanes);
2788 if((g->mono) || (g->depth == ONE)){
2789 XSetForeground(g->dpy, g->gc, g->black);
2790 }else{
2791 if(g->stereo){
2792 XSetForeground(g->dpy, g->gc, (long)g->Black);
2793 }else{
2794 XSetForeground(g->dpy, g->gc, g->Black);
2795 }
2796 }
2797
2798 XFillRectangle(g->dpy, g->pix, g->gc, 0, 0, g->winX, g->winY);
2799 XFillRectangle(g->dpy, g->win, g->gc, 0, 0, g->winX, g->winY);
2800 }
2801
2802 if(g->buffer){
2803 if((g->mono) || (g->depth != EIGHT)){
2804 g->dest = g->pix;
2805 }else{
2806 if((g->numColors > BUFFER_CMAP) || (((g->renderMode == SOLID) ||
2807 (g->renderMode == HIDDENLINE)) && (g->stereo))){
2808 g->dest = g->pix;
2809 }else{
2810 g->dest = g->win;
2811
2812 if(g->ColorSelect){
2813 XSetPlaneMask(g->dpy, g->gc, BUFFER1);
2814 }else{
2815 XSetPlaneMask(g->dpy, g->gc, BUFFER0);
2816 }
2817 }
2818 }
2819 }else{
2820 g->dest = g->win;
2821 }
2822}
2823
2824
2825
2826static void DrawObject(Oinfo *o, Ginfo *g)
2827/******************************************************************************
2828 Draw an x3d objext to the screen. Be sure to draw the objects back to
2829 front when calling this function.
2830******************************************************************************/
2831{
2832
2833/* rotate the object */
2834
2835 rotate(o, g);
2836
2837/* Clip against the screen edges */
2838
2839 clip(o, g);
2840
2841/* Draw in the proper render mode */
2842
2843 switch(g->renderMode){
2844
2845 case WIREFRAME:
2846 if((g->mono) || (g->depth == ONE)){
2847 DrawLines(o, g, BW);
2848 }else{
2849 if(g->stereo){
2850 DrawLines(o, g, STEREO);
2851 }else{
2852 DrawLines(o, g, COLOR);
2853 }
2854 }
2855 break;
2856
2857 case HIDDENLINE:
2858 if((g->mono) || (g->depth == ONE)){
2859 DrawHiddenLines(o, g, BW);
2860 }else{
2861 if(g->stereo){
2863 }else{
2864 DrawHiddenLines(o, g, COLOR);
2865 }
2866 }
2867 break;
2868
2869 case SOLID:
2870 if((g->mono) || (g->depth == ONE)){
2871 DrawPolys(o, g, BW);
2872 }else{
2873 if(g->stereo){
2874 DrawPolys(o, g, STEREO);
2875 }else{
2876 DrawPolys(o, g, COLOR);
2877 }
2878 }
2879 break;
2880
2881 default :
2882 fprintf(stderr, "Unknown Render Mode!\n");
2883 return;
2884 break;
2885 }
2886
2887/* Reset the number of lines (We always keep the purple rectangle) */
2888
2889 g->numberRed = 4;
2890 g->numberBlue = 4;
2891 g->numRedColors = 4;
2892 g->modeChanged = 0;
2893}
2894
2895
2896
2897static void EndImage(Oinfo *o, Ginfo *g)
2898/******************************************************************************
2899 Finish drawing x3d objects.
2900******************************************************************************/
2901{
2902
2903/* Colormap double buffer? */
2904
2905 if((g->depth == EIGHT) && (!(g->mono)) && (g->numColors <= BUFFER_CMAP) &&
2906 (!((g->stereo) && (g->renderMode == HIDDENLINE))) &&
2907 (!((g->stereo) && (g->renderMode == SOLID)))){
2908 g->ColorSelect = !g->ColorSelect;
2909
2910 if((g->stereo) && (g->renderMode == WIREFRAME) && (!(g->modeChanged))){
2911 XStoreColors(g->dpy, g->colormap, g->wireframeColors[g->ColorSelect],
2912 12);
2913 }else{
2914 XStoreColors(g->dpy, g->colormap, g->cmapColors[g->ColorSelect], 256);
2915 }
2916 }else{
2917
2918/* Stereo solid, wireframe? */
2919
2920 if(g->depth == EIGHT){
2921 if(((g->renderMode == SOLID) || (g->renderMode == HIDDENLINE))
2922 && (g->stereo)){
2923 XStoreColors(g->dpy, g->colormap, g->cmapColors[2], 256);
2924 }else{
2925 XStoreColors(g->dpy, g->colormap, g->cmapColors[g->ColorSelect],
2926 256);
2927 }
2928 }
2929
2930/* generic */
2931
2932 if(g->buffer){
2933 XCopyArea(g->dpy, g->pix, g->win, g->gc, o->copyX, o->copyY,
2934 o->copyWidth, o->copyHeight, o->copyX, o->copyY);
2935 }
2936 }
2937
2938 XFlush(g->dpy);
2939}
2940
2941
2942
2943
2945/******************************************************************************
2946 Make polygon pointer array
2947******************************************************************************/
2948{
2949
2950 /*
2951 * Make polygon pointer array
2952 */
2953
2954 int index1, index2, i;
2955 point *prevPoint;
2956 segment *tmpSeg;
2957
2958
2959 if (gSize3D.numPolys) {
2960 /* sort use the last space as a place holder */
2961 list = (polygon **) calloc(gSize3D.numPolys+1, sizeof(polygon *));
2962 if(!list){
2963 puts("Unable to allocate memory for pointer list !");
2964 return;
2965 }
2966 }
2967 /* This is only for preventing 'Bus error' */
2968 else list = (polygon **) calloc(2, sizeof(polygon *));
2969
2970 for(i = 0; i < gSize3D.numPolys; i++)
2971 list[i] = &(polys[i]);
2972
2973
2974 /*
2975 * Update more lists
2976 */
2977
2978 for(index1 = 0; index1 < gSize3D.numPolys; index1++) {
2979
2980 index2 = 0;
2981
2982 if((list[index1]->segs[0]->P == list[index1]->segs[1]->P) ||
2983 (list[index1]->segs[0]->P == list[index1]->segs[1]->Q)) {
2984 prevPoint = list[index1]->segs[0]->Q;
2985 }
2986 else{
2987 prevPoint = list[index1]->segs[0]->P;
2988 }
2989
2990 while(index2 < list[index1]->numSegs){
2991
2992 tmpSeg = list[index1]->segs[index2];
2993
2994 if(tmpSeg->P == prevPoint){
2995 prevPoint = tmpSeg->Q;
2996 }
2997 else{
2998 prevPoint = tmpSeg->P;
2999 }
3000
3001 /*
3002 * Update points' polygon lists
3003 */
3004
3005 if(prevPoint->numPolys == 0){
3006 if((prevPoint->polys = (polygon **)calloc(1, sizeof(polygon *)))== NULL){
3007 puts("Unable to allocate memory for point polygons !");
3008 return;
3009 }
3010 }
3011 else {
3012 if((prevPoint->polys = (polygon **)realloc(prevPoint->polys,
3013 (prevPoint->numPolys + 1) * sizeof(polygon *))) == NULL){
3014 puts("Unable to allocate memory for point polygons !");
3015 return;
3016 }
3017 }
3018 prevPoint->polys[prevPoint->numPolys] = &(polys[index1]);
3019 prevPoint->numPolys++;
3020
3021 /*
3022 * Update polygons' point lists
3023 */
3024
3025 if(polys[index1].numPoints == 0){
3026 if((polys[index1].points = (point **)calloc(1, sizeof(point *)))== NULL){
3027 puts("Unable to allocate memory for polygon points !");
3028 return;
3029 }
3030 }
3031 else {
3032 if((polys[index1].points = (point **) realloc(
3033 polys[index1].points, (polys[index1].numPoints + 1) *
3034 sizeof(point *))) == NULL){
3035 puts("Unable to allocate memory for point polygons !");
3036 return;
3037 }
3038 }
3039
3040 polys[index1].points[polys[index1].numPoints] = prevPoint;
3041 polys[index1].numPoints++;
3042
3043 index2++;
3044 }
3045 }
3046}
3047
3048
3049/*****************************************************************************
3050* *
3051* main procedure *
3052* *
3053******************************************************************************/
3054unsigned long x3d_main(float *longitude, float *latitude, float *psi, char *string, Window parent)
3055{
3056 Ginfo *g = NULL;
3057 Oinfo *o = NULL;
3058 int i, j;
3059 FILE *fp;
3060 int export = 0;
3061 char filename[80], *indx;
3062
3063 float xMin, yMin, zMin, xMax, yMax, zMax, correctionFactor;
3064 float xCenter, yCenter, zCenter;
3065 float xRange, zRange;
3066
3067 quitApplication = 0;
3068
3069 if((o = (Oinfo *) calloc(1, sizeof(Oinfo))) == NULL){
3070 (void) fprintf(stderr, "Unable to allocate memory for Object\n");
3071 return 0L;
3072 }
3073 gOInfo = o;
3074
3075 if((g = (Ginfo *) calloc(1, sizeof(Ginfo))) == NULL){
3076 (void) fprintf(stderr, "Unable to allocate memory for Ginfo\n");
3077 return 0L;
3078 }
3079 gGInfo = g;
3080
3081 indx = NULL;
3082 strcpy(title, "ROOT://X3D");
3083
3084/*
3085 * Print help
3086 */
3087 if (!strcmp(string, "help")) {
3088 puts("**** x3d QUICK HELP **************************************\n");
3089 puts(" QUIT q Q MOVE OBJECT DOWN u U" );
3090 puts(" TOGGLE CONTROLS STYLE o O MOVE OBJECT UP i I" );
3091 puts(" TOGGLE STEREO DISPLAY s S MOVE OBJECT RIGHT h H" );
3092 puts(" TOGGLE BLUE STEREO VIEW d D MOVE OBJECT BACKWARD j J" );
3093 puts(" TOGGLE DOUBLE BUFFER f F MOVE OBJECT FOREWARD k K" );
3094 puts(" TOGGLE HELP MENU m M MOVE OBJECT LEFT l L" );
3095 puts(" ROTATE ABOUT X x X a A AUTOROTATE ABOUT X 1 2 3" );
3096 puts(" ROTATE ABOUT Y y Y b B AUTOROTATE ABOUT Y 4 5 6" );
3097 puts(" ROTATE ABOUT Z z Z c C AUTOROTATE ABOUT Z 7 8 9\n");
3098 puts(" ADJUST FOCUS [ ] { } HIDDEN LINE MODE e E" );
3099 puts(" WIREFRAME MODE w W HIDDEN SURFACE MODE r R\n");
3100 puts(" POINTER MOVEMENT WITH LEFT BUTTON :\n");
3101 puts(" ROTATE OBJECT ABOUT X Vertical" );
3102 puts(" ROTATE OBJECT ABOUT Z Horizontal\n");
3103
3104 return 0L;
3105 }
3106 else if ((indx = (char *) strstr(string, "hull:")) != NULL) {
3107 strcpy (filename, indx + 5);
3108 if (strlen(filename)) export = 1;
3109 }
3110 else if ((indx = (char *) strstr(string, "java:")) != NULL) {
3111 strcpy (filename, indx + 5);
3112 if (strlen(filename)) export = 2;
3113 }
3114 else if (string) {
3115 strcat(title, "/");
3116 strcat(title, string);
3117 }
3118
3119 switch( export ) {
3120 case 1: /* hull */
3121
3122 if (gSize3D.numPolys) {
3123 fp = fopen (filename, "w");
3124 if (fp != NULL) {
3125 for (i = 0; i < gSize3D.numPolys; i++) {
3126 fprintf (fp, "\n# polygon No. %d color ( R G B )\n", i);
3127 fprintf (fp, "%5d%5d%5d\n\n", polys[i].color->red, polys[i].color->green, polys[i].color->blue);
3128 for (j = 0; j < polys[i].numSegs; j++) {
3129 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);
3130 }
3131 }
3132 fclose (fp);
3133 }
3134 }
3135 else puts ("Can't export (number of polygons=0)");
3136 break;
3137
3138 case 2: /* java */
3139
3140 if( gSize3D.numSegs ) {
3141 fp = fopen( filename, "w" );
3142 if( fp != NULL ) {
3143 for( i = 0; i < gSize3D.numSegs; i++ ) {
3144 fprintf( fp, "v %20.6f%20.6f%20.6f\n", segs[i].P->x, segs[i].P->y, segs[i].P->z);
3145 fprintf( fp, "v %20.6f%20.6f%20.6f\n", segs[i].Q->x, segs[i].Q->y, segs[i].Q->z);
3146 fprintf( fp, "l %6d%6d\n", i*2+1, i*2+2 );
3147 }
3148 fclose (fp);
3149 }
3150 }
3151 break;
3152
3153 default:
3154 break;
3155 }
3156
3157/*
3158 * Try to find the boundaries of the object
3159 */
3160
3161 xMin = yMin = zMin = 999999;
3162 xMax = yMax = zMax = -999999;
3163
3164 for (i = 0; i < gSize3D.numPoints; i++) {
3165 xMin = xMin <= points[i].x ? xMin : points[i].x;
3166 xMax = xMax >= points[i].x ? xMax : points[i].x;
3167
3168 yMin = yMin <= points[i].y ? yMin : points[i].y;
3169 yMax = yMax >= points[i].y ? yMax : points[i].y;
3170
3171 zMin = zMin <= points[i].z ? zMin : points[i].z;
3172 zMax = zMax >= points[i].z ? zMax : points[i].z;
3173 }
3174
3175/*
3176 * Compute the range & center of the object
3177 */
3178
3179 xRange = fabs(xMax - xMin);
3180 zRange = fabs(zMax - zMin);
3181
3182 xCenter = (xMax + xMin) / 2.0;
3183 yCenter = (yMax + yMin) / 2.0;
3184 zCenter = (zMax + zMin) / 2.0;
3185
3186/*
3187 * Compute the correctionFactor, rescale & put the object in the center
3188 */
3189 correctionFactor = 6000.0 / (xRange > zRange ? xRange : zRange);
3190
3191 for (i = 0; i < gSize3D.numPoints; i++) {
3192 points[i].x = (points[i].x - xCenter) * correctionFactor;
3193 points[i].y = (points[i].y - yCenter) * correctionFactor;
3194 points[i].z = (points[i].z - zCenter) * correctionFactor;
3195 }
3196
3197 deltaMove = (float) (xRange >= zRange ? xRange : zRange) / 20.0 * correctionFactor;
3198
3199/*
3200 * Calculate the bounding cube
3201 */
3202
3203 bounds = NULL;
3204 bounds = (point *) calloc(8, sizeof(point));
3205
3206 if (!bounds)
3207 (void) fprintf(stderr, "Unable to allocate memory for bounding cube.\n");
3208
3209 xMin = (xMin - xCenter) * correctionFactor;
3210 xMax = (xMax - xCenter) * correctionFactor;
3211 yMin = (yMin - yCenter) * correctionFactor;
3212 yMax = (yMax - yCenter) * correctionFactor;
3213 zMin = (zMin - zCenter) * correctionFactor;
3214 zMax = (zMax - zCenter) * correctionFactor;
3215
3216 if (bounds) {
3217 bounds[0].x = xMin; bounds[0].y = yMin; bounds[0].z = zMin;
3218 bounds[1].x = xMin; bounds[1].y = yMin; bounds[1].z = zMax;
3219 bounds[2].x = xMin; bounds[2].y = yMax; bounds[2].z = zMin;
3220 bounds[3].x = xMin; bounds[3].y = yMax; bounds[3].z = zMax;
3221 bounds[4].x = xMax; bounds[4].y = yMin; bounds[4].z = zMin;
3222 bounds[5].x = xMax; bounds[5].y = yMin; bounds[5].z = zMax;
3223 bounds[6].x = xMax; bounds[6].y = yMax; bounds[6].z = zMin;
3224 bounds[7].x = xMax; bounds[7].y = yMax; bounds[7].z = zMax;
3225 }
3226
3227/*
3228 * Make polygon pointer array
3229 */
3230
3232
3233 g->Geometry = "800x600";
3234 g->DisplayName = NULL;
3235 g->renderMode = WIREFRAME;
3236 g->buffer = 1;
3237 g->mono = 0;
3238 g->stereo = 0;
3239 g->stereoBlue = 1;
3240 g->colors = colors;
3241 g->numColors = 28;
3242 g->win = 0;
3243 o->points = points;
3244 o->numPoints = gSize3D.numPoints;
3245 o->segs = segs;
3246 o->numSegs = gSize3D.numSegs;
3247 o->polys = polys;
3248 o->numPolys = gSize3D.numPolys;
3249 o->list = list;
3250 o->bounds = bounds;
3251
3252
3253 if (!export && bounds) {
3254
3255 /* Define viewing parameters */
3256
3257 o->BViewpointX = 100.0; /* stereo separation factor */
3258 o->viewpointY = -650.0; /* view point */
3259 o->tX = 640.0; /* observer X coordinate */
3260 o->tY = 6000.0; /* observer Y coordinate */
3261 o->tZ = 490.0; /* observer Z coordinate */
3262 o->oX = 0.0; /* origin X coordinate */
3263 o->oY = 0.0; /* origin Y coordinate */
3264 o->oZ = 0.0; /* origin Z coordinate */
3265 o->X = (double) (*latitude); /* rotate angle around X */
3266 o->Y = (double) (*psi); /* rotate angle around Y */
3267 o->Z = (double) (*longitude); /* rotate angle around Z */
3268 o->dX = 0.0; /* autorotate around X */
3269 o->dY = 0.0; /* autorotate around Y */
3270 o->dZ = 0.0; /* autorotate around Z */
3271 o->focus = 0.2;
3272
3273
3274 /* Initialize the display */
3275
3276
3277 InitDisplay(o, g, parent);
3278
3279 return g->win;
3280 }
3281 return 0;
3282}
3283
3285{
3286 Ginfo *g = gGInfo;
3287 Oinfo *o = gOInfo;
3288
3289 BeginImage(o, g);
3290 DrawObject(o, g);
3291 EndImage(o, g);
3292}
3293
3294int x3d_dispatch_event(unsigned long evnt)
3295{
3296
3297 XEvent *event = (XEvent *)evnt;
3298 Ginfo *g = gGInfo;
3299 Oinfo *o = gOInfo;
3300
3301 UpdatePosition(event, o, g);
3302
3303 x3d_update();
3304
3305 return 1;
3306}
3307
3308void x3d_get_position(float *longitude, float *latitude, float *psi)
3309{
3310 Oinfo *o = gOInfo;
3311
3312 /* Update longitude and latitude */
3313 *latitude = (float) (o->X);
3314 *psi = (float) (o->Y);
3315 *longitude = (float) (o->Z);
3316}
3317
3319{
3320 int i;
3321 Ginfo *g = gGInfo;
3322 Oinfo *o = gOInfo;
3323
3324 if (g->win) {
3325 /* Destroy windows */
3326 XDestroyWindow(g->dpy, g->win);
3327 XDestroyWindow(g->dpy, g->helpWin);
3328
3329 /* Destroy graphics contexts */
3330 XFreeGC(g->dpy, g->gc);
3331 XFreeGC(g->dpy, g->helpGc);
3332
3333 /* Free pixmap */
3334 XFreePixmap(g->dpy, g->pix);
3335
3336 /* Close display */
3337
3338 if (!gDisplay) {
3339 XSetCloseDownMode(g->dpy, DestroyAll);
3340 XCloseDisplay(g->dpy);
3341 }
3342
3343 /* Free allocated memory */
3344 if (g->redColors) free (g->redColors);
3345 if (g->redSegments) free (g->redSegments);
3346 if (g->blueSegments) free (g->blueSegments);
3347 if (o) free (o);
3348 if (g) free (g);
3349
3350 }
3351
3352/*
3353 * Free allocated memory & reset counters
3354 */
3355 currPoint = currSeg = currPoly = 0;
3356
3357 for (i = 0; i < gSize3D.numPolys; i++) {
3358/*
3359 * for (j = 0; j < polys[i].numPoints; j++) {
3360 * if (polys[i].points[j]->polys)
3361 * free (polys[i].points[j]->polys);
3362 * }
3363 */
3364 if (polys[i].points) free (polys[i].points);
3365 }
3366
3367 for (i = 0; i < gSize3D.numSegs; i++)
3368 if (segs[i].polys) free (segs[i].polys);
3369
3370 for (i = 0; i < gSize3D.numPoints; i++)
3371 if (points[i].segs) free (points[i].segs);
3372
3373 if (points) free (points);
3374 if (colors) free (colors);
3375 if (segs) free (segs);
3376 if (polys) free (polys);
3377 if (list) free (list);
3378 if (bounds) free (bounds);
3379}
3380
3381void x3d_set_display(unsigned long disp)
3382{
3383 gDisplay = (Display*) disp;
3384}
3385
3386int x3d_exec_command(int pointerX, int pointerY, char command)
3387/******************************************************************************
3388 Update the scene position information using user input.
3389
3390 The routine will eventually block waiting for an event if block is True
3391 and the no events of interest show up due to the call to GetInput()
3392******************************************************************************/
3393{
3394int dx, dy;
3395double X, Y, Z;
3396
3397 Ginfo *g = gGInfo;
3398 Oinfo *o = gOInfo;
3399
3400 X = Y = Z = 0.0;
3401
3402/* dx, dy, dz are the amount to step about each axis every frame
3403 We want the scene to continue to rotate even if the user does
3404 not give any new input */
3405
3406/* Do not forget to put your automatic update variables into this if
3407 statement. Be careful somehow you can get MANY bugs with these! */
3408
3409 g->Block = 1;
3410
3411/* Note: I do not move the origin which the scene is rotated about around.
3412 You may want to do oX += ???; oY += ???; oZ += ??? */
3413
3414 switch(command){
3415 case ' ' : break;
3416
3417 case 'm' :
3418 case 'M' : g->helpMenu = !g->helpMenu;
3419 /*
3420 if(g->helpMenu == False){
3421 XUnmapWindow(g->dpy, g->helpWin);
3422 }else{
3423 XMapWindow(g->dpy, g->helpWin);
3424 }
3425 */
3426 break;
3427
3428 case 's' :
3429 case 'S' : g->stereo = !g->stereo; g->modeChanged = 1;
3430 break;
3431
3432 case 'd' :
3433 case 'D' : g->stereoBlue = !g->stereoBlue; g->modeChanged = 1;
3434 break;
3435
3436 case 'f' :
3437 case 'F' : g->buffer = !g->buffer; g->modeChanged = 1;
3438 break;
3439
3440 case 'o' :
3441 case 'O' : g->Relative = !g->Relative; break;
3442
3443 case 'w' :
3444 case 'W' : g->renderMode = WIREFRAME; g->modeChanged = 1;
3445 break;
3446
3447 case 'e' :
3448 case 'E' : if(o->numPolys) {
3449 g->renderMode = HIDDENLINE; g->modeChanged = 1;
3450 }
3451 break;
3452
3453 case 'r' :
3454 case 'R' : if(o->numPolys) {
3455 g->renderMode = SOLID; g->modeChanged = 1;
3456 }
3457 break;
3458
3459 case 'l' : o->tX -= deltaMove; break;
3460 case 'j' : o->tY -= deltaMove; break;
3461 case 'k' : o->tY += deltaMove; break;
3462 case 'h' : o->tX += deltaMove; break;
3463 case 'i' : o->tZ += deltaMove; break;
3464 case 'u' : o->tZ -= deltaMove; break;
3465 case 'L' : o->tX -= 5*deltaMove; break;
3466 case 'J' : o->tY -= 5*deltaMove; break;
3467 case 'K' : o->tY += 5*deltaMove; break;
3468 case 'H' : o->tX += 5*deltaMove; break;
3469 case 'I' : o->tZ += 5*deltaMove; break;
3470 case 'U' : o->tZ -= 5*deltaMove; break;
3471 case '1' : o->dX += 0.02; break;
3472 case '2' : o->dX = 0.0 ; break;
3473 case '3' : o->dX -= 0.02; break;
3474 case '4' : o->dY -= 0.02; break;
3475 case '5' : o->dY = 0.0 ; break;
3476 case '6' : o->dY += 0.02; break;
3477 case '7' : o->dZ += 0.02; break;
3478 case '8' : o->dZ = 0.0 ; break;
3479 case '9' : o->dZ -= 0.02; break;
3480 case 'x' : X -= 0.03; break;
3481 case 'X' : X += 0.03; break;
3482 case 'y' : Y += 0.03; break;
3483 case 'Y' : Y -= 0.03; break;
3484 case 'z' : Z -= 0.03; break;
3485 case 'Z' : Z += 0.03; break;
3486 case 'a' : X -= 0.05; break;
3487 case 'A' : X += 0.05; break;
3488 case 'b' : Y += 0.05; break;
3489 case 'B' : Y -= 0.05; break;
3490 case 'c' : Z -= 0.05; break;
3491 case 'C' : Z += 0.05; break;
3492 case '[' : o->focus += 0.1;
3493 if((o->focus > 1.8))
3494 o->focus = 1.8;
3495 break;
3496 case ']' : o->focus -= 0.1;
3497 if((o->focus < -0.8))
3498 o->focus = -0.8;
3499 break;
3500 case '{' : o->BViewpointX -= 4.0; break;
3501 case '}' : o->BViewpointX += 4.0; break;
3502
3503 case 'q' :
3504 case 'Q' : return(1);
3505
3506 default : {
3507
3508/* My pointer movement stuff */
3509
3510/* Only update if the movement was reasonably small */
3511
3512 dx = pointerX - g->oldPointerX;
3513 dy = pointerY - g->oldPointerY;
3514
3515 if((dy * dy <= SMALLMOVEMENT) &&
3516 (dx * dx <= SMALLMOVEMENT)){
3517
3518/* Rotate proportionally with the amount the pointer moved */
3519/* Note: I only control the X and Z axes by the pointer */
3520
3521 X -= (dy * POINTERRATIO);
3522 Z -= (dx * POINTERRATIO);
3523 }
3524 g->oldPointerY = pointerY;
3525 g->oldPointerX = pointerX;
3526 }
3527 }
3528/* } */
3529
3530/* Keep angles 0 - 6.28 */
3531
3532 X = fmod(X + o->dX, TWOPI);
3533 Y = fmod(Y + o->dY, TWOPI);
3534 Z = fmod(Z + o->dZ, TWOPI);
3535
3536/* Fix up the angles */
3537
3538 if(g->Relative){
3539 o->X = fmod(X + o->X, TWOPI);
3540 o->Y = fmod(Y + o->Y, TWOPI);
3541 o->Z = fmod(Z + o->Z, TWOPI);
3542 }else{
3543 CalculateAngles(&(o->X), &(o->Y), &(o->Z), X, Y, Z);
3544 }
3545
3546 x3d_update();
3547
3548 return quitApplication;
3549}
3550
3551#endif
unsigned UCHAR_MAX CPyCppyy_PyLong_AsInt8 CPyCppyy_PyLong_AsInt16 CPyCppyy_PyLong_AsInt32 CPyCppyy_PyLong_AsShort int
double
SCHAR_MAX INT16_MAX INT32_MAX short
unsigned UCHAR_MAX CPyCppyy_PyLong_AsInt8 CPyCppyy_PyLong_AsInt16 CPyCppyy_PyLong_AsInt32 CPyCppyy_PyLong_AsShort CPyCppyy_PyLong_AsStrictInt long
signed _i16 _i8 _i32 unsigned unsigned unsigned L
signed _i16 _i8 _i32 unsigned unsigned unsigned unsigned long Q
signed _i16 _i8 _i32 unsigned unsigned unsigned unsigned long z
PyLong_AsLong PyLong_AsLong PyLong_AsLong PyLong_AsLong PyLong_AsLong PyLong_AsLongLong float
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
start
Definition Rotated.cxx:223
#define X(type, name)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t dest
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pixel
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t win
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t points
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t height
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void gc
XID Window
Definition TGX11.h:38
XID Drawable
Definition TGX11.h:35
#define void
Definition Tailor.h:179
segment * segs
Definition X3DBuffer.c:23
int currSeg
Definition X3DBuffer.c:18
polygon * polys
Definition X3DBuffer.c:24
int currPoint
Definition X3DBuffer.c:17
Color * colors
Definition X3DBuffer.c:21
int currPoly
Definition X3DBuffer.c:19
#define gSize3D
Definition X3DBuffer.h:40
#define TRIG_ADJ
Definition X3DDefs.h:25
struct COLOR_ Color
Definition X3DDefs.h:33
struct POLYGON polygon
Definition X3DDefs.h:32
struct SEGMENT segment
Definition X3DDefs.h:31
float number
Definition X3DDefs.h:26
struct POINT point
Definition X3DDefs.h:30
#define NULL
Definition ZInflate.c:15
#define realloc
Definition civetweb.c:1577
#define free
Definition civetweb.c:1578
#define calloc
Definition civetweb.c:1576
STL class.
#define False
Definition ifparser.h:65
#define True
Definition ifparser.h:66
#define H(x, y, z)
double y
Definition x3d.h:194
double x
Definition x3d.h:194
double z
Definition x3d.h:194
long value
Definition X3DDefs.h:78
int green
Definition X3DDefs.h:81
long stereoColor
Definition X3DDefs.h:79
int stipple
Definition X3DDefs.h:80
int red
Definition X3DDefs.h:81
int blue
Definition X3DDefs.h:81
polygon * polys
Definition x3d.h:203
double X
Definition x3d.h:222
float tX
Definition x3d.h:220
int copyHeight
Definition x3d.h:213
int Hmin2
Definition x3d.h:212
int objClip
Definition x3d.h:209
segment * segs
Definition x3d.h:202
double Y
Definition x3d.h:222
point * bounds
Definition x3d.h:208
double dY
Definition x3d.h:222
int Vmin2
Definition x3d.h:212
double Z
Definition x3d.h:222
int Hmax
Definition x3d.h:210
int Hmin
Definition x3d.h:210
int Vmax2
Definition x3d.h:212
int numPoints
Definition x3d.h:216
float tZ
Definition x3d.h:220
int copyY
Definition x3d.h:213
int copyX
Definition x3d.h:213
double dX
Definition x3d.h:222
int numPolys
Definition x3d.h:216
float oX
Definition x3d.h:221
int numSegs
Definition x3d.h:216
int fillWidth
Definition x3d.h:214
int Vmax
Definition x3d.h:210
int fillHeight
Definition x3d.h:214
float oY
Definition x3d.h:221
float oZ
Definition x3d.h:221
polygon ** list
Definition x3d.h:204
int Vmax1
Definition x3d.h:211
float BViewpointX
Definition x3d.h:224
double dZ
Definition x3d.h:222
double focus
Definition x3d.h:223
int fillY
Definition x3d.h:214
int Hmax2
Definition x3d.h:212
int copyWidth
Definition x3d.h:213
float tY
Definition x3d.h:220
int Vmin
Definition x3d.h:210
int fillX
Definition x3d.h:214
float viewpointY
Definition x3d.h:224
int Hmin1
Definition x3d.h:211
int Hmax1
Definition x3d.h:211
point * points
Definition x3d.h:201
int Vmin1
Definition x3d.h:211
float RX
Definition X3DDefs.h:45
polygon ** polys
Definition X3DDefs.h:52
short sBX
Definition X3DDefs.h:47
int ClipFlags
Definition X3DDefs.h:42
_XPoint R
Definition X3DDefs.h:46
float Y
Definition X3DDefs.h:45
int numPolys
Definition X3DDefs.h:51
float BX
Definition X3DDefs.h:45
Color * color
Definition X3DDefs.h:59
point * P
Definition X3DDefs.h:58
point * Q
Definition X3DDefs.h:58
short x
Definition X3DDefs.h:37
short y
Definition X3DDefs.h:37
void x3d_terminate()
Definition x3d.c:3318
int x3d_exec_command(int pointerX, int pointerY, char command)
Definition x3d.c:3386
unsigned long x3d_main(float *longitude, float *latitude, float *psi, char *string, Window parent)
Definition x3d.c:3054
static Ginfo * gGInfo
Definition x3d.c:123
static void TrueColorSetColors(Ginfo *g)
Definition x3d.c:854
static void ResetPurpleRectangle(int XL, int YL, int XH, int YH, Ginfo *g)
Definition x3d.c:542
void x3d_set_display(unsigned long disp)
Definition x3d.c:3381
static polygon ** list
Definition x3d.c:119
static int quitApplication
Definition x3d.c:121
static void GetInput(XEvent *xevent, int *pointerX, int *pointerY, char *command, int *same, Ginfo *g)
Definition x3d.c:1280
static void rotate(Oinfo *o, Ginfo *g)
Definition x3d.c:2188
static void InitDisplay(Oinfo *o, Ginfo *g, Window parent)
Definition x3d.c:918
static double DotProduct(double x1, double Y1, double x2, double y2)
Definition x3d.c:305
static void DrawObject(Oinfo *o, Ginfo *g)
Definition x3d.c:2826
#define STEREOROTATE
Definition x3d.c:2166
#define REDCLIPFLAGS
Definition x3d.c:2175
static void DrawSegments(Display *display, Window win, GC gc, XSegment segs1[], int numSegs, Ginfo *g)
Definition x3d.c:2382
static Oinfo * gOInfo
Definition x3d.c:124
static int CheckEvent(Display *display, XEvent *event, char *arg)
Definition x3d.c:1256
static point * bounds
Definition x3d.c:120
static int gGreenShift
Definition x3d.c:126
static int gGreenDiv
Definition x3d.c:126
static int gBlueShift
Definition x3d.c:126
Atom wm_protocols[2]
Definition x3d.c:916
static void EightBitSetColors(Ginfo *g)
Definition x3d.c:613
static void EndImage(Oinfo *o, Ginfo *g)
Definition x3d.c:2897
static void clip(Oinfo *o, Ginfo *g)
Definition x3d.c:1839
#define STEREOCLIPFLAGS
Definition x3d.c:2181
static void DisplayMenu(Ginfo *g)
Definition x3d.c:477
int x3d_dispatch_event(unsigned long evnt)
Definition x3d.c:3294
static Display * gDisplay
Definition x3d.c:122
static void DrawPolys(Oinfo *o, Ginfo *g, int mode)
Definition x3d.c:2631
static int UpdatePosition(XEvent *event, Oinfo *o, Ginfo *g)
Definition x3d.c:1445
static void DrawLines(Oinfo *o, Ginfo *g, int mode)
Definition x3d.c:2407
static void sort(polygon **list1, int numPolys)
Definition x3d.c:130
#define REDROTATE
Definition x3d.c:2155
void x3d_update()
Definition x3d.c:3284
static void Rotate(anglePoint *points1, double cx, double cy, double cz, double sx, double sy, double sz)
Definition x3d.c:277
void x3d_get_position(float *longitude, float *latitude, float *psi)
Definition x3d.c:3308
char title[80]
Definition x3d.c:915
static void DrawHiddenLines(Oinfo *o, Ginfo *g, int mode)
Definition x3d.c:2482
static int gRedShift
Definition x3d.c:126
static int clipSegment(float *pX, float *pY, float *qX, float *qY, int Pclip, int Qclip, float H, float V)
Definition x3d.c:1630
float deltaMove
Definition x3d.c:1443
void MakePolygonArray()
Definition x3d.c:2944
static void OneBitSetColors(Ginfo *g)
Definition x3d.c:583
static void DrawLogo(Ginfo *g, int x, int y)
Definition x3d.c:367
static void BeginImage(Oinfo *o, Ginfo *g)
Definition x3d.c:2778
static int gRedDiv
Definition x3d.c:126
static int gBlueDiv
Definition x3d.c:126
static void CalculateAngles(double *X, double *Y, double *Z, double X1, double Y1, double Z1)
Definition x3d.c:333
#define REQUESTFACTOR
Definition x3d.h:84
#define RLeftRight
Definition x3d.h:66
#define STIPPLESIZE
Definition x3d.h:74
struct XSEGMENT xsegment
#define FIXED
Definition x3d.h:99
#define ONE
Definition x3d.h:117
#define HELPLINES
Definition x3d.h:88
#define POINTERRATIO
Definition x3d.h:81
#define clipWithTop(x, y, dx, dy, V)
Definition x3d.h:139
#define MAXVALUE
Definition x3d.h:71
#define BITSPERBYTE
Definition x3d.h:75
#define FONTHEIGHT(font)
Definition x3d.h:143
#define HelpPrint(g, x, y, string)
Definition x3d.h:145
#define BOLDFONT
Definition x3d.h:98
#define TWOPI
Definition x3d.h:83
#define COLOR
Definition x3d.h:107
struct STACKELEMENT StackElement
#define HIDDENLINE
Definition x3d.h:112
struct OINFO Oinfo
#define VALUESCALE
Definition x3d.h:72
#define STEREO
Definition x3d.h:106
#define MAXCOLORS
Definition x3d.h:76
#define BUFFER_CMAP
Definition x3d.h:123
#define BUFFER0
Definition x3d.h:124
#define Behind
Definition x3d.h:56
#define BUFFER1
Definition x3d.h:125
#define MAXCOLORDIST
Definition x3d.h:73
#define NUMSTIPPLES
Definition x3d.h:70
#define TITLEFONT
Definition x3d.h:97
#define BW
Definition x3d.h:105
#define RBmask
Definition x3d.h:65
#define LONGESTSTRING
Definition x3d.h:101
#define Rmask
Definition x3d.h:64
#define clipWithLeftSide(x, y, dx, dy, H)
Definition x3d.h:140
#define SOLID
Definition x3d.h:113
#define MAXSTACK
Definition x3d.h:90
#define EIGHT
Definition x3d.h:118
#define MARGIN
Definition x3d.h:82
#define clipWithRightSide(x, y, dx, dy, H)
Definition x3d.h:141
#define WIREFRAME
Definition x3d.h:111
#define median5(v1, v2, v3, v4, v5)
Definition x3d.h:155
#define NUMBOUNDS
Definition x3d.h:69
struct GINFO Ginfo
struct ANGLEPOINT anglePoint
#define FONT
Definition x3d.h:96
#define STOP
Definition x3d.h:91
#define SMALLMOVEMENT
Definition x3d.h:80
#define clipWithBottom(x, y, dx, dy, V)
Definition x3d.h:138
#define TMPSTRLEN
Definition x3d.h:79
#define MAX_COLORS
Definition x3d.h:122
unsigned long Atom
Definition xatom.h:9