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