1
/* $Xorg: miTriStrip.c,v 1.4 2001/02/09 02:04:11 xorgcvs Exp $ */
4
Copyright 1989, 1990, 1991, 1998 The Open Group
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
12
The above copyright notice and this permission notice shall be included
13
in all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
19
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21
OTHER DEALINGS IN THE SOFTWARE.
23
Except as contained in this notice, the name of The Open Group shall
24
not be used in advertising or otherwise to promote the sale, use or
25
other dealings in this Software without prior written authorization
29
Copyright 1989, 1990, 1991 by Sun Microsystems, Inc.
32
Permission to use, copy, modify, and distribute this software and its
33
documentation for any purpose and without fee is hereby granted,
34
provided that the above copyright notice appear in all copies and that
35
both that copyright notice and this permission notice appear in
36
supporting documentation, and that the name of Sun Microsystems
37
not be used in advertising or publicity pertaining to distribution
38
of the software without specific, written prior permission.
40
SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
41
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
42
SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
43
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
44
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
45
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49
/* $XFree86: xc/programs/Xserver/PEX5/ddpex/mi/level2/miTriStrip.c,v 3.7 2001/12/14 19:57:30 dawes Exp $ */
53
#include "miscstruct.h"
57
#include "PEXprotost.h"
65
static ddpex3rtn miClipTriStrip();
66
static ddpex3rtn miCullTriStrip();
67
static ddpex3rtn miDepthCueTriStrip();
68
static ddpex3rtn Complete_TriFacetList();
69
static ddpex3rtn Calculate_TriStrip_Facet_Normal();
70
static ddpex3rtn Calculate_TriStrip_Vertex_Color_and_Normal();
71
static ddpex3rtn Breakup_TriStrip();
75
| Function Name: miTriangleStrip
77
| Function Description:
78
| Handles the triangle strip OC.
85
miTriangleStrip(pRend, pExecuteOC)
87
ddRendererPtr pRend; /* renderer handle */
88
miGenericStr *pExecuteOC;
92
ddpex3rtn miTransform();
93
ddpex3rtn miConvertVertexColors();
94
ddpex3rtn miConvertFacetColors();
95
ddpex3rtn miLightTriStrip();
96
ddpex3rtn miRenderTriStrip();
97
ddpex3rtn ComputeMCVolume();
99
/* Local variable definitions */
100
miTriangleStripStruct *ddTri
101
= (miTriangleStripStruct *)(pExecuteOC+1);
102
miListHeader *input_list = &(ddTri->points); /* Input points */
103
listofddFacet *input_facet = ddTri->pFacets; /* facets */
104
miDDContext *pddc = (miDDContext *)(pRend->pDDContext);
105
miListHeader *color_list,
116
listofddFacet *color_facet,
127
ddPointType out_type;
132
* First, check data input
133
* At this point, the data is all in one list
136
if (input_list->numLists == 0) return(Success);
139
* Convert per-vertex and per-facet colors to rendering color model.
140
* Note that this implementation only supports rgb float.
143
if (DD_IsVertColour(input_list->type)) {
144
if (status = miConvertVertexColors(pRend,
145
input_list, PEXRdrColourModelRGB,
149
color_list = input_list;
152
if ((input_facet) && (DD_IsFacetColour(input_facet->type))) {
153
if (status = miConvertFacetColors(pRend,
154
input_facet, PEXRdrColourModelRGB,
158
color_facet = input_facet;
161
/* Check for Model clipping */
163
if (pddc->Dynamic->pPCAttr->modelClip == PEXClip) {
165
/* Compute modelling coord version of clipping volume */
166
ComputeMCVolume(pRend, pddc);
168
clip_mode = MI_MCLIP;
170
/* Tranform points to 4D for clipping */
171
out_type = color_list->type;
172
if (status = miTransform(pddc,
173
color_list, &mc_clist,
176
DD_SetVert4D(out_type)))
180
if (status = miClipTriStrip(pddc, mc_clist, color_facet,
181
&mc_list, &mc_facet, clip_mode))
184
/* if nothing left after model clip, return early */
185
if (mc_list->numLists <= 0) return(Success);
188
mc_list = color_list;
189
mc_facet = color_facet;
192
/* Note - After clipping the triangle strip may have
193
* decomposed into a number of separate triangle strips
198
* Next, check lighting requirements
201
if (pddc->Static.attrs->reflModel != PEXReflectionNoShading) {
203
/* Transform to WC prior to applying lighting */
204
out_type = mc_list->type;
205
if (DD_IsVertNormal(out_type)) VALIDATEINVTRMCTOWCXFRM(pddc);
206
if (status = miTransform(pddc,
208
pddc->Dynamic->mc_to_wc_xform,
209
pddc->Static.misc.inv_tr_mc_to_wc_xform,
210
DD_SetVert4D(out_type)))
213
/* Transform facet normals if necessary */
215
(mc_facet->numFacets > 0) &&
216
(DD_IsFacetNormal(mc_facet->type))) {
217
VALIDATEINVTRMCTOWCXFRM(pddc);
218
if (status = miFacetTransform(pddc,
220
pddc->Static.misc.inv_tr_mc_to_wc_xform))
222
} else wc_facet = mc_facet;
225
if (status = miLightTriStrip(pRend, pddc,
227
&light_list, &light_facet))
231
/* Transform to CC for clipping */
232
if (DD_IsVertNormal(light_list->type)) VALIDATEINVTRWCTOCCXFRM(pddc);
233
if (status = miTransform(pddc,
234
light_list, &cc_list,
235
pddc->Dynamic->wc_to_cc_xform,
236
pddc->Static.misc.inv_tr_wc_to_cc_xform,
240
/* Transform facet normals if necessary */
241
if ( (light_facet) &&
242
(light_facet->numFacets > 0) &&
243
(DD_IsFacetNormal(light_facet->type)) ) {
244
VALIDATEINVTRWCTOCCXFRM(pddc);
245
if (status = miFacetTransform(pddc,
246
light_facet, &cc_facet,
247
pddc->Static.misc.inv_tr_wc_to_cc_xform))
249
} else cc_facet = light_facet;
253
/* PEXReflectionNoShading case */
255
/* Now transform points and facets normals to CC */
256
out_type = mc_list->type;
257
if (DD_IsVertNormal(out_type)) VALIDATEINVTRMCTOCCXFRM(pddc);
258
if (status = miTransform(pddc,
260
pddc->Dynamic->mc_to_cc_xform,
261
pddc->Static.misc.inv_tr_mc_to_cc_xform,
262
DD_SetVert4D(out_type)))
266
(mc_facet->numFacets > 0) &&
267
(DD_IsFacetNormal(mc_facet->type)) ) {
268
VALIDATEINVTRMCTOCCXFRM(pddc);
269
if (status = miFacetTransform(pddc,
271
pddc->Static.misc.inv_tr_mc_to_cc_xform))
273
} else cc_facet = mc_facet;
277
/* View clip primitive */
278
clip_mode = MI_VCLIP;
279
if (status = miClipTriStrip(pddc, cc_list, cc_facet,
280
&clip_list, &clip_facet, clip_mode))
283
/* if nothing left after view clip, return early */
284
if (clip_list->numLists <= 0) return(Success);
286
/* Note - After View clipping, the triangle strip may have
287
* decomposed into a number of separate triangle strips
290
if (pddc->Dynamic->pPCAttr->cullMode) {
291
/* Now cull according to current culling mode */
292
if (status = miCullTriStrip(pddc, clip_list, clip_facet,
293
&cull_list, &cull_facet))
296
/* if nothing left after culling, return early */
297
if (cull_list->numLists <= 0) return(Success);
299
cull_list = clip_list;
300
cull_facet = clip_facet;
304
if (pddc->Dynamic->pPCAttr->depthCueIndex) {
305
miDepthCueTriStrip(pRend, cull_list, cull_facet, &dcue_list);
306
cull_list = dcue_list;
309
/* Lastly, transform to DC coordinates */
310
out_type = cull_list->type;
311
DD_SetVert2D(out_type);
312
DD_SetVertShort(out_type);
313
if (DD_IsVertNormal(out_type)) VALIDATEINVTRCCTODCXFRM(pddc);
314
if (status = miTransform(pddc,
316
pddc->Dynamic->cc_to_dc_xform,
317
pddc->Static.misc.inv_tr_cc_to_dc_xform,
321
/* Transform facet normals if necessary */
323
(cull_facet->numFacets > 0) &&
324
(DD_IsFacetNormal(cull_facet->type)) ) {
325
VALIDATEINVTRCCTODCXFRM(pddc);
326
if (status = miFacetTransform(pddc,
327
cull_facet, &dc_facet,
328
pddc->Static.misc.inv_tr_cc_to_dc_xform))
330
} else dc_facet = cull_facet;
332
return (pddc->Static.RenderProcs[TRISTRIP_RENDER_TABLE_INDEX](pRend,
337
/*************************************************************************/
341
| Function Name: miClipTriStrip
343
| Function Description:
344
| Clips a triangle strip. Note that this routine
345
| will return a triangle strip, though it sometimes creates
346
| "degenerate" (ie colinear vertices) triangles to achieve
347
| this result. At this point "hollow" filled triangles will
348
| exhibit clipping artifacts, (degenerate triangles) whereas
349
| "empty" fill with edge visibility enabled will not.
353
| This routine uses a Sutherland-Hodgman approach for
354
| polygon clipping. (See, for example, Rodger's "Procedural
355
| Elements for Computer Graphics", pp 169-179).
356
| Each triangle strip is clipped successively against each (enabled)
363
miClipTriStrip(pddc, input_vert, input_fct, output_vert, output_fct,clip_mode)
366
miListHeader *input_vert; /* input vertex data */
367
listofddFacet *input_fct; /* input facet data */
368
miListHeader **output_vert; /* output vertex data */
369
listofddFacet **output_fct; /* output facet data */
373
ddPointUnion in_ptP, in_ptQ, in_ptR;
375
float t_ptP, t_ptQ, t_ptR;
376
char *in_fct, *out_fct;
377
miListHeader *vinput, *voutput, *list1, *list2;
378
listofddFacet *finput, *foutput, *fct_list1, *fct_list2;
379
listofddPoint *pddilist;
380
listofddPoint *pddolist;
386
int clip_plane, j, k, out_listnum;
388
ddUSHORT current_clip;
390
ddHalfSpace *MC_HSpace;
391
ddVector3D PdotN, QdotN;
398
/* Vertex data must be homogeneous and contain more than two points
401
if (!(DD_IsVert4D(input_vert->type))
402
|| (input_vert->numLists == 0)) return(1);
405
* Use the pre-defined clip lists for output
409
* Must have edge flags in vertex if edges are to be drawn -
410
* otherwise, cannot determine wich edges are "original" and
411
* which edges where added by the clipper.
413
if ((pddc->Static.attrs->edges != PEXOff) &&
414
(!(DD_IsVertEdge(input_vert->type))))
416
if (status = miAddEdgeFlag(pddc, input_vert, &list1)) return(status);
420
/* Allocate an initial number of headers */
421
list1 = MI_NEXTTEMPDATALIST(pddc);
422
MI_ALLOCLISTHEADER(list1,
423
MI_ROUND_LISTHEADERCOUNT(input_vert->numLists));
424
if (!list1->ddList) return(BadAlloc);
425
list1->type = input_vert->type;
426
list1->flags = input_vert->flags;
427
vinput = input_vert; /* Initially set to input list */
430
list2 = MI_NEXTTEMPDATALIST(pddc);
431
MI_ALLOCLISTHEADER(list2,
432
MI_ROUND_LISTHEADERCOUNT(vinput->numLists));
433
if (!list2->ddList) return(BadAlloc);
434
list2->type = vinput->type;
435
list2->flags = vinput->flags;
439
* Initialize an output facet list. Note that facet lists are only
440
* maintained if an initial one is supplied.
441
* Note that twice the number of input facets is an upper bound,
442
* although there is probably a tighter "fit".
444
if ((input_fct) && (input_fct->numFacets)) {
446
DDFacetSIZE(input_fct->type, facet_size);
447
fct_list1 = MI_NEXTTEMPFACETLIST(pddc);
448
fct_list1->type = input_fct->type;
449
MI_ALLOCLISTOFDDFACET(fct_list1, 3*input_fct->numFacets, facet_size);
450
if (!fct_list1->facets.pFacetRgbFloatN)
454
fct_list2 = MI_NEXTTEMPFACETLIST(pddc);
455
fct_list2->type = input_fct->type;
456
MI_ALLOCLISTOFDDFACET(fct_list2, 3*input_fct->numFacets, facet_size);
457
if (!fct_list2->facets.pFacetRgbFloatN)
460
finput = foutput = fct_list1 = fct_list2 = 0;
463
* Get point size so that this works for all point types
465
DD_VertPointSize(vinput->type, point_size);
466
if DD_IsVertEdge(vinput->type)
467
DD_VertOffsetEdge(vinput->type, edge_offset);
470
* Each list is now clipped in turn against each (enabled) boundary.
473
if (clip_mode == MI_MCLIP)
474
num_planes = pddc->Static.misc.ms_MCV->numObj;
477
if (clip_mode == MI_MCLIP)
478
MC_HSpace = (ddHalfSpace *)(pddc->Static.misc.ms_MCV->pList);
480
for (clip_plane = 0; clip_plane < num_planes; clip_plane++) {
482
/* do entire list against one clipping plane at a time */
483
current_clip = 1 << clip_plane; /* current_clip is new clip bound */
486
* Triangle strips begin with only one input and output
487
* vertex list. If a facet is found to be entirely out
488
* of bounds, A new list is started at the new included
489
* point. This new series of lists is clipped in turn
490
* against the next clipping planei, and may be decomposed into
491
* yet more lists. However, only a single facet list is
492
* maintained, at it is assumed that a one<->one correspondence
493
* exists between vertex triads and facets (within a single list)
494
* even if degenerate facets are added.
498
in_fct = (char *)(finput->facets.pNoFacet);
499
MI_ALLOCLISTOFDDFACET(foutput,
500
(3*finput->numFacets), facet_size);
501
out_fct = (char *)(foutput->facets.pNoFacet);
504
for (j = 0, out_listnum = 0, new_list = 1, new_facets = 0,
505
pddilist = vinput->ddList, pddolist = voutput->ddList,
506
voutput->numLists = 0;
507
j < vinput->numLists; j++) {
510
/* Don't process if not enough points */
511
if ((vert_count = pddilist->numPoints) < 3) {
517
/* Insure sufficient room for vertecies and degenerate points
518
* Note that twice the vertex count is an upper-bound for
519
* a clipped triangle(although there is probably a "tighter fit").
522
MI_ALLOCLISTOFDDPOINT(pddolist, 2*vert_count, point_size);
523
out_pt = pddolist->pts;
524
if (!out_pt.ptr) return(BadAlloc);
527
/* Aquire first three points */
528
/* and generate clip code */
529
in_ptP.ptr = pddilist->pts.ptr;
530
COMPUTE_CLIP_PARAMS(in_ptP,t_ptP,0,clip_mode,
531
current_clip,MC_HSpace,clip_code);
532
in_ptQ.ptr = in_ptP.ptr + point_size;
533
COMPUTE_CLIP_PARAMS(in_ptQ, t_ptQ, 1, clip_mode,
534
current_clip,MC_HSpace,clip_code);
535
in_ptR.ptr = in_ptQ.ptr + point_size;
537
* Initialize the output array. The output array is expected
538
* to always contain the first two points, so load them -
539
* clipped if necessary.
543
case 0: /* both P and Q are in bounds */
544
COPY_POINT(in_ptP, out_pt, point_size);
545
out_pt.ptr += point_size;
546
COPY_POINT(in_ptQ, out_pt, point_size);
547
out_pt.ptr += point_size;
550
case 1: /* P is out, Q is in */
551
CLIP_AND_COPY(vinput->type, in_ptP, t_ptP,
552
in_ptQ, t_ptQ, out_pt);
553
out_pt.ptr += point_size;
554
COPY_POINT(in_ptQ, out_pt, point_size);
555
out_pt.ptr += point_size;
558
case 2: /* P is in, Q is out */
559
COPY_POINT(in_ptP, out_pt, point_size);
560
out_pt.ptr += point_size;
561
CLIP_AND_COPY(vinput->type, in_ptQ, t_ptQ,
562
in_ptP, t_ptP, out_pt);
563
out_pt.ptr += point_size;
566
case 3: /* both are out */
572
* For each vertex, clip a triangle.
573
* Each case assumes that points P & Q (the first and
574
* second points in the triangle, pointed to in the input
575
* list by in_ptR & in_ptQ) are already copied
576
* into the output array (clipped, if necessary and except for
577
* case 3), while R will be copied into the output array (pointed
578
* to by out_pt) if necessary during execution of the case
581
* It is important to note that if a facet is completely
582
* rejected, a new list is formed. Also, to maintain
583
* the correct "sense" of the normals, if the new
584
* list is about to begin on an even facet #, a
585
* degenerate facet is placed at the beginning of the
588
* Also, note that if additional facets are generated
589
* (cases 1,2,3,4,& 6) the artifact edge flag is set to zero.
590
* Within an edge flag, there are two bits determining edge
591
* visibility. Bit zero determines whether an edge is drawn
592
* between the current vertex N and vertex N-2, while bit one
593
* determines if an edge is drawn between edge N and N+1.
594
* If N-2 < 0 or N+1 > numfacets the edge is not drawn.
601
* 1<--------+3+---------5
603
* So, for the third element in the edge list,
604
* bit 0 indicates presence of an edge from 3 -> 4
606
* bit 1 indicates presence of an edge from 3 -> 1
609
* Also note that clipping in PHIGS does NOT
610
* display clipped edges along the boundaries, whereas fill
611
* area attribute HOLLOW does. This implementation does
612
* not handle the HOLLOW fill style properly in that respect.
613
* One possible solution is to use additional bits in the
617
for (k = 2; k < vert_count; k++) {
619
* Clip the new triangle
620
* There are 8 possible ways that the triangle (P, Q, R) can
621
* be intersected by a clipping plane:
623
* P, Q, R in P, Q, R out
624
* P in Q, R out P, Q in R out P, R in, Q out
625
* Q in P, R out Q, R in P out
628
* Each of these cases are handled separately.
632
COMPUTE_CLIP_PARAMS(in_ptR, t_ptR, 2, clip_mode,
633
current_clip,MC_HSpace,clip_code);
638
* Case 0 - trivial accept P, Q, and R
639
* Proceed to next triangle.
642
COPY_POINT(in_ptR, out_pt, point_size);
643
out_pt.ptr += point_size;
646
COPY_FACET(in_fct, out_fct, facet_size);
647
out_fct += facet_size;
653
* Case 1 - P is outside, Q & R are inside clip zone.
654
* This is a complex case which results in the creation
655
* of several new triangles including a "degenerate" triangle
656
* (two identical endpoints). Point "A" and point "Q" are
657
* already in the output list. Output vertex list is A-Q-B-Q-R
664
* P+-|------+R B+------+R
666
* triangle PQR triangles AQB, QBQ(degenerate)
671
/* If edges are visible,
672
* we wish to disable the edge from
673
* Q to B. This edge is specified
674
* by the forward edge of the first Q,
675
* the forward edge of B, and the
676
* backward edge of the second Q
678
if (pddc->Static.attrs->edges != PEXOff) {
679
out_pt.ptr -= point_size;
680
CLEAR_FWD_EDGE(out_pt.ptr, edge_offset);
681
/* edge from Q -> B */
682
out_pt.ptr += point_size;
685
CLIP_AND_COPY(vinput->type, in_ptP, t_ptP,
686
in_ptR, t_ptR, out_pt);
687
/* Places point "B" into output list */
688
if (pddc->Static.attrs->edges != PEXOff) {
689
CLEAR_FWD_EDGE(out_pt.ptr,edge_offset);
690
/* edge from B -> Q */
691
CLEAR_BKWD_EDGE(out_pt.ptr,edge_offset);
692
/* edge from B -> A */
694
out_pt.ptr += point_size;
696
COPY_POINT(in_ptQ, out_pt, point_size); /* degenerate point */
697
if (pddc->Static.attrs->edges != PEXOff)
698
CLEAR_BKWD_EDGE(out_pt.ptr,edge_offset);
699
out_pt.ptr += point_size;
701
COPY_POINT(in_ptR, out_pt, point_size);
702
out_pt.ptr += point_size;
707
* Add three identical facets
709
COPY_FACET(in_fct, out_fct, facet_size);
710
out_fct += facet_size;
711
COPY_FACET(in_fct, out_fct, facet_size);
712
out_fct += facet_size;
713
COPY_FACET(in_fct, out_fct, facet_size);
714
out_fct += facet_size;
720
* Case 2 - P is inside, Q is outside, R is inside.
721
* Points P and A are already in the output list.
722
* Output list is P-A-R-B-R : disable edges from
727
* ---------- ---+--+---
730
* P+--------+R P+--------+R
732
* triangle PQR triangles PAR, ARB, RBR
736
if (pddc->Static.attrs->edges != PEXOff) {
737
out_pt.ptr -= point_size;
738
CLEAR_FWD_EDGE(out_pt.ptr,edge_offset);
739
/* Edge from A -> R */
740
out_pt.ptr += point_size;
743
COPY_POINT(in_ptR, out_pt, point_size);
744
/* Place point "R" into output list */
745
if (pddc->Static.attrs->edges != PEXOff)
746
CLEAR_FWD_EDGE(out_pt.ptr,edge_offset);
747
/* Edge from R -> B */
748
out_pt.ptr += point_size;
750
CLIP_AND_COPY(vinput->type, in_ptQ, t_ptQ,
751
in_ptR, t_ptR, out_pt);
752
/*place point "B" into output list */
753
if (pddc->Static.attrs->edges != PEXOff)
754
CLEAR_BKWD_EDGE(out_pt.ptr,edge_offset);
755
/* Edge from B -> A */
756
out_pt.ptr += point_size;
758
COPY_POINT(in_ptR, out_pt, point_size); /* degenerate point */
759
out_pt.ptr += point_size;
764
* Add three identical facets
766
COPY_FACET(in_fct, out_fct, facet_size);
767
out_fct += facet_size;
768
COPY_FACET(in_fct, out_fct, facet_size);
769
out_fct += facet_size;
770
COPY_FACET(in_fct, out_fct, facet_size);
771
out_fct += facet_size;
777
* Case 3 - P and Q outside, R inside.
778
* Note - this is the first triangle in a new list
780
* Output list is A-B-R. If beginning on odd facet
781
* output list is B-A-B-R
791
* triangle PQR triangle ABR or BABR
797
* Note - this is the first triangle in a
798
* list, so copy the first two points in
799
* addition to copying the last point. Also,
800
* in model clipping we must be careful to
801
* preserve the "sense" of the normals, so
802
* add a degenerate facet if necessary.
806
CLIP_AND_COPY(vinput->type, in_ptQ, t_ptQ,
807
in_ptR, t_ptR, out_pt);
808
/*Places point "B" into output list */
809
out_pt.ptr += point_size;
812
COPY_FACET(in_fct, out_fct, facet_size);
813
out_fct += facet_size;
818
CLIP_AND_COPY(vinput->type, in_ptP, t_ptP,
819
in_ptR, t_ptR, out_pt);
820
/*Places point "A" into output list */
822
if (pddc->Static.attrs->edges != PEXOff)
823
CLEAR_FWD_EDGE(out_pt.ptr,edge_offset);
824
/*Edge from A -> B */
825
out_pt.ptr += point_size;
827
CLIP_AND_COPY(vinput->type, in_ptQ, t_ptQ,
828
in_ptR, t_ptR, out_pt);
829
/*Places point "B" into output list */
830
out_pt.ptr += point_size;
833
COPY_POINT(in_ptR, out_pt, point_size);
834
/*Places point "R" into output list */
835
out_pt.ptr += point_size;
838
COPY_FACET(in_fct, out_fct, facet_size);
839
out_fct += facet_size;
846
* Case 4 - P and Q inside, R outside
847
* Output list is P-Q-B-Q-A
854
* P+------|-+R P+------+B
857
* triangle PQR triangles PQB, BQB, BQA
862
if (pddc->Static.attrs->edges != PEXOff) {
863
out_pt.ptr -= point_size;
864
CLEAR_FWD_EDGE(out_pt.ptr, edge_offset);
865
/* edge from Q -> B */
866
out_pt.ptr += point_size;
869
CLIP_AND_COPY(vinput->type, in_ptR, t_ptR,
870
in_ptP, t_ptP, out_pt);
871
/* Places "B" into output */
872
if (pddc->Static.attrs->edges != PEXOff)
873
CLEAR_FWD_EDGE(out_pt.ptr,edge_offset);
874
/* Edge from B -> Q */
875
out_pt.ptr += point_size;
877
COPY_POINT(in_ptQ, out_pt, point_size);
878
/* Places "Q" into output */
879
if (pddc->Static.attrs->edges != PEXOff)
880
CLEAR_FWD_EDGE(out_pt.ptr,edge_offset);
881
/* Edge from Q -> B */
882
out_pt.ptr += point_size;
884
CLIP_AND_COPY(vinput->type, in_ptR, t_ptR,
885
in_ptQ, t_ptQ, out_pt);
886
/* Places "A" into output */
887
if (pddc->Static.attrs->edges != PEXOff)
888
CLEAR_BKWD_EDGE(out_pt.ptr,edge_offset);
889
/* Edge from A -> B */
890
out_pt.ptr += point_size;
895
* Add three identical facets
897
COPY_FACET(in_fct, out_fct, facet_size);
898
out_fct += facet_size;
899
COPY_FACET(in_fct, out_fct, facet_size);
900
out_fct += facet_size;
901
COPY_FACET(in_fct, out_fct, facet_size);
902
out_fct += facet_size;
908
* Case 5 - P and R are outside, Q in inside.
909
* Output list is A-Q-B. A and Q already in list
913
* ---------- ---+--+---
918
* triangle PQR triangles AQB
922
CLIP_AND_COPY(vinput->type, in_ptR, t_ptR,
923
in_ptQ, t_ptQ, out_pt);
924
/*Places point "B" into output list */
925
if (pddc->Static.attrs->edges != PEXOff)
926
CLEAR_BKWD_EDGE(out_pt.ptr,edge_offset);
927
/* Edge from B -> A */
928
out_pt.ptr += point_size;
932
COPY_FACET(in_fct, out_fct, facet_size);
933
out_fct += facet_size;
939
* Case 6 - P is inside, R and Q are outside
940
* Output list is: P-A-B
949
* triangle PQR triangles
953
if (pddc->Static.attrs->edges != PEXOff) {
954
out_pt.ptr -= point_size;
955
CLEAR_FWD_EDGE(out_pt.ptr,edge_offset);
956
out_pt.ptr += point_size;
959
CLIP_AND_COPY(vinput->type, in_ptR, t_ptR,
960
in_ptP, t_ptP, out_pt);
961
/* Places "B" into output list */
962
out_pt.ptr += point_size;
966
COPY_FACET(in_fct, out_fct, facet_size);
967
out_fct += facet_size;
973
* Case 7 - P, Q, and R are outside
974
* trivial rejection; begin new list
975
* at first "included" point if
976
* sufficient number of points
987
/* Complete initialization of last list */
988
if (pts_in_list > 2) {
989
/* Generate a new output list, increment list count. */
990
pddolist->numPoints = pts_in_list;
993
MI_ALLOCLISTHEADER(voutput,
994
MI_ROUND_LISTHEADERCOUNT(voutput->numLists));
995
/* skip to next output list */
996
pddolist = voutput->ddList + out_listnum;
998
/* Insure sufficient room for remaining verts
999
and degenerate points */
1000
MI_ALLOCLISTOFDDPOINT(pddolist,
1001
2*(vert_count - k), point_size);
1003
out_pt.ptr = pddolist->pts.ptr;
1004
if (!out_pt.ptr) return(BadAlloc);
1008
/* Not enough points for output list */
1009
pddolist->numPoints = 0;
1012
/* Look for next point inside bounds */
1015
in_ptR.ptr += point_size;
1016
if (finput) in_fct += facet_size;
1018
if (k == vert_count)
1020
COMPUTE_CLIP_PARAMS(in_ptR, t_ptR, 2, clip_mode,
1021
current_clip,MC_HSpace,clip_code);
1023
if (k < vert_count) {
1025
* k is incremented by the for loop, but because we have
1026
* a new_list, the pointers won't get bumped. Therefore,
1027
* k must be decremented to keep it consistent with the
1028
* pointers for reentering the for loop.
1030
* However, k must not be adjusted when k == vert_count,
1031
* because in this case P, Q and R are all clipped and it
1032
* is necessary to leave k == vert_count to terminate the
1037
/* Get P & Q; re-enter loop.
1038
* Next case encountered will be 3, which will
1039
* handle the odd-even rule for normals.
1041
in_ptQ.ptr = in_ptR.ptr - point_size;
1042
in_ptP.ptr = in_ptQ.ptr - point_size;
1043
clip_code = 0; /* Q's ORd in at top of loop */
1044
COMPUTE_CLIP_PARAMS(in_ptP, t_ptP, 0, clip_mode,
1045
current_clip,MC_HSpace,clip_code);
1046
COMPUTE_CLIP_PARAMS(in_ptQ, t_ptQ, 1, clip_mode,
1047
current_clip,MC_HSpace,clip_code);
1050
pts_in_list = 0; /*start a new list*/
1053
} /* end of cases */
1056
/* Prepare for next point */
1057
in_ptP = in_ptQ; t_ptP = t_ptQ;
1058
in_ptQ = in_ptR; t_ptQ = t_ptR;
1059
in_ptR.ptr += point_size;
1060
if (finput) in_fct += facet_size;
1064
} /* end of single list processing */
1066
if (pts_in_list > 2) { /* Got some points! */
1067
/* skip to next list, increment list count. */
1068
pddolist->numPoints = pts_in_list;
1071
++voutput->numLists;
1073
else pddolist->numPoints = 0; /* use same list */
1076
} /* end of list of lists processing */
1078
if (foutput) foutput->numFacets = new_facets;
1080
if (out_listnum > 0) {
1081
/* Use result of previous clip for input to next clip */
1083
if (voutput == list2) voutput = list1; /* ping-pong */
1084
else voutput = list2;
1087
/* Use result of previous clip for input to next clip */
1089
if (foutput == fct_list2) foutput = fct_list1;
1090
else foutput = fct_list2;
1093
/* If no lists, exit loop */
1097
if (clip_mode == MI_MCLIP) MC_HSpace++;
1099
} /* end of processing for all clip planes */
1102
/* Current input list is last processed (clipped) list */
1103
*output_vert = vinput;
1104
if (finput) *output_fct = finput;
1105
else *output_fct = input_fct;
1118
| Perform lighting calculations for the vertex or facet
1119
| data provided according to the current attributes.
1124
miLightTriStrip(pRend, pddc, input_vert, input_fct, output_vert, output_fct)
1125
ddRendererPtr pRend; /* renderer handle */
1126
miDDContext *pddc; /* dd Context pointer */
1127
miListHeader *input_vert; /* input vertex data */
1128
listofddFacet *input_fct; /* input facet data */
1129
miListHeader **output_vert; /* output vertex data */
1130
listofddFacet **output_fct; /* output facet data */
1133
ddpex3rtn miApply_Lighting();
1134
ddpex3rtn miFilterPath();
1137
listofddFacet *fct_list, *broken_fct;
1138
miListHeader *out_vert, *broken_list;
1139
ddVector3D in_vertnorm;
1140
ddRgbFloatColour in_vertcolour;
1141
ddRgbFloatNormal *in_fct;
1142
ddRgbFloatColour *out_fct;
1143
listofddPoint *pddilist;
1144
listofddPoint *pddolist;
1145
ddPointUnion in_pt, out_pt;
1146
int i, j, k, num_facets,
1147
inpoint_size, outpoint_size;
1151
/* Look for empty fill style. Still might have to render edges. */
1152
if (pddc->Static.attrs->intStyle == PEXInteriorStyleEmpty)
1156
* First, Insure that the vertex and/or facet data
1157
* is sufficient for the current Surface Interpolation method.
1158
* Note that this implementation does not support
1159
* PEXSurfaceInterpDotProduct and PEXSurfaceInterpNormal and
1160
* that these surface interpolation types are approximated by
1161
* PEXSurfaceInterpColour. The cases dealt with here, therefore,
1162
* are constant surface color (thus a single color is computed
1163
* per facet) and interpolated surface color (thus a color
1164
* per vertex is required).
1167
DD_VertPointSize(input_vert->type, inpoint_size);
1168
switch(pddc->Static.attrs->surfInterp) {
1170
case PEXSurfaceInterpNone: /* Flat shading */
1173
(input_fct->numFacets == 0) ||
1174
(!( (DD_IsFacetColour(input_fct->type)) &&
1175
(DD_IsFacetNormal(input_fct->type))))) {
1177
Complete_TriFacetList(pRend, input_vert, input_fct,
1180
input_fct = *output_fct;
1184
* Should have facets with normals and surface colors now.
1185
* Since we are flat shading, there is no further use
1186
* for per-vertex color or normal data (however, leave
1187
* any edge information). Remove it to prevent confusion
1188
* further down the pipeline.
1190
if ( (DD_IsVertNormal(input_vert->type)) ||
1191
(DD_IsVertColour(input_vert->type)) ) {
1192
if (status = miFilterPath(pddc, input_vert, output_vert,
1196
*output_vert = input_vert;
1200
* Now allocate storage for the output facet list
1201
* Note that the output facet list only contains colors.
1203
*output_fct = fct_list = MI_NEXTTEMPFACETLIST(pddc);
1204
fct_list->numFacets = input_fct->numFacets;
1205
fct_list->type = DD_FACET_RGBFLOAT;
1206
MI_ALLOCLISTOFDDFACET(fct_list, input_fct->numFacets,
1207
sizeof(ddRgbFloatColour));
1208
if (!(out_fct = fct_list->facets.pFacetRgbFloat)) return(BadAlloc);
1209
in_fct = input_fct->facets.pFacetRgbFloatN;
1210
pddilist = input_vert->ddList;
1211
for(i = 0, in_pt.ptr = pddilist->pts.ptr;
1212
i < input_vert->numLists; i++) {
1215
* Compute lighted facet color for each facet.
1216
* Facet color is simply the sum of the lighting contributions
1217
* from each light source.
1219
for (k = 2; k < pddilist->numPoints; k++) {
1221
/* One point at a time. Again, it is assumed there is a */
1222
/* one<->one correspondence between the points in the lists */
1223
/* and individual facets. Also note that we are associating */
1224
/* arbitrarily the first point with the "position" of the */
1225
/* facet. Perhaps a more correct method would use that average */
1227
if (status = miApply_Lighting(pRend, pddc,
1234
in_pt.ptr += inpoint_size;
1238
/* skip to next input vertex list */
1243
case PEXSurfaceInterpColour:
1244
case PEXSurfaceInterpDotProduct:
1245
case PEXSurfaceInterpNormal:
1247
if (!DD_IsVertNormal(input_vert->type)) {
1248
/* Here, and only here, we must create a separate list for
1249
* facet of the triangle strip. The reason for this is that
1250
* we can only associate with each vertex a single normal,
1251
* when in reality a vertex has different normals depending
1252
* upon which facet is being rendered. The lighting effects
1253
* only appear in positional lights, because the dot
1254
* product with the vertex normals is indeed dependent upon
1257
if (i = Breakup_TriStrip(pddc, input_vert, input_fct,
1258
&broken_list, &broken_fct)) return (i);
1259
input_vert = broken_list;
1260
input_fct = broken_fct;
1263
/* Insure sufficient info for calculation */
1264
if ( (!DD_IsVertColour(input_vert->type)) ||
1265
(!DD_IsVertNormal(input_vert->type)) ) {
1266
Calculate_TriStrip_Vertex_Color_and_Normal(pRend, input_vert,
1269
input_vert = *output_vert;
1272
/* From here facet data only used in culling operation */
1273
*output_fct = input_fct;
1275
/* Use one of the pre-defined 4D list for output */
1276
*output_vert = out_vert = MI_NEXTTEMPDATALIST(pddc);
1278
/* Insure sufficient room for each header */
1279
MI_ALLOCLISTHEADER(out_vert,
1280
MI_ROUND_LISTHEADERCOUNT(input_vert->numLists))
1281
if (!out_vert->ddList) return(BadAlloc);
1283
out_vert->type = DD_RGBFLOAT_POINT4D;
1284
if (pddc->Static.attrs->edges != PEXOff &&
1285
DD_IsVertEdge(input_vert->type)) {
1286
DD_SetVertEdge(out_vert->type);
1288
out_vert->numLists = input_vert->numLists;
1289
out_vert->flags = input_vert->flags;
1291
DD_VertPointSize(out_vert->type, outpoint_size);
1292
pddilist = input_vert->ddList;
1293
pddolist = out_vert->ddList;
1295
for(i = 0; i < input_vert->numLists; i++) {
1297
pddolist->numPoints = pddilist->numPoints;
1298
MI_ALLOCLISTOFDDPOINT(pddolist, pddolist->numPoints,
1300
if (!(out_pt.ptr = pddolist->pts.ptr)) return(BadAlloc);
1302
for (j = 0, in_pt.ptr = pddilist->pts.ptr;
1303
j < pddilist->numPoints; j++) {
1305
/* Copy over the coordinate info */
1306
*out_pt.p4Dpt = *in_pt.p4Dpt;
1308
/* move output pointer to colour field */
1311
/* miApplyLighting works on a single point at a time */
1312
if (status = miApply_Lighting(pRend, pddc,
1314
&(in_pt.pRgbFloatNpt4D->colour),
1315
&(in_pt.pRgbFloatNpt4D->normal),
1316
out_pt.pRgbFloatClr))
1319
/* increment pointers */
1320
in_pt.pRgbFloatNpt4D++;
1321
out_pt.pRgbFloatClr++;
1323
if (DD_IsVertEdge(out_vert->type)) {
1324
*out_pt.pEdge = *in_pt.pEdge;
1331
/* skip to next input and output vertex list */
1339
*output_vert = input_vert;
1340
*output_fct = input_fct;
1349
| Complete_TriFacetList(pRend, input_vert, output_fct)
1351
| Generates a facet list with colors and normals
1352
| This routine should get folded into one with
1353
| Create_Normals, with some form of flag to signal
1354
| the type of output required. It would also be the
1355
| place to put back-face attribute distinction.
1362
Complete_TriFacetList(pRend, input_vert, input_fct, output_fct)
1363
ddRendererPtr pRend; /* renderer handle */
1364
miListHeader *input_vert; /* input vertex data */
1365
listofddFacet *input_fct; /* input facet data */
1366
listofddFacet **output_fct; /* output facet data */
1369
miDDContext *pddc = (miDDContext *)(pRend->pDDContext);
1370
listofddFacet *fct_list;
1371
ddRgbFloatNormal *out_fct;
1372
listofddPoint *pddlist;
1373
ddPointUnion in_pt, tmp_pt;
1374
ddFacetUnion in_fct;
1376
ddRgbFloatPoint4D *vert1, *vert2, *vert3;
1381
char have_colors, have_normals;
1383
have_colors = have_normals = 0;
1385
/* What data must be added to output facet list ? */
1386
if (!(input_fct) || (input_fct->type == DD_FACET_NONE)) {
1388
* Since we are creating the facet list for the first
1389
* we need to learn how many verticies are in all the
1392
pddlist = input_vert->ddList;
1393
for (i = 0, total_facets = 0; i < input_vert->numLists; pddlist++, i++)
1394
total_facets += (pddlist->numPoints - 2);
1396
/* use input facet information */
1397
total_facets = input_fct->numFacets;
1398
in_fct.pNoFacet = input_fct->facets.pNoFacet;
1399
if DD_IsFacetNormal(input_fct->type) have_normals = ~0;
1400
if DD_IsFacetColour(input_fct->type) have_colors = ~0;
1403
if ((have_colors) && (have_normals)) { /* Why are we here? */
1404
*output_fct = input_fct;
1409
* Allocate storage for the facet list
1411
fct_list = MI_NEXTTEMPFACETLIST(pddc);
1412
fct_list->type = DD_FACET_RGBFLOAT_NORM;
1413
MI_ALLOCLISTOFDDFACET(fct_list, total_facets, sizeof(ddRgbFloatNormal));
1414
if (!fct_list->facets.pNoFacet) return(BadAlloc);
1415
out_fct = (ddRgbFloatNormal *)fct_list->facets.pFacetRgbFloatN;
1417
DD_VertPointSize(input_vert->type, point_size);
1419
/* Don't process if insufficient number of points */
1421
if (input_vert->numLists > 0) {
1423
pddlist = input_vert->ddList;
1425
for (i = 0; i < input_vert->numLists; i++) {
1427
in_pt.ptr = pddlist->pts.ptr;
1429
for (j = 2; j < pddlist->numPoints; j++) {
1432
* Compute "intrinsic" color of facet.
1433
* There is a "hierarchy" of sources for a facet's intrinsic
1435
* vertex_colors present? facet_color =
1436
* vertex_color of 1st point of facet
1437
* else facet_color present? facet_color = facet_color
1438
* else facet_color = PC_surface_color
1439
* Note - this needs to be enhanced, using a dot product
1440
* with the eye position to determine which surface color
1441
* should be assigned in the case of front/back face
1442
* distinguishing. this entire routine might get rolled into
1443
* miLightTriStrip, and the correct color and reflectance
1444
* model get passed into miApplyLighting.
1447
if (DD_IsVertColour(input_vert->type)) {
1449
out_fct->colour.red=out_fct->colour.green=out_fct->colour.blue=0.0;
1450
vert1 = in_pt.pRgbFloatpt4D;
1451
tmp_pt.ptr = in_pt.ptr + point_size;
1452
vert2 = tmp_pt.pRgbFloatpt4D;
1453
tmp_pt.ptr += point_size;
1454
vert3 = tmp_pt.pRgbFloatpt4D;
1456
out_fct->colour.red = ( vert1->colour.red +
1458
vert3->colour.red )/3.0;
1459
out_fct->colour.green = ( vert1->colour.green +
1460
vert2->colour.green +
1461
vert3->colour.green )/3.0;
1462
out_fct->colour.blue = ( vert1->colour.blue +
1463
vert2->colour.blue +
1464
vert3->colour.blue )/3.0;
1466
} else if (have_colors) {
1467
out_fct->colour = *in_fct.pFacetRgbFloat;
1468
in_fct.pFacetRgbFloat++;
1470
/* use front face colors. This needs to get generalized
1471
to deal with back-facing attributes*/
1473
(pddc->Static.attrs->surfaceColour.colour.rgbFloat);
1476
if (!(have_normals)) {
1478
* Compute surface normal. Normals are required in
1479
* Apply_Lighting for directional and positional lights,
1480
* as well as culling (if enabled). One COULD check
1481
* for ambient only, no culling, to optimize.
1483
* The Surface normal is the cross product
1484
* of three non-colinear points, in correct order.
1487
vert1 = in_pt.pRgbFloatpt4D;
1488
tmp_pt.ptr = in_pt.ptr + point_size;
1489
vert2 = tmp_pt.pRgbFloatpt4D;
1490
tmp_pt.ptr += point_size;
1491
vert3 = tmp_pt.pRgbFloatpt4D;
1494
CROSS_PRODUCT((&(vert3->pt)), (&(vert2->pt)), (&(vert1->pt)),
1495
&(out_fct->normal));
1498
CROSS_PRODUCT((&(vert1->pt)), (&(vert2->pt)), (&(vert3->pt)),
1499
&(out_fct->normal));
1502
NORMALIZE_VECTOR(&(out_fct->normal), length);
1504
/* Initialize to zero if triangle is
1505
* degenerate and points are co-linear
1508
if NEAR_ZERO(length) {
1509
/* degenerate facet */
1510
(out_fct->normal.x = 0.0);
1511
(out_fct->normal.y = 0.0);
1512
(out_fct->normal.z = 0.0);
1515
/* use input facet normals */
1516
out_fct->normal = *in_fct.pFacetN;
1520
/* Process next facet */
1522
in_pt.ptr += point_size;
1528
fct_list->numFacets = total_facets;
1529
fct_list->type = DD_FACET_RGBFLOAT_NORM;
1532
fct_list->type = DD_FACET_NONE;
1533
fct_list->numFacets = 0;
1536
*output_fct = fct_list;
1543
| Calculate_TriStrip_Facet_Normal
1545
| Add facet normals to a facet list.
1546
| Here we are counting on the fact that there is a one to one
1547
| correspondance between input facets and vertex ordering.
1552
Calculate_TriStrip_Facet_Normal(pddc, input_vert, input_fct, output_fct)
1554
miListHeader *input_vert; /* input vertex data */
1555
listofddFacet *input_fct; /* input facet data */
1556
listofddFacet **output_fct; /* output facet data */
1559
listofddFacet *fct_list;
1560
ddRgbFloatColour *in_fct;
1561
ddFacetUnion out_fct;
1562
listofddPoint *pddlist;
1563
ddPointUnion in_pt, nxt_pt;
1566
ddCoord3D *vert1, *vert2, *vert3;
1572
/* Some quick error checking */
1573
if ((input_fct) && (DD_IsFacetNormal(input_fct->type))) return(Success);
1577
* First, allocate storage for the facet list
1579
fct_list = MI_NEXTTEMPFACETLIST(pddc);
1580
if ((input_fct) && DD_IsFacetColour(input_fct->type)) {
1581
in_fct = input_fct->facets.pFacetRgbFloat;
1582
fct_list->type = DD_FACET_RGBFLOAT_NORM;
1583
numfacets = input_fct->numFacets;
1584
MI_ALLOCLISTOFDDFACET(fct_list, numfacets, sizeof(ddRgbFloatNormal));
1587
fct_list->type = DD_FACET_NORM;
1590
/* Determine the total number of facets in all the lists */
1591
for (i = 0, numfacets = 0, pddlist = input_vert->ddList;
1592
i < input_vert->numLists; pddlist++, i++)
1593
numfacets += (pddlist->numPoints - 2);
1595
MI_ALLOCLISTOFDDFACET(fct_list, numfacets, sizeof(ddVector3D));
1598
fct_list->numFacets = numfacets;
1599
if (!fct_list->facets.pNoFacet) return(BadAlloc);
1602
out_fct = fct_list->facets;
1603
DD_VertPointSize(input_vert->type, point_size);
1605
/* Don't process if no facets (!) */
1606
if (numfacets == 0) return(1);
1609
for(i = 0, pddlist = input_vert->ddList;
1610
i < input_vert->numLists; i++) {
1611
for (j = 2, in_pt.ptr = pddlist->pts.ptr;
1612
j < pddlist->numPoints; j++) {
1614
/* Copy the input facet color */
1616
*out_fct.pFacetRgbFloat = *in_fct;
1620
/* Calculate and copy normal */
1622
vert1 = in_pt.p3Dpt;
1623
nxt_pt.ptr = in_pt.ptr + point_size;
1624
vert2 = nxt_pt.p3Dpt;
1625
nxt_pt.ptr += point_size;
1626
vert3 = nxt_pt.p3Dpt;
1629
CROSS_PRODUCT(vert3, vert2, vert1, &normal);
1631
CROSS_PRODUCT(vert1, vert2, vert3, &normal);
1634
NORMALIZE_VECTOR(&normal, length)
1636
/* Initialize to zero if triangle is
1637
* degenerate and points are co-linear
1640
if (length == 0.0) {
1647
if (in_fct) (out_fct.pFacetRgbFloatN++)->normal = normal;
1648
else *(out_fct.pFacetN++) = normal;
1650
in_pt.ptr += point_size;
1656
*output_fct = fct_list;
1666
| Breaks up a triangle strip into as many lists as there are facets.
1667
| This is necessary for shading interpolation methods as we need to
1668
| facilitate a set of normals per facet.
1675
Breakup_TriStrip(pddc, input_vert, input_fct, output_vert, output_fct)
1677
miListHeader *input_vert;
1678
miListHeader **output_vert;
1679
listofddFacet *input_fct; /* input facet data */
1680
listofddFacet **output_fct; /* output facet data */
1682
miListHeader *list1;
1683
listofddFacet *fct_list;
1684
ddRgbFloatColour *in_fct;
1685
ddFacetUnion out_fct;
1686
listofddPoint *pddilist, *pddolist;
1687
ddPointUnion pt_in, nxt_pt;
1688
char *in_vert, *out_vert;
1690
int numfacets, facetofpoints;
1695
/* make sure that we have a facet list, and that it has normals */
1696
if (!((input_fct) && (DD_IsFacetNormal(input_fct->type)))) {
1697
if (i = Calculate_TriStrip_Facet_Normal(pddc, input_vert,
1698
input_fct, &fct_list))
1700
input_fct = fct_list;
1703
list1 = MI_NEXTTEMPDATALIST(pddc);
1704
MI_ALLOCLISTHEADER(list1,
1705
MI_ROUND_LISTHEADERCOUNT(input_fct->numFacets));
1706
if (!list1->ddList) return(BadAlloc);
1707
list1->type = input_vert->type;
1708
list1->flags = input_vert->flags;
1710
list1->numLists = input_fct->numFacets;
1713
DD_VertPointSize(input_vert->type, point_size);
1714
facetofpoints = 3 * point_size;
1716
for(i = 0, pddilist = input_vert->ddList,
1717
pddolist = list1->ddList;
1718
i < input_vert->numLists; i++) {
1720
for (j = 2, pt_in.ptr = pddilist->pts.ptr;
1721
j < pddilist->numPoints; j++) {
1723
MI_ALLOCLISTOFDDPOINT(pddolist, 1, facetofpoints);
1726
* Note that to preserver correct normals, must
1727
* flip the order of the vertices every other facet.
1731
in_vert = pt_in.ptr + 2*point_size;
1732
out_vert = pddolist->pts.ptr;
1733
memcpy( out_vert, in_vert, point_size);
1734
in_vert -= point_size; out_vert += point_size;
1735
memcpy( out_vert, in_vert, point_size);
1736
out_vert += point_size;
1737
memcpy( out_vert, pt_in.ptr, point_size);
1741
memcpy( pddolist->pts.ptr, pt_in.ptr, facetofpoints);
1745
pddolist->numPoints = 3;
1746
pddolist++; /* one list per facet */
1747
pt_in.ptr += point_size;
1752
*output_fct = input_fct;
1753
*output_vert = list1;
1763
| Calculate_TriStrip_Vertex_Color_and_Normal
1765
| Add vertex normals and colors to a vertex list.
1770
Calculate_TriStrip_Vertex_Color_and_Normal(pRend, input_vert, input_fct,
1773
ddRendererPtr pRend; /* renderer handle */
1774
miListHeader *input_vert; /* input vertex data */
1775
listofddFacet *input_fct; /* input facet data */
1776
miListHeader **output_vert; /* output vertex data */
1778
miDDContext *pddc = (miDDContext *)(pRend->pDDContext);
1779
miListHeader *out_vert;
1780
listofddFacet *fct_list;
1781
ddRgbFloatNormal *out_fct;
1782
listofddPoint *pddilist;
1783
listofddPoint *pddolist;
1784
ddPointUnion in_pt, out_pt;
1785
ddFacetUnion in_fct;
1786
int inpoint_size, outpoint_size;
1793
/* Some quick error checking */
1794
if ((DD_IsVertNormal(input_vert->type)) &&
1795
(DD_IsVertColour(input_vert->type)))
1798
/* Use one of the pre-defined 4D list for output */
1799
*output_vert = out_vert = MI_NEXTTEMPDATALIST(pddc);
1801
/* Insure sufficient room for each header */
1802
MI_ALLOCLISTHEADER(out_vert,
1803
MI_ROUND_LISTHEADERCOUNT(input_vert->numLists))
1804
if (!out_vert->ddList) return(BadAlloc);
1806
out_vert->type = DD_RGBFLOAT_NORM_POINT4D;
1807
if (pddc->Static.attrs->edges != PEXOff &&
1808
DD_IsVertEdge(input_vert->type)) {
1809
DD_SetVertEdge(out_vert->type);
1811
out_vert->numLists = input_vert->numLists;
1812
out_vert->flags = input_vert->flags;
1814
pddilist = input_vert->ddList;
1815
pddolist = out_vert->ddList;
1817
DD_VertPointSize(input_vert->type, inpoint_size);
1818
DD_VertPointSize(out_vert->type, outpoint_size);
1820
/* Compute facet normals if no per-vertex normals with data */
1821
if ( (!(DD_IsVertNormal(input_vert->type))) &&
1822
((!(input_fct)) || (!(DD_IsFacetNormal(input_fct->type)))) ) {
1824
if (i = Calculate_TriStrip_Facet_Normal(pddc, input_vert,
1825
input_fct, &fct_list))
1828
input_fct = fct_list;
1831
if ((input_fct) && (input_fct->numFacets > 0)) {
1832
in_fct = input_fct->facets;
1833
DDFacetSIZE(input_fct->type, facet_size);
1835
else in_fct.pNoFacet = 0;
1838
for(i = 0; i < input_vert->numLists; i++) {
1839
pddolist->numPoints = pddilist->numPoints;
1840
in_pt.ptr = pddilist->pts.ptr;
1841
MI_ALLOCLISTOFDDPOINT(pddolist,(pddilist->numPoints+1),
1843
if (!(out_pt.ptr = pddolist->pts.ptr)) return(BadAlloc);
1845
for (j = 0, in_pt.ptr = pddilist->pts.ptr,
1846
out_pt.ptr = pddolist->pts.ptr;
1847
j < pddilist->numPoints; j++) {
1849
/* First copy over coordinate data */
1850
*out_pt.p4Dpt = *in_pt.p4Dpt;
1856
* Colour is derived first from the vertex, second from the
1857
* facet, and third from the current PC attributes.
1859
if (DD_IsVertColour(input_vert->type)){
1860
*out_pt.pRgbFloatClr = *in_pt.pRgbFloatClr;
1861
in_pt.pRgbFloatClr++;
1864
if ((in_fct.pNoFacet) && (DD_IsFacetColour(input_fct->type)))
1865
*out_pt.pRgbFloatClr = *in_fct.pFacetRgbFloat;
1867
*out_pt.pRgbFloatClr =
1868
(pddc->Static.attrs->surfaceColour.colour.rgbFloat);
1872
out_pt.pRgbFloatClr++;
1876
* Normals are derived first from the vertex, second from the
1877
* facet (note that we insured above that there were facet normals).
1879
if DD_IsVertNormal(input_vert->type) {
1880
*out_pt.pNormal = *in_pt.pNormal;
1883
else if (DD_IsFacetColour(input_fct->type))
1884
*out_pt.pNormal = in_fct.pFacetRgbFloatN->normal;
1885
else *out_pt.pNormal = *in_fct.pFacetN;
1889
/* Next pass along edge info if there is any */
1890
if (DD_IsVertEdge(out_vert->type)) {
1891
*out_pt.pEdge = *in_pt.pEdge;
1897
if ((in_fct.pNoFacet)) in_fct.pNoFacet += facet_size;
1906
| miCullTriStrip(pddc, input_vert, input_fct, output_vert, output_fct)
1908
| Perform culling of facets, and their associated data points,
1909
| according to the current culling mode.
1915
miCullTriStrip(pddc, input_vert, input_fct, output_vert, output_fct)
1916
miDDContext *pddc; /* dd Context pointer */
1917
miListHeader *input_vert; /* input vertex data */
1918
listofddFacet *input_fct; /* input facet data */
1919
miListHeader **output_vert; /* output vertex data */
1920
listofddFacet **output_fct; /* output facet data */
1923
miListHeader *out_vert;
1924
listofddPoint *pddilist;
1925
listofddPoint *pddolist;
1926
listofddFacet *fct_list;
1927
ddFacetUnion in_fct;
1928
ddFacetUnion out_fct;
1929
ddPointUnion in_pt,out_pt;
1932
char accept, new_list;
1933
char return_facet_list;
1934
int point_size, facet_size;
1935
int verts_in_list, out_listnum;
1938
* Create facet normals if necessary. These are used to determine
1939
* if the facet is to be culled. Note: only return a facet list
1940
* if a valid facet list is input.
1942
if ( (!input_fct) || (input_fct->numFacets <= 0) ) {
1943
Calculate_TriStrip_Facet_Normal(pddc, input_vert,
1944
(listofddFacet *)0, &input_fct);
1945
return_facet_list = 0;
1948
if (!(DD_IsFacetNormal(input_fct->type))) {
1949
Calculate_TriStrip_Facet_Normal(pddc, input_vert,
1950
input_fct, output_fct);
1951
input_fct = *output_fct;
1953
return_facet_list = 1;
1957
* allocate storage for the output vertex and facet list
1959
*output_vert = out_vert = MI_NEXTTEMPDATALIST(pddc);
1960
out_vert->type = input_vert->type;
1961
out_vert->flags = input_vert->flags;
1962
out_vert->numLists = 0;
1963
MI_ALLOCLISTHEADER(out_vert,
1964
MI_ROUND_LISTHEADERCOUNT(input_vert->numLists))
1965
if (!out_vert->ddList) return(BadAlloc);
1968
DD_VertPointSize(input_vert->type, point_size);
1970
fct_list = MI_NEXTTEMPFACETLIST(pddc);
1971
fct_list->type = input_fct->type;
1972
DDFacetSIZE(input_fct->type, facet_size);
1973
MI_ALLOCLISTOFDDFACET(fct_list, input_fct->numFacets, facet_size);
1974
out_fct = fct_list->facets;
1975
if (!out_fct.pNoFacet) return(BadAlloc);
1976
in_fct = input_fct->facets;
1980
* This test is performed in NPC space. As a result,
1981
* the sign of the z component of the facet normal
1982
* indicates the direction in which the facet is pointing.
1983
* Therefore if the cullmode is PEXBackFaces and the
1984
* z component is negative, reject the facet. Similarily,
1985
* if the z component of the normal is positive, and
1986
* the cullmode is PEXFrontFaces, also reject the face.
1989
for(i = 0, out_listnum = 1, fct_list->numFacets = 0,
1990
out_vert->numLists = 0,
1991
pddilist = input_vert->ddList, pddolist = out_vert->ddList;
1992
i < input_vert->numLists; i++) {
1994
MI_ALLOCLISTOFDDPOINT(pddolist,(pddilist->numPoints+1),point_size);
1995
if (!pddolist->pts.ptr) return(BadAlloc);
1997
for (j= 2, verts_in_list = 0, new_list = 1,
1998
in_pt.ptr = pddilist->pts.ptr + (2 * point_size),
1999
out_pt.ptr = pddolist->pts.ptr,
2000
pddolist->numPoints = 0;
2001
j < pddilist->numPoints; j++) {
2005
if (pddc->Dynamic->pPCAttr->cullMode == PEXBackFaces) {
2006
if (DD_IsFacetColour(input_fct->type)) {
2007
if (in_fct.pFacetRgbFloatN->normal.z >= 0) accept = 1;
2008
} else if (in_fct.pFacetN->z >= 0) accept = 1;
2009
} else /* pddc->Dynamic->pPCAttr->cullMode == PEXFrontFaces */ {
2010
if (DD_IsFacetColour(input_fct->type)) {
2011
if (in_fct.pFacetRgbFloatN->normal.z < 0) accept = 1;
2012
} else if (in_fct.pFacetN->z < 0) accept = 1;
2017
if (new_list) { /* starting new list after facet(s) culled */
2018
/*initialize first points for the first facet */
2019
memcpy( out_pt.ptr, in_pt.ptr - (2 * point_size), (2*point_size));
2020
out_pt.ptr += 2 * point_size;
2025
/* copy the vertex info associated with this facet */
2026
memcpy( out_pt.ptr, in_pt.ptr, point_size);
2027
out_pt.ptr += point_size;
2030
/* copy the facet info */
2031
if (DD_IsFacetColour(input_fct->type))
2032
*out_fct.pFacetRgbFloatN = *in_fct.pFacetRgbFloatN;
2033
else *out_fct.pFacetN = *in_fct.pFacetN;
2035
/* increment the output pointer */
2036
out_fct.pNoFacet += facet_size;
2037
fct_list->numFacets++;
2040
/* Facet culled; terminate output vertex list */
2041
if (verts_in_list > 2) { /* facets in this list */
2042
pddolist->numPoints = verts_in_list;
2043
++out_vert->numLists;
2045
/* create a new output vertex list; load first points */
2046
MI_ALLOCLISTHEADER(out_vert,
2047
MI_ROUND_LISTHEADERCOUNT(out_listnum))
2048
if (!out_vert->ddList) return(BadAlloc);
2050
pddolist = out_vert->ddList + (out_listnum - 1);
2051
pddolist->numPoints = 0;
2052
MI_ALLOCLISTOFDDPOINT(pddolist,
2053
(pddilist->numPoints - j + 2), point_size);
2054
if (!pddolist->pts.ptr) return(BadAlloc);
2055
out_pt.ptr = pddolist->pts.ptr;
2060
in_pt.ptr += point_size;
2061
in_fct.pNoFacet += facet_size;
2064
if (verts_in_list > 2) {
2065
pddolist->numPoints = verts_in_list;
2067
++out_vert->numLists;
2073
* Only return facet list if one was passed in. Reduces the
2074
* information that must be processed by the rest of the pipeline.
2076
if (return_facet_list) *output_fct = fct_list;
2083
| miDepthCueTriStrip(pddc, input_vert, input_fct, output_vert, output_fct)
2085
| Performs Depth cueing of triangle strips data lists..
2086
| Assigns per-vertex colors to the data list according to the
2087
| "Annex E - Informative" discussion of the ISO PHIGS PLUS spec.
2093
miDepthCueTriStrip(pRend, input_vert, input_fct, output_vert)
2095
ddRendererPtr pRend; /* renderer handle */
2096
miListHeader *input_vert; /* input vertex data */
2097
listofddFacet *input_fct; /* input facet data */
2098
miListHeader **output_vert; /* output vertex data */
2100
miDDContext *pddc = (miDDContext *)(pRend->pDDContext);
2101
miListHeader *out_vert;
2102
listofddFacet *fct_list;
2104
listofddPoint *pddilist;
2105
listofddPoint *pddolist;
2106
ddPointUnion in_pt, out_pt;
2107
ddRgbFloatColour *in_color;
2108
ddFacetUnion in_fct;
2109
int inpoint_size, outpoint_size;
2114
ddDepthCueEntry *dcue_entry;
2116
/* look for empty list header */
2117
if (input_vert->numLists == 0) return(Success);
2119
/* validate CC version of Depth Cue information */
2120
if (pddc->Static.misc.flags & CC_DCUEVERSION)
2121
Compute_CC_Dcue(pRend, pddc);
2123
/* check to make sure depth cuing is enabled */
2124
if (pddc->Static.misc.cc_dcue_entry.mode == PEXOff) {
2125
*output_vert = input_vert;
2129
/* Else, depth cue! Use one of the pre-defined 4D list for output */
2130
*output_vert = out_vert = MI_NEXTTEMPDATALIST(pddc);
2132
/* Insure sufficient room for each header */
2133
MI_ALLOCLISTHEADER(out_vert,
2134
MI_ROUND_LISTHEADERCOUNT(input_vert->numLists))
2135
if (!out_vert->ddList) return(BadAlloc);
2137
out_vert->type = input_vert->type;
2138
if (!(DD_IsVertColour(input_vert->type)))
2139
DD_SetVertRGBFLOAT(out_vert->type);
2140
out_vert->numLists = input_vert->numLists;
2141
out_vert->flags = input_vert->flags;
2143
pddilist = input_vert->ddList;
2144
pddolist = out_vert->ddList;
2146
DD_VertPointSize(input_vert->type, inpoint_size);
2147
DD_VertPointSize(out_vert->type, outpoint_size);
2149
if ((input_fct) && (input_fct->numFacets > 0)) {
2150
in_fct = input_fct->facets;
2151
DDFacetSIZE(input_fct->type, facet_size);
2152
} else in_fct.pNoFacet = 0;
2154
for(i = 0; i < input_vert->numLists; i++) {
2155
pddolist->numPoints = pddilist->numPoints;
2156
in_pt.ptr = pddilist->pts.ptr;
2157
MI_ALLOCLISTOFDDPOINT(pddolist,(pddilist->numPoints+1),
2159
if (!(out_pt.ptr = pddolist->pts.ptr)) return(BadAlloc);
2161
for (j = 0, in_pt.ptr = pddilist->pts.ptr,
2162
out_pt.ptr = pddolist->pts.ptr;
2163
j < pddilist->numPoints; j++) {
2165
/* First copy over coordinate data */
2166
pt_depth = in_pt.p4Dpt->z;
2167
*out_pt.p4Dpt = *in_pt.p4Dpt;
2173
* Colour is derived first from the vertex, second from the
2174
* facet, and third from the current PC attributes.
2176
if (DD_IsVertColour(input_vert->type)){
2177
in_color = in_pt.pRgbFloatClr;
2178
in_pt.pRgbFloatClr++;
2181
if ((in_fct.pNoFacet) && (DD_IsFacetColour(input_fct->type)))
2182
in_color = in_fct.pFacetRgbFloat;
2185
&(pddc->Static.attrs->surfaceColour.colour.rgbFloat);
2189
APPLY_DEPTH_CUEING(pddc->Static.misc.cc_dcue_entry,
2190
pt_depth, in_color, out_pt.pRgbFloatClr)
2192
out_pt.pRgbFloatClr++;
2196
* Normals are derived first from the vertex, second from the
2197
* facet (note that we insured above that there were facet normals).
2199
if DD_IsVertNormal(input_vert->type) {
2200
*out_pt.pNormal = *in_pt.pNormal;
2205
/* Next pass along edge info if there is any */
2206
if (DD_IsVertEdge(out_vert->type)) {
2207
*out_pt.pEdge = *in_pt.pEdge;
2213
if ((in_fct.pNoFacet)) in_fct.pNoFacet += facet_size;