1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 /*
9  * $Source: /src/master/dx/src/exec/hwrender/hwMatrix.c,v $
10  */
11 
12 #include <dxconfig.h>
13 
14 #if defined(HAVE_STRINGS_H)
15 #include <strings.h>
16 #endif
17 
18 #include <stdio.h>
19 #include <math.h>
20 
21 #ifndef STANDALONE
22 #include "hwMemory.h"
23 #endif
24 #include "hwDeclarations.h"
25 #include "hwMatrix.h"
26 #include "hwPortLayer.h"
27 #include "hwDebug.h"
28 
29 /*
30  *  TDM maintains the current transform on both the hardware stack and its
31  *  own stack as implemented here.  We do this because we need to be able
32  *  to access the modeling, viewing, projection, and screen transforms
33  *  independently for certain computations.
34  *
35  *  While some API's such as Starbase provide a separate modeling
36  *  transformation stack, other API's such as GL combine the
37  *  modeling/viewing matrix.  (This is determined by the coordinate system
38  *  in which the API performs lighting.  Starbase performs lighting in
39  *  world coordinates and so combines the non-orthogonal projection
40  *  components of the transformation pipeline into a viewing/projection
41  *  matrix, while GL computes lighting in viewing coordinates and so has
42  *  an independent projection matrix).
43  *
44  *  We implement a GL-style matrix stack for the software shadow.
45  */
46 
47 typedef struct tdmTransformS {
48   float	m[4][4] ;
49   float fuzz ;
50   float ff ;
51 } tdmTransformT ;
52 
53 typedef struct tdmViewportS {
54   int left, right, bottom, top ;
55 } tdmViewportT ;
56 
57 typedef struct tdmTransformStackS {
58   /* modeling transform stack */
59   int mSize ;
60   tdmTransformT	*mStack ;
61   tdmTransformT	*mTop ;
62 
63   /* view transform stack */
64   int vSize ;
65   tdmTransformT *vStack ;
66   tdmTransformT *vTop ;
67 
68   /* viewport stack */
69   int pSize ;
70   tdmViewportT *pStack ;
71   tdmViewportT *pTop ;
72 
73   /* composite (model X view X fuzz) matrix */
74   float composite[4][4] ;
75   int composite_current ;
76 
77   /* projection info */
78   float projmat[4][4], width, aspect, Near, Far ;
79   int projection, resolution, projection_current ;
80 } tdmTransformStackT, *tdmTransformStackP ;
81 
82 
83 #define	EMPTY(stack, top) (top == stack)
84 #define	FULL(stack, top, size) (top == &stack[size-1])
85 
86 #define FREE(stack)                                                         \
87 {                                                                           \
88   if (stack)                                                                \
89     {                                                                       \
90       tdmFree(stack) ;                                                      \
91       stack = NULL ;                                                        \
92     }                                                                       \
93 }
94 
95 #define GROW(type, stack, top, size)   	       	       	                    \
96 {								            \
97   register int i ;						            \
98   register type *p, *newTop, *newStack ;			            \
99  								            \
100   newStack = newTop = (type *) tdmAllocateLocal(sizeof(type) * (size+32)) ; \
101   								            \
102   for (i=0, p=stack ; i<size ; i++)			                    \
103       *newTop++ = *p++ ;					            \
104 								            \
105   if (stack) tdmFree(stack) ;				                    \
106 								            \
107   stack = newStack ;						            \
108   top = newTop ;						            \
109   size += 32 ;						                    \
110 }
111 
112 #define POP(stack, top)                                                     \
113 {		       						            \
114   if (!EMPTY(stack, top)) top-- ;				            \
115 }
116 
117 #define PUSH(type, stack, top, size)                                        \
118 {								            \
119   /* push copy of top */					            \
120   if (FULL(stack, top, size))					            \
121       GROW(type, stack, top, size) ;				            \
122 								            \
123   *(top+1) = *top ;						            \
124   top++ ;							            \
125 }
126 
127 
128 void *
_dxfCreateStack()129 _dxfCreateStack()
130 {
131   tdmTransformStackP tdmStack ;
132 
133   ENTRY(("_dxfCreateStack()"));
134 
135   if (! (tdmStack = (tdmTransformStackP)
136 	            tdmAllocateLocal(sizeof(tdmTransformStackT))))
137       goto error ;
138 
139   tdmStack->mSize = 0 ;
140   tdmStack->mTop = tdmStack->mStack = NULL ;
141   GROW(tdmTransformT, tdmStack->mStack, tdmStack->mTop, tdmStack->mSize) ;
142 
143   tdmStack->vSize = 0 ;
144   tdmStack->vTop = tdmStack->vStack = NULL ;
145   GROW(tdmTransformT, tdmStack->vStack, tdmStack->vTop, tdmStack->vSize) ;
146 
147   tdmStack->pSize = 0 ;
148   tdmStack->pTop = tdmStack->pStack = NULL ;
149   GROW(tdmViewportT, tdmStack->pStack, tdmStack->pTop, tdmStack->pSize) ;
150 
151   EXIT((""));
152   return (void *)tdmStack ;
153 
154  error:
155 
156   EXIT(("ERROR"));
157   return (void *)0 ;
158 }
159 
160 void
_dxfInitStack(void * stack,int resolution,float view[4][4],int projection,float width,float aspect,float Near,float Far)161 _dxfInitStack(void *stack, int resolution, float view[4][4], int projection,
162 	     float width, float aspect, float Near, float Far)
163 {
164   tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
165 
166   ENTRY(("_dxfInitStack(0x%x, %d, 0x%x, %d, %f, %f, %f, %f)",
167 	 stack, resolution, view, projection, width, aspect, Near, Far));
168 
169   tdmStack->mTop = tdmStack->mStack ;
170   tdmStack->mTop->fuzz = 0 ;
171   tdmStack->mTop->ff = 1 ;
172   _dxfLoadMatrix(stack, (float (*)[4])identity) ;
173 
174   tdmStack->vTop = tdmStack->vStack ;
175   _dxfLoadViewMatrix(stack, view) ;
176 
177   tdmStack->resolution = resolution ;
178   _dxfSetProjectionInfo(stack, projection, width, aspect, Near, Far) ;
179 
180   tdmStack->composite_current = 0 ;
181 
182   EXIT((""));
183 }
184 
185 void
_dxfFreeStack(void * stack)186 _dxfFreeStack (void *stack)
187 {
188   tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
189 
190   ENTRY(("_dxfFreeStack(0x%x)", stack));
191 
192   if (!tdmStack) {
193     EXIT((""));
194     return ;
195   }
196 
197   FREE(tdmStack->mStack) ; /* modeling */
198   FREE(tdmStack->vStack) ; /* viewing */
199   FREE(tdmStack->pStack) ; /* viewport */
200 
201   tdmFree(tdmStack) ;
202 
203   EXIT((""));
204 }
205 
206 void
_dxfSetFuzzValue(void * stack,float fuzz)207 _dxfSetFuzzValue (void *stack, float fuzz)
208 {
209   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
210 
211   ENTRY(("_dxfSetFuzzValue(0x%x, %f)", stack, fuzz));
212 
213   /* ff is normally 1.0 except when drawing screen objects */
214   tdmStack->mTop->fuzz = tdmStack->mTop->ff * fuzz ;
215   tdmStack->composite_current = 0 ;
216 
217   EXIT((""));
218 }
219 
220 
221 void
_dxfSetScreenFuzzFactor(void * stack,float ff)222 _dxfSetScreenFuzzFactor (void *stack, float ff)
223 {
224   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
225 
226   ENTRY(("_dxfSetScreenFuzzFactor(0x%x, %f", stack, ff));
227 
228   /* ff is normally 1.0 except when drawing screen objects */
229   tdmStack->mTop->ff = ff ;
230   tdmStack->mTop->fuzz *= ff ;
231   tdmStack->composite_current = 0 ;
232 
233   EXIT((""));
234 }
235 
236 
237 void
_dxfPushMatrix(void * stack)238 _dxfPushMatrix (void *stack)
239 {
240   /* push modeling transform and copy to top */
241   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
242 
243   ENTRY(("_dxfPushMatrix(0x%x)", stack));
244 
245   PUSH(tdmTransformT, tdmStack->mStack, tdmStack->mTop, tdmStack->mSize) ;
246 
247   EXIT((""));
248 }
249 
250 void
_dxfPushViewMatrix(void * stack)251 _dxfPushViewMatrix (void *stack)
252 {
253   /* push viewing transform and copy to top */
254   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
255 
256   ENTRY(("_dxfPushViewMatrix(0x%x)", stack));
257 
258   PUSH(tdmTransformT, tdmStack->vStack, tdmStack->vTop, tdmStack->vSize) ;
259 
260   EXIT((""));
261 }
262 
263 void
_dxfPushViewport(void * stack)264 _dxfPushViewport (void *stack)
265 {
266   /* push viewport and copy to top */
267   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
268 
269   ENTRY(("_dxfPushViewport(0x%x)", stack));
270 
271   PUSH(tdmViewportT, tdmStack->pStack, tdmStack->pTop, tdmStack->pSize) ;
272 
273   EXIT((""));
274 }
275 
276 void
_dxfPopMatrix(void * stack)277 _dxfPopMatrix (void *stack)
278 {
279   /* pop modeling transform */
280   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
281 
282   ENTRY(("_dxfPopMatrix(0x%x)", stack));
283 
284   POP(tdmStack->mStack, tdmStack->mTop) ;
285   tdmStack->composite_current = 0 ;
286 
287   EXIT((""));
288 }
289 
290 void
_dxfPopViewMatrix(void * stack)291 _dxfPopViewMatrix (void *stack)
292 {
293   /* pop view transform */
294   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
295 
296   ENTRY(("_dxfPopViewMatrix(0x%x)", stack));
297 
298   POP(tdmStack->vStack, tdmStack->vTop) ;
299   tdmStack->composite_current = 0 ;
300 
301   EXIT((""));
302 }
303 
304 void
_dxfPopViewport(void * stack)305 _dxfPopViewport (void *stack)
306 {
307   /* pop viewport stack */
308   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
309 
310   ENTRY(("_dxfPopViewport(0x%x)", stack));
311 
312   POP(tdmStack->pStack, tdmStack->pTop) ;
313 
314   EXIT((""));
315 }
316 
317 
318 void
_dxfMultMatrix(void * stack,register float m[4][4])319 _dxfMultMatrix(void *stack, register float m[4][4])
320 {
321   /* replace top modeling transform with [m] X [current top] */
322   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
323   float newMatrix[4][4] ;
324 
325   ENTRY(("_dxfMultMatrix(0x%x, 0x%x)", stack, m));
326 
327   MULTMATRIX(newMatrix, m, tdmStack->mTop->m) ;
328   COPYMATRIX(tdmStack->mTop->m, newMatrix) ;
329   tdmStack->composite_current = 0 ;
330 
331   EXIT((""));
332 }
333 
334 void
_dxfLoadMatrix(void * stack,float m[4][4])335 _dxfLoadMatrix(void *stack, float m[4][4])
336 {
337   /* replace top modeling transform with [m] */
338   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
339 
340   ENTRY(("_dxfLoadMatrix(0x%x, 0x%x)", stack, m));
341 
342   COPYMATRIX(tdmStack->mTop->m, m) ;
343   tdmStack->composite_current = 0 ;
344 
345   EXIT((""));
346 }
347 
348 void
_dxfLoadViewMatrix(void * stack,float m[4][4])349 _dxfLoadViewMatrix(void *stack, float m[4][4])
350 {
351   /* replace top viewing matrix with [m] */
352   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
353 
354   ENTRY(("_dxfLoadViewMatrix(0x%x, 0x%x)", stack, m));
355 
356   COPYMATRIX(tdmStack->vTop->m, m) ;
357   tdmStack->composite_current = 0 ;
358 
359   EXIT((""));
360 }
361 
362 void
_dxfSetViewport(void * stack,int left,int right,int bottom,int top)363 _dxfSetViewport(void *stack, int left, int right, int bottom, int top)
364 {
365   /* record viewport coordinates */
366   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
367 
368   ENTRY(("_dxfSetViewport(0x%x, %d, %d, %d, %d)",
369 	 stack, left, right, bottom, top));
370 
371   tdmStack->pTop->left = left ;
372   tdmStack->pTop->right = right ;
373   tdmStack->pTop->bottom = bottom ;
374   tdmStack->pTop->top = top ;
375 
376   EXIT((""));
377 }
378 
379 void
_dxfGetMatrix(void * stack,float m[4][4])380 _dxfGetMatrix(void *stack, float m[4][4])
381 {
382   /* return modeling transform from top of stack */
383   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
384 
385   ENTRY(("_dxfGetMatrix(0x%x, 0x%x)", stack, m));
386 
387   COPYMATRIX(m, tdmStack->mTop->m) ;
388 
389   EXIT((""));
390 }
391 
392 void
_dxfGetViewMatrix(void * stack,float m[4][4])393 _dxfGetViewMatrix(void *stack, float m[4][4])
394 {
395   /* return view transform from top of stack */
396   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
397 
398   ENTRY(("_dxfGetViewMatrix(0x%x, 0x%x)", stack, m));
399 
400   COPYMATRIX(m, tdmStack->vTop->m) ;
401 
402   EXIT((""));
403 }
404 
405 void
_dxfGetViewport(void * stack,int * left,int * right,int * bottom,int * top)406 _dxfGetViewport(void *stack, int *left, int *right, int *bottom, int *top)
407 {
408   /* return viewport from top of stack */
409   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
410 
411   ENTRY(("_dxfGetViewport(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)",
412 	 stack, left, right, bottom, top));
413 
414   /* !!!! Should test for NULL pointers !!!! */
415   *left = tdmStack->pTop->left ;
416   *right = tdmStack->pTop->right ;
417   *bottom = tdmStack->pTop->bottom ;
418   *top = tdmStack->pTop->top ;
419 
420   EXIT((""));
421 }
422 
423 void
_dxfGetViewMatrixWithFuzz(void * stack,double fuzz,register float m[4][4])424 _dxfGetViewMatrixWithFuzz(void *stack, double fuzz, register float m[4][4])
425 {
426   /* return [view] X [fuzz] */
427   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
428 
429   ENTRY(("_dxfGetViewMatrixWithFuzz(0x%x, %f, 0x%x)", stack, fuzz, m));
430 
431   COPYMATRIX(m, tdmStack->vTop->m) ;
432 
433   /* [view] x [fuzz] */
434   if (fuzz != 0.0)
435     {
436       /*
437        *  Apply fuzz.  See "Method for drawing lines, curves, and points
438        *  coincident with surfaces" [Lucas, Allain 1992].
439        */
440 
441       float dOffset, half_pixel ;
442       half_pixel = tdmStack->width / (2.0 * tdmStack->resolution) ;
443       dOffset = fuzz * half_pixel ;
444 
445       if (tdmStack->projection)
446 	{
447 	  /* apply matrix from equation (8) for perspective depth offset */
448 	  register float f = 1.0 - dOffset ;
449 
450 	  m[0][0] *= f ;  m[0][1] *= f ;  m[0][2] *= f ;
451 	  m[1][0] *= f ;  m[1][1] *= f ;  m[1][2] *= f ;
452 	  m[2][0] *= f ;  m[2][1] *= f ;  m[2][2] *= f ;
453 	  m[3][0] *= f ;  m[3][1] *= f ;  m[3][2] *= f ;
454 	}
455       else
456 	{
457 	  /* apply matrix from equation (4) for orthogonal depth offset */
458 	  m[3][2] += dOffset ;
459 	}
460     }
461 
462   PRINT(("[view] X [fuzz] ="));
463   MPRINT(m);
464 
465   EXIT((""));
466 }
467 
468 void
_dxfGetCompositeMatrix(void * stack,register float m[4][4])469 _dxfGetCompositeMatrix(void *stack, register float m[4][4])
470 {
471   /* return [model] X [view] X [fuzz] */
472   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
473 
474 
475   ENTRY(("_dxfGetCompositeMatrix(0x%x, 0x%x)", stack, m));
476 
477   if (tdmStack->composite_current)
478     {
479       COPYMATRIX(m, tdmStack->composite) ;
480       EXIT(("composite was not recomputed"));
481       return ;
482     }
483 
484   /* [view] X [fuzz] */
485   _dxfGetViewMatrixWithFuzz(stack, tdmStack->mTop->fuzz, m);
486 
487   /* [model] X [view] X [fuzz] */
488   MULTMATRIX(tdmStack->composite, tdmStack->mTop->m, m) ;
489 
490   COPYMATRIX(m, tdmStack->composite) ;
491   tdmStack->composite_current = 1 ;
492 
493   PRINT(("[model] X [view] X [fuzz] ="));
494   MPRINT(m);
495   EXIT((""));
496 }
497 
498 void
_dxfGetProjectionInfo(void * stack,int * projection,float * width,float * aspect,float * Near,float * Far)499 _dxfGetProjectionInfo (void *stack, int *projection,
500 		      float *width, float *aspect, float *Near, float *Far)
501 {
502   /* return projection info */
503   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
504 
505   ENTRY(("_dxfGetProjectionInfo(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)",
506 	 stack, projection, width, aspect, Near, Far));
507 
508   /* !!!! Should test for NULL pointers !!!! */
509   *projection = tdmStack->projection ;
510   *width = tdmStack->width ;
511   *aspect = tdmStack->aspect ;
512   *Near = tdmStack->Near ;
513   *Far = tdmStack->Far ;
514 
515   EXIT((""));
516 }
517 
518 void
_dxfSetProjectionInfo(void * stack,int projection,float width,float aspect,float Near,float Far)519 _dxfSetProjectionInfo (void *stack, int projection,
520 		      float width, float aspect, float Near, float Far)
521 {
522   /* record projection info */
523   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
524 
525   ENTRY(("_dxfSetProjectionInfo(0x%x, %d, %f, %f, %f, %f)",
526 	 stack, projection, width, aspect, Near, Far));
527 
528   tdmStack->projection = projection ;
529   tdmStack->width = width ;
530   tdmStack->aspect = aspect ;
531   tdmStack->Near = Near ;
532   tdmStack->Far = Far ;
533   tdmStack->projection_current = 0 ;
534 
535   /*
536    *  Warn about view angles < 0.001 degrees.  This is equivalent to a width
537    *  of 2*tan(0.001/2) = ~1.745329e-05 = ~tan(0.0005) for this small angle.
538    */
539 
540   if (projection && width < 1.745329e-05)
541     {
542       PRINT(("view angle less than 0.001 degrees: display unpredictable"));
543       DXWarning ("#13930") ;
544     }
545 
546   EXIT((""));
547 }
548 
549 void
_dxfGetProjectionMatrix(void * portHandle,void * stack,float projmat[4][4])550 _dxfGetProjectionMatrix (void *portHandle, void *stack, float projmat[4][4])
551 {
552   DEFPORT(portHandle);
553   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
554 
555   ENTRY(("_dxfGetProjectionMatrix(0x%x, 0x%x, 0x%x)",
556 	 portHandle, stack, projmat));
557 
558   if (! tdmStack->projection_current)
559     {
560       _dxf_MAKE_PROJECTION_MATRIX
561 	  (tdmStack->projection, tdmStack->width,
562 	   tdmStack->aspect, tdmStack->Near, tdmStack->Far,
563 	   tdmStack->projmat) ;
564 
565       tdmStack->projection_current = 1 ;
566     }
567 
568   COPYMATRIX(projmat, tdmStack->projmat) ;
569 
570   EXIT((""));
571 }
572 
573 /*
574  *  Misc. algebra
575  */
576 
577 void
_dxfMult44f(register double s0[4][4],register float s1[4][4])578 _dxfMult44f (register double s0[4][4], register float s1[4][4])
579 {
580   double res[4][4] ;
581   register int i, j, k ;
582 
583   ENTRY(("_dxfMult44f(0x%x, 0x%x)", s0, s1));
584 
585   DMCOPY (res, dZero) ;
586   for (i = 0 ; i < 4 ; i++)
587       for (j = 0 ; j < 4 ; j++)
588           for (k = 0 ; k < 4 ; k++)
589               res[i][j] += (s0[i][k] * (double)s1[k][j]) ;
590 
591   DMCOPY (s0, res) ;
592 
593   EXIT((""));
594 }
595 
596 void
_dxfMult44(register double s0[4][4],register double s1[4][4])597 _dxfMult44 (register double s0[4][4], register double s1[4][4])
598 {
599   double res[4][4];
600   register int i, j, k;
601 
602   ENTRY(("_dxfMult44(0x%x, 0x%x)", s0, s1));
603 
604   DMCOPY (res, dZero) ;
605   for (i = 0 ; i < 4 ; i++)
606       for (j = 0 ; j < 4 ; j++)
607           for (k = 0 ; k < 4 ; k++)
608               res[i][j] += (s0[i][k] * s1[k][j]) ;
609 
610   DMCOPY (s0, res) ;
611 
612   EXIT((""));
613 }
614 
615 #define DET33(s) \
616         (( s[0][0] * ((s[1][1] * s[2][2]) - (s[2][1] * s[1][2])) ) + \
617          (-s[0][1] * ((s[1][0] * s[2][2]) - (s[2][0] * s[1][2])) ) + \
618          ( s[0][2] * ((s[1][0] * s[2][1]) - (s[2][0] * s[1][1])) ) )
619 
620 static double
cofac(register double s0[4][4],register int s1,register int s2)621 cofac (register double s0[4][4], register int s1, register int s2)
622 {
623   register int i, j, I, J ;
624   double cofac[4][4] ;
625 
626   ENTRY(("cofac(0x%x, %d, %d)", s0, s1, s2));
627 
628   for (i = 0, I = 0 ; i < 4 ; i++)
629       if (i != s1)
630         {
631           for (j = 0, J = 0 ; j < 4 ; j++)
632               if (j != s2)
633                   cofac[I][J++] = s0[i][j] ;
634           I++ ;
635         }
636 
637   EXIT((""));
638   return DET33(cofac) ;
639 }
640 /* s1 <- inverse (s0) */
641 
642 void
_dxfInverse(register double s1[4][4],register double s0[4][4])643 _dxfInverse (register double s1[4][4], register double s0[4][4])
644 {
645   register int i, j ;
646   double det ;
647 
648   ENTRY(("_dxfInverse(0x%x, 0x%x)", s1, s0));
649 
650   det = (s0[0][0] * cofac(s0, 0, 0)) + (-s0[0][1] * cofac(s0, 0, 1)) +
651         (s0[0][2] * cofac(s0, 0, 2)) + (-s0[0][3] * cofac(s0, 0, 3)) ;
652 
653   det = 1/det ;
654 
655   for (i = 0 ; i < 4 ; i++)
656       for (j = 0 ; j < 4 ; j++)
657           s1[j][i] = ((((i + j + 1) % 2) * 2) - 1) * cofac(s0, i, j) * det ;
658 
659   EXIT((""));
660 }
661 
662 /* s1 <- adjointTranspose (s0) */
663 void
_dxfAdjointTranspose(register double s1[4][4],register double s0[4][4])664 _dxfAdjointTranspose (register double s1[4][4], register double s0[4][4])
665 {
666   register int i, j ;
667 
668   ENTRY(("_dxfAdjointTranspose(0x%x, 0x%x)", s1, s0));
669 
670   for (i = 0 ; i < 3 ; i++)
671       for (j = 0 ; j < 3 ; j++)
672           s1[i][j] = ((((i + j + 1) % 2) * 2) - 1) * cofac(s0, i, j);
673 
674   for(i = 0; i < 3 ; i++) {
675     s1[3][i] = 0.0;
676     s1[i][3] = 0.0;
677   }
678 
679   s1[3][3] = 1.0;
680 
681   EXIT((""));
682 }
683 
684 /* s1 <- Transpose (s0) */
685 void
_dxfTranspose(register double s1[4][4],register double s0[4][4])686 _dxfTranspose (register double s1[4][4], register double s0[4][4])
687 {
688   register int i, j ;
689 
690   ENTRY(("_dxfTranspose(0x%x, 0x%x)", s1, s0));
691 
692   for (i = 0 ; i < 4 ; i++)
693       for (j = 0 ; j < 4 ; j++) {
694 	s1[i][j] = s0[j][i];
695       }
696 
697   EXIT((""));
698 }
699 
700 void
_dxfRenormalizeView(register float m[4][4])701 _dxfRenormalizeView (register float m[4][4])
702 {
703   double len, x[3], z[3] ;
704 
705 
706   ENTRY(("_dxfRenormalizeView(0x%x)", m));
707 
708   /* normalize Z axis */
709   len = sqrt((double)(m[0][2]*m[0][2] + m[1][2]*m[1][2] + m[2][2]*m[2][2])) ;
710   m[0][2] = z[0] = m[0][2] / len ;
711   m[1][2] = z[1] = m[1][2] / len ;
712   m[2][2] = z[2] = m[2][2] / len ;
713 
714   /* cross Y with Z to get X axis */
715   x[0] = m[1][1]*z[2] - m[2][1]*z[1] ;
716   x[1] = m[2][1]*z[0] - m[0][1]*z[2] ;
717   x[2] = m[0][1]*z[1] - m[1][1]*z[0] ;
718 
719   /* normalize the X axis */
720   len = sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]) ;
721   m[0][0] = x[0] = x[0] / len ;
722   m[1][0] = x[1] = x[1] / len ;
723   m[2][0] = x[2] = x[2] / len ;
724 
725   /* cross Z with X axis to get new Y axis */
726   m[0][1] = z[1]*x[2] - z[2]*x[1] ;
727   m[1][1] = z[2]*x[0] - z[0]*x[2] ;
728   m[2][1] = z[0]*x[1] - z[1]*x[0] ;
729 
730   /* this shouldn't be necessary, but IBM GL fails here! */
731   m[0][3] = 0 ;
732   m[1][3] = 0 ;
733   m[2][3] = 0 ;
734   m[3][3] = 1 ;
735 
736   EXIT((""));
737 }
738 
739 void
_dxfGetNearFar(int projection,int resolution,float width,float from[3],float zaxis[3],float box[8][3],float * Near,float * Far)740 _dxfGetNearFar(int projection, int resolution, float width,
741 	      float from[3], float zaxis[3], float box[8][3],
742               float *Near, float *Far)
743 {
744   register int i ;
745   register float ClipMin, ClipMax, len, fuzz ;
746   float BoxVecs[8][3] ;
747 
748   /*
749    *  Calculate new clip planes based on WC bounding box.
750    */
751 
752   ENTRY(("_dxfGetNearFar(%d, %d, %f, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)",
753 	 projection, resolution, width, from, zaxis, box, Near, Far));
754 
755   PRINT(("from point:"));
756   VPRINT(from);
757   PRINT(("view vector:"));
758   VPRINT(zaxis);
759 
760   for (i=0; i<8; i++)
761     {
762       BoxVecs[i][0] = box[i][0] - from[0];
763       BoxVecs[i][1] = box[i][1] - from[1];
764       BoxVecs[i][2] = box[i][2] - from[2];
765     }
766 
767   ClipMin =  DXD_MAX_FLOAT ;
768   ClipMax = -DXD_MAX_FLOAT ;
769   for (i=0; i<8; i++)
770     {
771       /* project vectors from `from' to box corners onto view direction */
772       len = BoxVecs[i][0]*zaxis[0] +
773 	    BoxVecs[i][1]*zaxis[1] +
774 	    BoxVecs[i][2]*zaxis[2];
775       if (len < ClipMin) ClipMin = len;
776       if (len > ClipMax) ClipMax = len;
777     }
778 
779   PRINT(("Far  clip pre-fuzz:  %f", ClipMax));
780   PRINT(("Near clip pre-fuzz:  %f", ClipMin));
781 
782   /*
783    *  DX maintains a notion of "fuzz" which is used to prevent surfaces
784    *  from burying coincident lines, curves and points (surface markings).
785    *  Fuzz is a function of the ratio of pixels to world coordinate units,
786    *  and is added to the projection depth coordinates of all surface
787    *  markings, so we must adjust the clip planes by at least this amount.
788    *
789    *  We won't know the fuzz value until DX object traversal starts,
790    *  but 4 is the most typical value.
791    */
792 
793   /*
794    * The aformentioned '4' didn't take accumulated fuzz into
795    * account.  For the time being we're going to assume that
796    * the sum total of fuzz will be < 100
797    */
798 
799   /*
800   fuzz = 4/(2.0*resolution/width) ;
801   */
802   fuzz = 100/(2.0*resolution/width) ;
803 
804   fuzz = 1.1 * (projection? ClipMax*fuzz: fuzz) ;
805   fuzz = fuzz < 0? -fuzz: fuzz ;
806 
807   if (projection && ClipMin < 2*fuzz)
808       ClipMin = ClipMax > 0? ClipMax/1000: fuzz ;
809   else
810       ClipMin -= fuzz ;
811 
812   if (ClipMax <= ClipMin)
813       ClipMax = ClipMin + fuzz ;
814   else
815       ClipMax += fuzz ;
816 
817   *Far = ClipMax;
818   *Near = ClipMin;
819 
820   PRINT(("fuzz: %f", fuzz));
821   PRINT(("Far  clip post-fuzz: %f", *Far));
822   PRINT(("Near clip post-fuzz: %f", *Near));
823 
824   EXIT((""));
825 }
826 
827 void
_dxfSetProjectionMatrix(void * portHandle,void * stack,float projmat[4][4])828 _dxfSetProjectionMatrix(void *portHandle, void *stack, float projmat[4][4])
829 {
830   register tdmTransformStackP tdmStack = (tdmTransformStackP) stack ;
831   COPYMATRIX(tdmStack->projmat, projmat) ;
832   tdmStack->projection_current = 1;
833 }
834 
835