~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/PEX5/ddpex/mi/level2/miTriStrip.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Xorg: miTriStrip.c,v 1.4 2001/02/09 02:04:11 xorgcvs Exp $ */
 
2
/*
 
3
 
 
4
Copyright 1989, 1990, 1991, 1998  The Open Group
 
5
 
 
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
 
10
documentation.
 
11
 
 
12
The above copyright notice and this permission notice shall be included
 
13
in all copies or substantial portions of the Software.
 
14
 
 
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.
 
22
 
 
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
 
26
from The Open Group.
 
27
 
 
28
 
 
29
Copyright 1989, 1990, 1991 by Sun Microsystems, Inc. 
 
30
All Rights Reserved
 
31
 
 
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.
 
39
 
 
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
 
46
SOFTWARE.
 
47
 
 
48
*/
 
49
/* $XFree86: xc/programs/Xserver/PEX5/ddpex/mi/level2/miTriStrip.c,v 3.7 2001/12/14 19:57:30 dawes Exp $ */
 
50
 
 
51
#include "miClip.h"
 
52
#include "misc.h"
 
53
#include "miscstruct.h"
 
54
#include "ddpex3.h"
 
55
#include "PEXErr.h"
 
56
#include "miStruct.h"
 
57
#include "PEXprotost.h"
 
58
#include "miRender.h"
 
59
#include "gcstruct.h"
 
60
#include "miLight.h"
 
61
#include "ddpex2.h"
 
62
#include "pexos.h"
 
63
 
 
64
 
 
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();
 
72
 
 
73
/*++
 
74
 |
 
75
 |  Function Name:      miTriangleStrip
 
76
 |
 
77
 |  Function Description:
 
78
 |       Handles the triangle strip OC.
 
79
 |
 
80
 |  Note(s):
 
81
 |
 
82
 --*/
 
83
 
 
84
ddpex3rtn
 
85
miTriangleStrip(pRend, pExecuteOC)
 
86
/* in */
 
87
    ddRendererPtr       pRend;    /* renderer handle */
 
88
    miGenericStr       *pExecuteOC;
 
89
{
 
90
 
 
91
/* calls */
 
92
      ddpex3rtn         miTransform();
 
93
      ddpex3rtn         miConvertVertexColors();
 
94
      ddpex3rtn         miConvertFacetColors();
 
95
      ddpex3rtn         miLightTriStrip();
 
96
      ddpex3rtn         miRenderTriStrip();
 
97
      ddpex3rtn         ComputeMCVolume();
 
98
 
 
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,
 
106
                        *mc_list,
 
107
                        *wc_list,
 
108
                        *mc_clist,
 
109
                        *light_list,
 
110
                        *cc_list,
 
111
                        *clip_list,
 
112
                        *cull_list,
 
113
                        *dcue_list,
 
114
                        *dc_list;
 
115
 
 
116
      listofddFacet     *color_facet,
 
117
                        *mc_facet,
 
118
                        *wc_facet,
 
119
                        *light_facet,
 
120
                        *cc_facet,
 
121
                        *clip_facet,
 
122
                        *cull_facet,
 
123
                        *dc_facet;
 
124
      listofddPoint     *sp;
 
125
      int               i, j;
 
126
      ddpex3rtn         status;
 
127
      ddPointType       out_type;
 
128
      ddUSHORT          clip_mode;      
 
129
 
 
130
   
 
131
      /* 
 
132
       * First, check data input
 
133
       * At this point, the data is all in one list
 
134
       */
 
135
 
 
136
      if (input_list->numLists == 0) return(Success);
 
137
 
 
138
      /*
 
139
       * Convert per-vertex and per-facet colors to rendering color model.
 
140
       * Note that this implementation only supports rgb float.
 
141
       */
 
142
 
 
143
      if (DD_IsVertColour(input_list->type)) {
 
144
        if (status = miConvertVertexColors(pRend, 
 
145
                                           input_list, PEXRdrColourModelRGB, 
 
146
                                           &color_list))
 
147
          return (status);
 
148
      } else {
 
149
        color_list = input_list;
 
150
      } 
 
151
 
 
152
      if ((input_facet) && (DD_IsFacetColour(input_facet->type))) {
 
153
        if (status = miConvertFacetColors(pRend, 
 
154
                                          input_facet, PEXRdrColourModelRGB, 
 
155
                                          &color_facet))
 
156
          return (status);
 
157
      } else {
 
158
        color_facet = input_facet;
 
159
      } 
 
160
 
 
161
      /* Check for Model clipping */
 
162
 
 
163
      if (pddc->Dynamic->pPCAttr->modelClip == PEXClip) {
 
164
 
 
165
        /* Compute  modelling coord version of clipping volume */ 
 
166
        ComputeMCVolume(pRend, pddc);
 
167
                                   
 
168
        clip_mode = MI_MCLIP;   
 
169
 
 
170
        /* Tranform points to 4D for clipping */
 
171
        out_type = color_list->type;
 
172
        if (status = miTransform(pddc,
 
173
                                 color_list, &mc_clist,
 
174
                                 ident4x4,
 
175
                                 ident4x4,
 
176
                                 DD_SetVert4D(out_type)))
 
177
          return (status);
 
178
 
 
179
 
 
180
        if (status = miClipTriStrip(pddc, mc_clist, color_facet, 
 
181
                                    &mc_list, &mc_facet, clip_mode))
 
182
            return (status);
 
183
 
 
184
      /* if nothing left after model clip, return early */
 
185
      if (mc_list->numLists <= 0) return(Success);
 
186
 
 
187
      } else {
 
188
        mc_list = color_list;
 
189
        mc_facet = color_facet;
 
190
      }
 
191
 
 
192
      /* Note - After clipping the triangle strip may have
 
193
       * decomposed into a number of separate triangle strips
 
194
       */
 
195
        
 
196
 
 
197
      /* 
 
198
       * Next, check lighting requirements
 
199
       */
 
200
 
 
201
      if (pddc->Static.attrs->reflModel != PEXReflectionNoShading) {
 
202
        
 
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,
 
207
                                 mc_list, &wc_list,
 
208
                                 pddc->Dynamic->mc_to_wc_xform,
 
209
                                 pddc->Static.misc.inv_tr_mc_to_wc_xform,
 
210
                                 DD_SetVert4D(out_type)))
 
211
          return (status);
 
212
 
 
213
        /* Transform facet normals if necessary */
 
214
        if ((mc_facet) &&
 
215
            (mc_facet->numFacets > 0) &&
 
216
            (DD_IsFacetNormal(mc_facet->type))) {
 
217
          VALIDATEINVTRMCTOWCXFRM(pddc);
 
218
          if (status = miFacetTransform(pddc,
 
219
                                       mc_facet, &wc_facet,
 
220
                                       pddc->Static.misc.inv_tr_mc_to_wc_xform))
 
221
            return (status);
 
222
        } else wc_facet = mc_facet;
 
223
 
 
224
        /* Apply lighting */
 
225
        if (status = miLightTriStrip(pRend, pddc,
 
226
                                     wc_list, wc_facet,
 
227
                                     &light_list, &light_facet))
 
228
          return (status);
 
229
 
 
230
 
 
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,
 
237
                                 light_list->type))
 
238
          return (status);
 
239
 
 
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))
 
248
            return (status);
 
249
        } else cc_facet = light_facet;
 
250
 
 
251
      } else {
 
252
 
 
253
        /* PEXReflectionNoShading case */
 
254
 
 
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,
 
259
                                 mc_list, &cc_list,
 
260
                                 pddc->Dynamic->mc_to_cc_xform,
 
261
                                 pddc->Static.misc.inv_tr_mc_to_cc_xform,
 
262
                                 DD_SetVert4D(out_type)))
 
263
          return (status);
 
264
 
 
265
        if ( (mc_facet) &&
 
266
             (mc_facet->numFacets > 0) &&
 
267
             (DD_IsFacetNormal(mc_facet->type)) ) {
 
268
          VALIDATEINVTRMCTOCCXFRM(pddc);
 
269
          if (status = miFacetTransform(pddc,
 
270
                                      mc_facet, &cc_facet,
 
271
                                      pddc->Static.misc.inv_tr_mc_to_cc_xform))
 
272
          return (status);
 
273
        } else cc_facet = mc_facet;
 
274
 
 
275
      }
 
276
 
 
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))
 
281
        return (status);
 
282
 
 
283
      /* if nothing left after view clip, return early */
 
284
      if (clip_list->numLists <= 0) return(Success);
 
285
 
 
286
      /* Note - After View clipping, the triangle strip may have
 
287
       * decomposed into a number of separate triangle strips
 
288
       */
 
289
 
 
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))
 
294
          return (status);
 
295
 
 
296
      /* if nothing left after culling, return early */
 
297
      if (cull_list->numLists <= 0) return(Success);
 
298
      } else {
 
299
        cull_list = clip_list;
 
300
        cull_facet = clip_facet;
 
301
      }
 
302
 
 
303
      /* DEPTH CUEING */
 
304
      if (pddc->Dynamic->pPCAttr->depthCueIndex) {
 
305
        miDepthCueTriStrip(pRend, cull_list, cull_facet, &dcue_list);
 
306
        cull_list = dcue_list;
 
307
      }
 
308
 
 
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,
 
315
                               cull_list, &dc_list,
 
316
                               pddc->Dynamic->cc_to_dc_xform,
 
317
                               pddc->Static.misc.inv_tr_cc_to_dc_xform,
 
318
                               out_type) )
 
319
          return (status);
 
320
 
 
321
      /* Transform facet normals if necessary */
 
322
      if ( (cull_facet) &&
 
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))
 
329
            return (status);
 
330
      } else dc_facet = cull_facet;
 
331
 
 
332
    return (pddc->Static.RenderProcs[TRISTRIP_RENDER_TABLE_INDEX](pRend,
 
333
                                                                  pddc,
 
334
                                                                  dc_list,
 
335
                                                                  dc_facet));
 
336
}
 
337
/*************************************************************************/
 
338
 
 
339
/*++
 
340
 |
 
341
 |  Function Name:      miClipTriStrip
 
342
 |
 
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.
 
350
 |
 
351
 |  Note(s):
 
352
 |
 
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) 
 
357
 |       clipping boundary. 
 
358
 |
 
359
 --*/
 
360
 
 
361
static
 
362
ddpex3rtn
 
363
miClipTriStrip(pddc, input_vert, input_fct, output_vert, output_fct,clip_mode)
 
364
/* in */
 
365
        miDDContext     *pddc;
 
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 */
 
370
        ddUSHORT        clip_mode;
 
371
{
 
372
/* uses */
 
373
    ddPointUnion        in_ptP, in_ptQ, in_ptR;
 
374
    ddPointUnion        out_pt;
 
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;
 
381
    int                 point_size;
 
382
    int                 facet_size;
 
383
    int                 pts_in_list;
 
384
    int                 vert_count;
 
385
    int                 new_facets;
 
386
    int                 clip_plane, j, k, out_listnum;
 
387
    ddUSHORT            clipflags;
 
388
    ddUSHORT            current_clip;
 
389
    int                 edge_offset;
 
390
    ddHalfSpace         *MC_HSpace;
 
391
    ddVector3D          PdotN, QdotN;
 
392
    int                 clip_code;
 
393
    ddULONG             *edge_ptr;
 
394
    char                new_list;
 
395
    ddpex3rtn           status;
 
396
    int                 num_planes;
 
397
 
 
398
    /* Vertex data must be homogeneous and contain more than two points
 
399
     *  for clipper 
 
400
     */
 
401
    if (!(DD_IsVert4D(input_vert->type)) 
 
402
        || (input_vert->numLists == 0)) return(1);
 
403
 
 
404
    /* 
 
405
     * Use the pre-defined clip lists for output 
 
406
     */
 
407
 
 
408
    /* 
 
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. 
 
412
     */
 
413
    if ((pddc->Static.attrs->edges != PEXOff) &&
 
414
        (!(DD_IsVertEdge(input_vert->type))))
 
415
    {
 
416
      if (status = miAddEdgeFlag(pddc, input_vert, &list1)) return(status);
 
417
      vinput = list1;
 
418
 
 
419
    } else {
 
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 */
 
428
    }
 
429
 
 
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;
 
436
    voutput = list2;
 
437
 
 
438
    /*
 
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".
 
443
     */
 
444
    if ((input_fct) && (input_fct->numFacets)) {
 
445
      finput = input_fct;
 
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) 
 
451
        return(BadAlloc);
 
452
      foutput = fct_list1;
 
453
 
 
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) 
 
458
        return(BadAlloc);
 
459
    } else 
 
460
      finput = foutput = fct_list1 = fct_list2 = 0;
 
461
 
 
462
    /* 
 
463
     * Get point size so that this works for all point types 
 
464
     */
 
465
    DD_VertPointSize(vinput->type, point_size);
 
466
    if DD_IsVertEdge(vinput->type)
 
467
                DD_VertOffsetEdge(vinput->type, edge_offset);
 
468
 
 
469
    /* 
 
470
     * Each list is now clipped in turn against each (enabled) boundary.
 
471
     */
 
472
 
 
473
    if (clip_mode == MI_MCLIP) 
 
474
                num_planes = pddc->Static.misc.ms_MCV->numObj;
 
475
    else num_planes = 6;
 
476
 
 
477
    if (clip_mode == MI_MCLIP) 
 
478
        MC_HSpace = (ddHalfSpace *)(pddc->Static.misc.ms_MCV->pList);
 
479
 
 
480
    for (clip_plane = 0; clip_plane < num_planes; clip_plane++) {
 
481
 
 
482
      /* do entire list against one clipping plane at a time */
 
483
      current_clip = 1 << clip_plane;  /* current_clip is new clip bound */
 
484
 
 
485
        /*
 
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.
 
495
         */
 
496
 
 
497
        if (finput) {
 
498
          in_fct = (char *)(finput->facets.pNoFacet);
 
499
          MI_ALLOCLISTOFDDFACET(foutput, 
 
500
                        (3*finput->numFacets), facet_size);
 
501
          out_fct = (char *)(foutput->facets.pNoFacet); 
 
502
        }
 
503
 
 
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++) {
 
508
 
 
509
 
 
510
          /* Don't process if not enough points */
 
511
          if ((vert_count = pddilist->numPoints) < 3) {
 
512
            pddilist++;
 
513
            continue;
 
514
          }
 
515
 
 
516
 
 
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").
 
520
           */
 
521
          
 
522
          MI_ALLOCLISTOFDDPOINT(pddolist, 2*vert_count, point_size);
 
523
          out_pt = pddolist->pts;
 
524
          if (!out_pt.ptr) return(BadAlloc);
 
525
 
 
526
          clip_code = 0;                
 
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;
 
536
          /* 
 
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.
 
540
           */
 
541
          switch(clip_code)
 
542
           {
 
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;
 
548
                pts_in_list = 2;
 
549
                break;
 
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;
 
556
                pts_in_list = 2;
 
557
                break;
 
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;
 
564
                pts_in_list = 2;
 
565
                break;
 
566
              case 3:                   /* both are out */
 
567
                pts_in_list = 0;
 
568
                break;
 
569
           }
 
570
          
 
571
          /* 
 
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 
 
579
           * statement. 
 
580
           *
 
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
 
586
           * new list.
 
587
           *
 
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.
 
595
           *
 
596
           *         2_________ _4
 
597
           *         /\         /|\
 
598
           *        /  \       /   \
 
599
           *       /    \     /     \
 
600
           *      /      \   /       \
 
601
           *    1<--------+3+---------5
 
602
           *
 
603
           * So, for the third element in the edge list,
 
604
           * bit 0 indicates presence of an edge from 3 -> 4
 
605
           *    (forward edge)
 
606
           * bit 1 indicates presence of an edge from 3 -> 1  
 
607
           *    (backward edge)
 
608
           *
 
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
 
614
           * edge flag field.
 
615
           */
 
616
 
 
617
          for (k = 2; k < vert_count; k++) {
 
618
            /* 
 
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:
 
622
             *
 
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
 
626
             *  R in P, Q out
 
627
             *
 
628
             * Each of these cases are handled separately.  
 
629
             */
 
630
 
 
631
            new_list = 0;
 
632
            COMPUTE_CLIP_PARAMS(in_ptR, t_ptR, 2, clip_mode,
 
633
                        current_clip,MC_HSpace,clip_code);
 
634
 
 
635
            switch(clip_code)
 
636
             {
 
637
              /* 
 
638
               * Case 0 - trivial accept P, Q, and R
 
639
               * Proceed to next triangle.
 
640
               */
 
641
              case 0:
 
642
                COPY_POINT(in_ptR, out_pt, point_size);
 
643
                out_pt.ptr += point_size;
 
644
                pts_in_list++;
 
645
                if (finput) {
 
646
                  COPY_FACET(in_fct, out_fct, facet_size);
 
647
                  out_fct += facet_size;
 
648
                  ++new_facets;
 
649
                }
 
650
                break;
 
651
 
 
652
              /* 
 
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 
 
658
               *
 
659
               *       |Q+                    |Q+             
 
660
               *       | /\                   | /\            
 
661
               *       |/  \                  |/  \           
 
662
               *       |    \     ===>       A+    \     
 
663
               *      /|     \                |     \         
 
664
               *    P+-|------+R             B+------+R       
 
665
               *       |                      |
 
666
               *      triangle PQR        triangles AQB, QBQ(degenerate)
 
667
               *                                                & BQR
 
668
               *
 
669
               */
 
670
              case 1:
 
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 
 
677
                                         */
 
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;
 
683
                }
 
684
 
 
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 */
 
693
                }
 
694
                out_pt.ptr += point_size;
 
695
 
 
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;
 
700
 
 
701
                COPY_POINT(in_ptR, out_pt, point_size);
 
702
                out_pt.ptr += point_size;
 
703
                pts_in_list += 3;
 
704
 
 
705
                if (finput) {
 
706
                  /* 
 
707
                   * Add three identical facets 
 
708
                   */ 
 
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;
 
715
                  new_facets += 3;
 
716
                }
 
717
                break;
 
718
 
 
719
              /* 
 
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 
 
723
               * A to R
 
724
               *             
 
725
               *        Q+                 
 
726
               *         /\                    A  B
 
727
               *     ----------             ---+--+---        
 
728
               *       /    \     ===>        /    \
 
729
               *      /      \               /      \         
 
730
               *    P+--------+R           P+--------+R       
 
731
               *             
 
732
               *      triangle PQR        triangles PAR, ARB, RBR
 
733
               *             
 
734
               */
 
735
              case 2:
 
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;
 
741
                }
 
742
 
 
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;
 
749
 
 
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;
 
757
        
 
758
                COPY_POINT(in_ptR, out_pt, point_size); /* degenerate point */
 
759
                out_pt.ptr += point_size;
 
760
                pts_in_list += 3;
 
761
 
 
762
                if (finput) {
 
763
                  /* 
 
764
                   * Add three identical facets
 
765
                   */ 
 
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;
 
772
                  new_facets += 3;
 
773
                }
 
774
                break;
 
775
 
 
776
              /* 
 
777
               * Case 3 - P and Q outside, R inside.
 
778
               * Note - this is the first triangle in a new list
 
779
               * 
 
780
               * Output list is A-B-R. If beginning on odd facet
 
781
               * output list is B-A-B-R
 
782
               *
 
783
               * 
 
784
               *        Q+  |                      |          
 
785
               *         /\ |                      |          
 
786
               *        /  \|                      |          
 
787
               *       /    |     ===>            B+     
 
788
               *      /     |\                     |\         
 
789
               *    P+------|-+R                  A+-+R       
 
790
               *            |                      |         
 
791
               *      triangle PQR        triangle ABR or BABR
 
792
               *
 
793
               *
 
794
               */
 
795
              case 3:
 
796
                /*
 
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. 
 
803
                 */
 
804
 
 
805
                if(IS_ODD(k)) {
 
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;
 
810
                  pts_in_list++;
 
811
                  if (finput) {
 
812
                    COPY_FACET(in_fct, out_fct, facet_size);
 
813
                    out_fct += facet_size;
 
814
                    ++new_facets;
 
815
                  }
 
816
                }
 
817
 
 
818
                CLIP_AND_COPY(vinput->type, in_ptP, t_ptP, 
 
819
                                in_ptR, t_ptR, out_pt);
 
820
                                        /*Places point "A" into output list */
 
821
 
 
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;
 
826
 
 
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;
 
831
 
 
832
 
 
833
                COPY_POINT(in_ptR, out_pt, point_size);
 
834
                                        /*Places point "R" into output list */
 
835
                out_pt.ptr += point_size;
 
836
 
 
837
                if (finput) {
 
838
                  COPY_FACET(in_fct, out_fct, facet_size);
 
839
                  out_fct += facet_size;
 
840
                  ++new_facets;
 
841
                }
 
842
                pts_in_list += 3;
 
843
                break;
 
844
 
 
845
              /* 
 
846
               * Case 4 - P and Q inside, R outside
 
847
               * Output list is P-Q-B-Q-A
 
848
               *
 
849
               *        Q+  |                  Q+  |          
 
850
               *         /\ |                   /\ |          
 
851
               *        /  \|                  /  \|          
 
852
               *       /    |     ===>        /    +A     
 
853
               *      /     |\               /     |
 
854
               *    P+------|-+R           P+------+B
 
855
               *            |                      |
 
856
               *             
 
857
               *    triangle PQR          triangles PQB, BQB, BQA
 
858
               *             
 
859
               */
 
860
              case 4:
 
861
 
 
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;
 
867
                }
 
868
 
 
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;
 
876
 
 
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;
 
883
 
 
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;
 
891
                pts_in_list += 3;
 
892
 
 
893
                if (finput) {
 
894
                  /* 
 
895
                   * Add three identical facets
 
896
                   */ 
 
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;
 
903
                  new_facets += 3;
 
904
                }
 
905
                break;
 
906
 
 
907
              /* 
 
908
               * Case 5 - P and R are outside, Q in inside.
 
909
               * Output list is A-Q-B. A and Q already in list
 
910
               *
 
911
               *        Q+                      Q+
 
912
               *         /\                     /\ 
 
913
               *     ----------             ---+--+---        
 
914
               *       /    \     ===>        A    B
 
915
               *      /      \         
 
916
               *    P+--------+R      
 
917
               *             
 
918
               *      triangle PQR        triangles AQB
 
919
               *             
 
920
               */
 
921
              case 5:
 
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;
 
929
                pts_in_list++;
 
930
 
 
931
                if (finput) {
 
932
                  COPY_FACET(in_fct, out_fct, facet_size);
 
933
                  out_fct += facet_size;
 
934
                  ++new_facets;
 
935
                }
 
936
                break;
 
937
 
 
938
              /* 
 
939
               * Case 6 - P is inside, R and Q are outside
 
940
               * Output list is: P-A-B
 
941
               *             
 
942
               *       |Q+                    |
 
943
               *       | /\                   |
 
944
               *       |/  \                  |
 
945
               *       |    \     ===>        +A
 
946
               *      /|     \               /|
 
947
               *    P+-|------+R           P+-+B
 
948
               *       |                      |
 
949
               *      triangle PQR        triangles 
 
950
               *
 
951
               */
 
952
              case 6:
 
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;
 
957
                }
 
958
 
 
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;
 
963
                pts_in_list += 1;
 
964
 
 
965
                if (finput) {
 
966
                  COPY_FACET(in_fct, out_fct, facet_size);
 
967
                  out_fct += facet_size;
 
968
                  ++new_facets;
 
969
                }
 
970
                break;
 
971
 
 
972
              /* 
 
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 
 
977
               *
 
978
               *        Q+             
 
979
               *         /\            
 
980
               *        /  \           
 
981
               *       /    \     ===> 
 
982
               *      /      \        
 
983
               *    P+--------+R      
 
984
               *                      
 
985
               */
 
986
              case 7:
 
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;
 
991
                  voutput->numLists++;
 
992
                  out_listnum++;
 
993
                  MI_ALLOCLISTHEADER(voutput, 
 
994
                        MI_ROUND_LISTHEADERCOUNT(voutput->numLists));
 
995
                  /* skip to next output list */
 
996
                  pddolist = voutput->ddList + out_listnum;
 
997
 
 
998
                  /* Insure sufficient room for remaining verts 
 
999
                        and degenerate points */
 
1000
                  MI_ALLOCLISTOFDDPOINT(pddolist, 
 
1001
                                2*(vert_count - k), point_size);
 
1002
 
 
1003
                  out_pt.ptr = pddolist->pts.ptr;
 
1004
                  if (!out_pt.ptr) return(BadAlloc);
 
1005
                }
 
1006
 
 
1007
                else {
 
1008
                  /* Not enough points for output list */
 
1009
                  pddolist->numPoints = 0;
 
1010
                }
 
1011
 
 
1012
                /* Look for next point inside bounds */
 
1013
                do {
 
1014
                  clip_code = 0;
 
1015
                  in_ptR.ptr += point_size;
 
1016
                  if (finput) in_fct += facet_size;
 
1017
                  k++;
 
1018
                  if (k == vert_count)
 
1019
                    break;
 
1020
                  COMPUTE_CLIP_PARAMS(in_ptR, t_ptR, 2, clip_mode,
 
1021
                        current_clip,MC_HSpace,clip_code);
 
1022
                } while(clip_code);
 
1023
                if (k < vert_count) {
 
1024
                  /*
 
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.
 
1029
                   *
 
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
 
1033
                   * for loop.
 
1034
                   */
 
1035
                  k--;
 
1036
 
 
1037
                  /* Get P & Q; re-enter loop. 
 
1038
                   * Next case encountered will be 3, which will
 
1039
                   * handle the odd-even rule for normals.
 
1040
                   */
 
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);
 
1048
                } 
 
1049
                new_list = 1;
 
1050
                pts_in_list = 0; /*start a new list*/
 
1051
                break;
 
1052
 
 
1053
             } /* end of cases */
 
1054
 
 
1055
              if (!new_list) {
 
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;
 
1061
                clip_code >>= 1;
 
1062
              }
 
1063
 
 
1064
          } /* end of single list processing */
 
1065
 
 
1066
          if (pts_in_list > 2) {        /* Got some points! */
 
1067
            /* skip to next list, increment list count. */
 
1068
            pddolist->numPoints = pts_in_list;
 
1069
            ++pddolist;
 
1070
            ++out_listnum;
 
1071
            ++voutput->numLists;
 
1072
          }
 
1073
          else pddolist->numPoints = 0;         /* use same list */
 
1074
 
 
1075
          pddilist++;
 
1076
        } /* end of list of lists processing */
 
1077
 
 
1078
        if (foutput) foutput->numFacets = new_facets;
 
1079
 
 
1080
      if (out_listnum > 0) {
 
1081
        /* Use result of previous clip for input to next clip */
 
1082
        vinput = voutput;
 
1083
        if (voutput == list2) voutput = list1;  /* ping-pong */
 
1084
        else voutput = list2;
 
1085
 
 
1086
        if (finput) {
 
1087
          /* Use result of previous clip for input to next clip */
 
1088
          finput = foutput;
 
1089
          if (foutput == fct_list2) foutput = fct_list1;
 
1090
          else foutput = fct_list2;
 
1091
        }
 
1092
      } else {
 
1093
        /* If no lists, exit loop */
 
1094
        vinput = voutput;
 
1095
        finput = foutput;
 
1096
      }
 
1097
      if (clip_mode == MI_MCLIP) MC_HSpace++;
 
1098
 
 
1099
    } /* end of processing for all clip planes */
 
1100
 
 
1101
 
 
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;
 
1106
 
 
1107
 
 
1108
    return (Success);
 
1109
 
 
1110
}
 
1111
 
 
1112
 
 
1113
 
 
1114
/*++
 
1115
 |
 
1116
 |  miLightTriStrip
 
1117
 |
 
1118
 |      Perform lighting calculations for the vertex or facet
 
1119
 |      data provided according to the current attributes.
 
1120
 |
 
1121
 --*/
 
1122
 
 
1123
ddpex3rtn
 
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 */
 
1131
{
 
1132
/* calls */
 
1133
    ddpex3rtn           miApply_Lighting();
 
1134
    ddpex3rtn           miFilterPath();
 
1135
 
 
1136
/* uses */
 
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;
 
1148
    ddpex3rtn                   status;
 
1149
 
 
1150
 
 
1151
    /* Look for empty fill style.  Still might have to render edges. */
 
1152
    if (pddc->Static.attrs->intStyle == PEXInteriorStyleEmpty)
 
1153
        return(Success);
 
1154
 
 
1155
    /*
 
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).
 
1165
     */
 
1166
 
 
1167
    DD_VertPointSize(input_vert->type, inpoint_size);
 
1168
    switch(pddc->Static.attrs->surfInterp) {
 
1169
 
 
1170
      case PEXSurfaceInterpNone: /* Flat shading */
 
1171
 
 
1172
          if ((!input_fct) || 
 
1173
              (input_fct->numFacets == 0) ||
 
1174
              (!( (DD_IsFacetColour(input_fct->type)) && 
 
1175
                (DD_IsFacetNormal(input_fct->type))))) {
 
1176
 
 
1177
            Complete_TriFacetList(pRend, input_vert, input_fct,
 
1178
                                          output_fct);
 
1179
 
 
1180
            input_fct = *output_fct;
 
1181
          }
 
1182
 
 
1183
          /* 
 
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.
 
1189
           */
 
1190
          if ( (DD_IsVertNormal(input_vert->type)) ||
 
1191
               (DD_IsVertColour(input_vert->type)) ) {
 
1192
            if (status = miFilterPath(pddc, input_vert, output_vert, 
 
1193
                                      ((1 << 3) | 1) ))
 
1194
              return(status);
 
1195
          } else {
 
1196
            *output_vert = input_vert;
 
1197
          }
 
1198
 
 
1199
          /*
 
1200
           * Now allocate storage for the output facet list
 
1201
           * Note that the output facet list only contains colors.
 
1202
           */
 
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++) {
 
1213
 
 
1214
            /*
 
1215
             * Compute lighted facet color for each facet.
 
1216
             * Facet color is simply the sum of the lighting contributions
 
1217
             * from each light source.
 
1218
             */
 
1219
            for (k = 2; k < pddilist->numPoints; k++) {
 
1220
 
 
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 */
 
1226
 
 
1227
              if (status = miApply_Lighting(pRend, pddc,
 
1228
                                          in_pt.p4Dpt,
 
1229
                                          &(in_fct->colour),
 
1230
                                          &(in_fct->normal),
 
1231
                                          out_fct ))
 
1232
                return(status);
 
1233
 
 
1234
                in_pt.ptr += inpoint_size;
 
1235
                in_fct++;
 
1236
                out_fct++;
 
1237
            }
 
1238
            /* skip to next input vertex list */
 
1239
            pddilist++;
 
1240
          }
 
1241
        break;
 
1242
 
 
1243
      case PEXSurfaceInterpColour:
 
1244
      case PEXSurfaceInterpDotProduct:
 
1245
      case PEXSurfaceInterpNormal:
 
1246
 
 
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
 
1255
           * position */
 
1256
        
 
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;
 
1261
        }
 
1262
 
 
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,
 
1267
                                                     input_fct,
 
1268
                                                     output_vert);
 
1269
          input_vert = *output_vert;
 
1270
        }
 
1271
 
 
1272
        /* From here facet data only used in culling operation */
 
1273
        *output_fct = input_fct;
 
1274
 
 
1275
        /* Use one of the pre-defined 4D list for output */
 
1276
        *output_vert = out_vert = MI_NEXTTEMPDATALIST(pddc);
 
1277
 
 
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);
 
1282
 
 
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);
 
1287
        }
 
1288
        out_vert->numLists = input_vert->numLists;
 
1289
        out_vert->flags =  input_vert->flags;
 
1290
 
 
1291
        DD_VertPointSize(out_vert->type, outpoint_size);
 
1292
        pddilist = input_vert->ddList;
 
1293
        pddolist = out_vert->ddList;
 
1294
 
 
1295
        for(i = 0; i < input_vert->numLists; i++) {
 
1296
 
 
1297
          pddolist->numPoints = pddilist->numPoints;
 
1298
          MI_ALLOCLISTOFDDPOINT(pddolist, pddolist->numPoints,
 
1299
                                  outpoint_size);
 
1300
          if (!(out_pt.ptr = pddolist->pts.ptr)) return(BadAlloc);
 
1301
 
 
1302
          for (j = 0, in_pt.ptr = pddilist->pts.ptr;
 
1303
                 j < pddilist->numPoints; j++) {
 
1304
 
 
1305
            /* Copy over the coordinate info */
 
1306
            *out_pt.p4Dpt = *in_pt.p4Dpt;
 
1307
 
 
1308
            /* move output pointer to colour field */
 
1309
            out_pt.p4Dpt++;
 
1310
 
 
1311
            /* miApplyLighting works on a single point at a time */
 
1312
            if (status = miApply_Lighting(pRend, pddc,
 
1313
                                            in_pt.p4Dpt,
 
1314
                                            &(in_pt.pRgbFloatNpt4D->colour),
 
1315
                                            &(in_pt.pRgbFloatNpt4D->normal),
 
1316
                                            out_pt.pRgbFloatClr))
 
1317
                        return(status);
 
1318
 
 
1319
            /* increment pointers */ 
 
1320
            in_pt.pRgbFloatNpt4D++;
 
1321
            out_pt.pRgbFloatClr++;
 
1322
 
 
1323
            if (DD_IsVertEdge(out_vert->type)) {
 
1324
              *out_pt.pEdge = *in_pt.pEdge;
 
1325
              out_pt.pEdge++;
 
1326
              in_pt.pEdge++;
 
1327
            }
 
1328
 
 
1329
 
 
1330
          }
 
1331
          /* skip to next input and output vertex list */
 
1332
          pddilist++;
 
1333
          pddolist++;
 
1334
        }
 
1335
 
 
1336
        break;
 
1337
 
 
1338
      default:
 
1339
        *output_vert = input_vert;
 
1340
        *output_fct = input_fct;
 
1341
 
 
1342
    }
 
1343
 
 
1344
    return(Success);
 
1345
}
 
1346
 
 
1347
/*++
 
1348
 |
 
1349
 |  Complete_TriFacetList(pRend, input_vert, output_fct)
 
1350
 |
 
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.
 
1356
 |
 
1357
 --*/
 
1358
/* calls */
 
1359
 
 
1360
static
 
1361
ddpex3rtn
 
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 */
 
1367
{
 
1368
/* local */
 
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;
 
1375
    int                 point_size;
 
1376
    ddRgbFloatPoint4D   *vert1, *vert2, *vert3;
 
1377
    int                 total_facets;
 
1378
    int                 i,j;
 
1379
    float               length;
 
1380
    ddpex3rtn           status;
 
1381
    char                have_colors, have_normals;
 
1382
 
 
1383
    have_colors = have_normals = 0;
 
1384
 
 
1385
    /* What data must be added to output facet list ? */
 
1386
    if (!(input_fct) || (input_fct->type == DD_FACET_NONE)) {
 
1387
      /*
 
1388
       * Since we are creating the facet list for the first
 
1389
       * we need to learn how many verticies are in all the
 
1390
       * lists.
 
1391
       */
 
1392
      pddlist = input_vert->ddList;
 
1393
      for (i = 0, total_facets = 0; i < input_vert->numLists; pddlist++, i++)
 
1394
        total_facets  += (pddlist->numPoints - 2); 
 
1395
    } else {
 
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;
 
1401
    }
 
1402
 
 
1403
    if ((have_colors) && (have_normals)) { /* Why are we here? */
 
1404
      *output_fct = input_fct;
 
1405
      return(Success);
 
1406
    }
 
1407
      
 
1408
    /*
 
1409
     * Allocate storage for the facet list
 
1410
     */
 
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;
 
1416
 
 
1417
    DD_VertPointSize(input_vert->type, point_size);
 
1418
 
 
1419
    /* Don't process if insufficient number of points */
 
1420
 
 
1421
    if (input_vert->numLists > 0) {
 
1422
 
 
1423
     pddlist = input_vert->ddList;
 
1424
        
 
1425
     for (i = 0; i < input_vert->numLists; i++) {
 
1426
 
 
1427
      in_pt.ptr = pddlist->pts.ptr;
 
1428
 
 
1429
      for (j = 2; j < pddlist->numPoints; j++) {
 
1430
 
 
1431
        /*
 
1432
         * Compute "intrinsic" color of facet.
 
1433
         * There is a "hierarchy" of sources for a facet's intrinsic
 
1434
         * color:
 
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.
 
1445
         */
 
1446
 
 
1447
        if (DD_IsVertColour(input_vert->type)) {
 
1448
 
 
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;
 
1455
          
 
1456
          out_fct->colour.red = ( vert1->colour.red + 
 
1457
                                  vert2->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;
 
1465
 
 
1466
        } else if (have_colors) {
 
1467
          out_fct->colour = *in_fct.pFacetRgbFloat;
 
1468
          in_fct.pFacetRgbFloat++;
 
1469
        } else {
 
1470
          /* use front face colors. This needs to get generalized
 
1471
             to deal with back-facing attributes*/
 
1472
          out_fct->colour =
 
1473
                (pddc->Static.attrs->surfaceColour.colour.rgbFloat);
 
1474
        }
 
1475
 
 
1476
        if (!(have_normals)) {
 
1477
         /*
 
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.
 
1482
          *
 
1483
          * The Surface normal is the cross product 
 
1484
          * of three non-colinear points, in correct order.
 
1485
          */        
 
1486
 
 
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;
 
1492
          
 
1493
         if IS_ODD(j) {
 
1494
              CROSS_PRODUCT((&(vert3->pt)), (&(vert2->pt)), (&(vert1->pt)), 
 
1495
                            &(out_fct->normal));
 
1496
              }
 
1497
         else {
 
1498
              CROSS_PRODUCT((&(vert1->pt)), (&(vert2->pt)), (&(vert3->pt)), 
 
1499
                            &(out_fct->normal));
 
1500
            }
 
1501
 
 
1502
            NORMALIZE_VECTOR(&(out_fct->normal), length);
 
1503
 
 
1504
            /* Initialize to zero if triangle is
 
1505
             * degenerate and points are co-linear
 
1506
             */
 
1507
 
 
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);
 
1513
            }
 
1514
          } else { 
 
1515
            /* use input facet normals */
 
1516
            out_fct->normal = *in_fct.pFacetN;
 
1517
            in_fct.pFacetN++;
 
1518
          }
 
1519
 
 
1520
          /* Process next facet */
 
1521
          out_fct++;
 
1522
          in_pt.ptr += point_size;
 
1523
        }
 
1524
 
 
1525
        pddlist++;
 
1526
      }
 
1527
 
 
1528
      fct_list->numFacets = total_facets;
 
1529
      fct_list->type = DD_FACET_RGBFLOAT_NORM;
 
1530
 
 
1531
    } else {
 
1532
      fct_list->type = DD_FACET_NONE;
 
1533
      fct_list->numFacets = 0;
 
1534
    }
 
1535
 
 
1536
  *output_fct = fct_list;
 
1537
  return(Success);
 
1538
 
 
1539
}
 
1540
 
 
1541
/*++
 
1542
 |
 
1543
 |  Calculate_TriStrip_Facet_Normal
 
1544
 |
 
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.
 
1548
 |
 
1549
 --*/
 
1550
static
 
1551
ddpex3rtn
 
1552
Calculate_TriStrip_Facet_Normal(pddc, input_vert, input_fct, output_fct)
 
1553
    miDDContext         *pddc;
 
1554
    miListHeader        *input_vert;    /* input vertex data */
 
1555
    listofddFacet       *input_fct;     /* input facet data */
 
1556
    listofddFacet       **output_fct;   /* output facet data */
 
1557
{
 
1558
 
 
1559
    listofddFacet       *fct_list;
 
1560
    ddRgbFloatColour    *in_fct;
 
1561
    ddFacetUnion        out_fct;
 
1562
    listofddPoint       *pddlist;
 
1563
    ddPointUnion        in_pt, nxt_pt;
 
1564
    ddVector3D          normal;
 
1565
    int                 point_size;
 
1566
    ddCoord3D           *vert1, *vert2, *vert3;
 
1567
    int                 numfacets;
 
1568
    int                 i,j;
 
1569
    float               length;
 
1570
 
 
1571
 
 
1572
    /* Some quick error checking */
 
1573
    if ((input_fct) && (DD_IsFacetNormal(input_fct->type))) return(Success);
 
1574
 
 
1575
 
 
1576
    /*
 
1577
     * First, allocate storage for the facet list
 
1578
     */
 
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));
 
1585
    } else {
 
1586
      in_fct = 0;
 
1587
      fct_list->type = DD_FACET_NORM;
 
1588
 
 
1589
 
 
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);
 
1594
 
 
1595
      MI_ALLOCLISTOFDDFACET(fct_list, numfacets, sizeof(ddVector3D));
 
1596
    }
 
1597
 
 
1598
    fct_list->numFacets = numfacets;
 
1599
    if (!fct_list->facets.pNoFacet) return(BadAlloc);
 
1600
 
 
1601
    /* Otherwise... */ 
 
1602
    out_fct = fct_list->facets;
 
1603
    DD_VertPointSize(input_vert->type, point_size);
 
1604
 
 
1605
    /* Don't process if no facets (!) */
 
1606
    if (numfacets == 0) return(1);
 
1607
 
 
1608
    else {
 
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++) {
 
1613
 
 
1614
          /* Copy the input facet color */
 
1615
          if (in_fct) {
 
1616
            *out_fct.pFacetRgbFloat = *in_fct;
 
1617
            in_fct++;
 
1618
          }
 
1619
 
 
1620
          /* Calculate and copy normal */ 
 
1621
 
 
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;
 
1627
 
 
1628
          if (IS_ODD(j)) {
 
1629
                CROSS_PRODUCT(vert3, vert2, vert1, &normal);
 
1630
          } else {
 
1631
                CROSS_PRODUCT(vert1, vert2, vert3, &normal);
 
1632
          }
 
1633
 
 
1634
          NORMALIZE_VECTOR(&normal, length)
 
1635
          
 
1636
          /* Initialize to zero if triangle is
 
1637
           * degenerate and points are co-linear
 
1638
           */
 
1639
 
 
1640
          if (length == 0.0) {
 
1641
            (normal.x = 0.0);
 
1642
            (normal.y = 0.0);
 
1643
            (normal.z = 0.0);
 
1644
           }
 
1645
 
 
1646
 
 
1647
          if (in_fct) (out_fct.pFacetRgbFloatN++)->normal = normal;
 
1648
          else *(out_fct.pFacetN++) = normal;
 
1649
 
 
1650
          in_pt.ptr += point_size;
 
1651
        }
 
1652
        pddlist++;
 
1653
      }
 
1654
    }
 
1655
 
 
1656
    *output_fct = fct_list;
 
1657
 
 
1658
    return(Success);
 
1659
}
 
1660
 
 
1661
 
 
1662
/*++
 
1663
 |
 
1664
 |  Breakup_TriStrip 
 
1665
 |
 
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.   
 
1669
 |     
 
1670
 |    
 
1671
 |
 
1672
 --*/
 
1673
static
 
1674
ddpex3rtn
 
1675
Breakup_TriStrip(pddc, input_vert, input_fct, output_vert, output_fct)
 
1676
    miDDContext         *pddc;
 
1677
    miListHeader        *input_vert;
 
1678
    miListHeader        **output_vert;    
 
1679
    listofddFacet       *input_fct;     /* input facet data */
 
1680
    listofddFacet       **output_fct;   /* output facet data */
 
1681
{
 
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;
 
1689
    int                 point_size;
 
1690
    int                 numfacets, facetofpoints;
 
1691
    int                 i,j;
 
1692
 
 
1693
 
 
1694
 
 
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))
 
1699
        return(i);
 
1700
      input_fct = fct_list;
 
1701
    }
 
1702
  
 
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;
 
1709
 
 
1710
    list1->numLists = input_fct->numFacets; 
 
1711
    
 
1712
 
 
1713
    DD_VertPointSize(input_vert->type, point_size);
 
1714
    facetofpoints = 3 * point_size;
 
1715
 
 
1716
    for(i = 0,  pddilist = input_vert->ddList,
 
1717
                pddolist = list1->ddList;
 
1718
                i < input_vert->numLists; i++) {
 
1719
 
 
1720
      for (j = 2, pt_in.ptr = pddilist->pts.ptr;
 
1721
                j < pddilist->numPoints; j++) {
 
1722
 
 
1723
        MI_ALLOCLISTOFDDPOINT(pddolist, 1, facetofpoints);
 
1724
 
 
1725
        /*
 
1726
         * Note that to preserver correct normals, must
 
1727
         * flip the order of the vertices every other facet.
 
1728
         */
 
1729
        if IS_ODD(j) {
 
1730
 
 
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);
 
1738
  
 
1739
        } else {
 
1740
 
 
1741
          memcpy( pddolist->pts.ptr, pt_in.ptr, facetofpoints);
 
1742
 
 
1743
        }
 
1744
 
 
1745
        pddolist->numPoints = 3;
 
1746
        pddolist++;             /* one list per facet */
 
1747
        pt_in.ptr += point_size;
 
1748
      }
 
1749
      pddilist++;
 
1750
    }
 
1751
 
 
1752
    *output_fct = input_fct;
 
1753
    *output_vert = list1; 
 
1754
    return(Success);        
 
1755
}
 
1756
 
 
1757
 
 
1758
 
 
1759
 
 
1760
 
 
1761
/*++
 
1762
 |
 
1763
 |  Calculate_TriStrip_Vertex_Color_and_Normal
 
1764
 |
 
1765
 |      Add vertex normals and colors to a vertex list.
 
1766
 |
 
1767
 --*/
 
1768
static
 
1769
ddpex3rtn
 
1770
Calculate_TriStrip_Vertex_Color_and_Normal(pRend, input_vert, input_fct,
 
1771
                                           output_vert)
 
1772
 
 
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 */
 
1777
{
 
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;
 
1787
    int                         facet_size;
 
1788
    int                         numFacets=0;
 
1789
    int                         i,j;
 
1790
    ddpex3rtn                   status;
 
1791
 
 
1792
 
 
1793
    /* Some quick error checking */
 
1794
    if ((DD_IsVertNormal(input_vert->type)) &&
 
1795
        (DD_IsVertColour(input_vert->type)))
 
1796
      return(Success);
 
1797
 
 
1798
    /* Use one of the pre-defined 4D list for output */
 
1799
    *output_vert = out_vert = MI_NEXTTEMPDATALIST(pddc);
 
1800
 
 
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);
 
1805
 
 
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);
 
1810
    }
 
1811
    out_vert->numLists = input_vert->numLists;
 
1812
    out_vert->flags =  input_vert->flags;
 
1813
 
 
1814
    pddilist = input_vert->ddList;
 
1815
    pddolist = out_vert->ddList;
 
1816
 
 
1817
    DD_VertPointSize(input_vert->type, inpoint_size);
 
1818
    DD_VertPointSize(out_vert->type, outpoint_size);
 
1819
 
 
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)))) ) {
 
1823
 
 
1824
      if (i = Calculate_TriStrip_Facet_Normal(pddc, input_vert,
 
1825
                                              input_fct, &fct_list))
 
1826
        return(i);
 
1827
 
 
1828
      input_fct = fct_list;
 
1829
    }
 
1830
 
 
1831
    if ((input_fct) && (input_fct->numFacets > 0)) {
 
1832
        in_fct = input_fct->facets;
 
1833
        DDFacetSIZE(input_fct->type, facet_size);
 
1834
    }
 
1835
    else in_fct.pNoFacet = 0;
 
1836
 
 
1837
 
 
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),
 
1842
                            outpoint_size);
 
1843
      if (!(out_pt.ptr = pddolist->pts.ptr)) return(BadAlloc);
 
1844
 
 
1845
      for (j = 0, in_pt.ptr = pddilist->pts.ptr,
 
1846
        out_pt.ptr = pddolist->pts.ptr;
 
1847
        j < pddilist->numPoints; j++) {
 
1848
 
 
1849
        /* First copy over coordinate data */
 
1850
        *out_pt.p4Dpt = *in_pt.p4Dpt;
 
1851
        in_pt.p4Dpt++;
 
1852
        out_pt.p4Dpt++;
 
1853
 
 
1854
        /*
 
1855
         * Next color
 
1856
         * Colour is derived first from the vertex, second from the
 
1857
         * facet, and third from the current PC attributes.
 
1858
         */
 
1859
        if (DD_IsVertColour(input_vert->type)){
 
1860
          *out_pt.pRgbFloatClr = *in_pt.pRgbFloatClr;
 
1861
          in_pt.pRgbFloatClr++;
 
1862
        } 
 
1863
        else {
 
1864
          if ((in_fct.pNoFacet) && (DD_IsFacetColour(input_fct->type)))
 
1865
            *out_pt.pRgbFloatClr = *in_fct.pFacetRgbFloat;
 
1866
          else {
 
1867
            *out_pt.pRgbFloatClr =
 
1868
                (pddc->Static.attrs->surfaceColour.colour.rgbFloat);
 
1869
          }
 
1870
        }
 
1871
 
 
1872
        out_pt.pRgbFloatClr++;
 
1873
             
 
1874
        /*
 
1875
         * Next normals
 
1876
         * Normals are derived first from the vertex, second from the
 
1877
         * facet (note that we insured above that there were facet normals).
 
1878
         */
 
1879
        if DD_IsVertNormal(input_vert->type) {
 
1880
          *out_pt.pNormal = *in_pt.pNormal;
 
1881
          in_pt.pNormal++;
 
1882
        }
 
1883
        else if (DD_IsFacetColour(input_fct->type))
 
1884
          *out_pt.pNormal = in_fct.pFacetRgbFloatN->normal;
 
1885
        else *out_pt.pNormal = *in_fct.pFacetN;
 
1886
 
 
1887
        out_pt.pNormal++; 
 
1888
 
 
1889
        /* Next pass along edge info if there is any */
 
1890
        if (DD_IsVertEdge(out_vert->type)) {
 
1891
          *out_pt.pEdge = *in_pt.pEdge;
 
1892
          in_pt.pEdge++;
 
1893
          out_pt.pEdge++;
 
1894
        }
 
1895
 
 
1896
      }
 
1897
      if ((in_fct.pNoFacet)) in_fct.pNoFacet += facet_size;
 
1898
      pddilist++;
 
1899
      pddolist++;
 
1900
    }
 
1901
    return(Success);
 
1902
}
 
1903
 
 
1904
/*++
 
1905
 |
 
1906
 |  miCullTriStrip(pddc, input_vert, input_fct, output_vert, output_fct)
 
1907
 |
 
1908
 |      Perform culling of facets, and their associated data points,
 
1909
 |      according to the current culling mode.
 
1910
 |
 
1911
 --*/
 
1912
 
 
1913
static
 
1914
ddpex3rtn
 
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 */
 
1921
{
 
1922
/* uses */
 
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;
 
1930
    listofddPoint               temp;
 
1931
    int                         i, j;
 
1932
    char                        accept, new_list;
 
1933
    char                        return_facet_list;
 
1934
    int                         point_size, facet_size;
 
1935
    int                         verts_in_list, out_listnum;
 
1936
 
 
1937
    /*
 
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.
 
1941
     */
 
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;
 
1946
        *output_fct = 0;
 
1947
    } else {
 
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;
 
1952
        }
 
1953
        return_facet_list = 1;
 
1954
    }
 
1955
   
 
1956
    /*
 
1957
     * allocate storage for the output vertex and facet list
 
1958
     */
 
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);
 
1966
 
 
1967
 
 
1968
    DD_VertPointSize(input_vert->type, point_size);
 
1969
 
 
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;
 
1977
 
 
1978
 
 
1979
    /*
 
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.
 
1987
     */
 
1988
 
 
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++) {
 
1993
 
 
1994
      MI_ALLOCLISTOFDDPOINT(pddolist,(pddilist->numPoints+1),point_size);
 
1995
      if (!pddolist->pts.ptr) return(BadAlloc);
 
1996
 
 
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++) {
 
2002
 
 
2003
        accept = 0;
 
2004
 
 
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;
 
2013
        }
 
2014
 
 
2015
        if (accept) {
 
2016
 
 
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;
 
2021
            new_list = 0;
 
2022
            verts_in_list += 2;
 
2023
          }
 
2024
 
 
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;
 
2028
          ++verts_in_list;
 
2029
 
 
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;
 
2034
 
 
2035
          /* increment the output pointer */
 
2036
          out_fct.pNoFacet += facet_size;
 
2037
          fct_list->numFacets++;
 
2038
 
 
2039
        } else {
 
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;
 
2044
            out_listnum++;
 
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);
 
2049
  
 
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;
 
2056
            verts_in_list = 0;
 
2057
          } 
 
2058
          new_list = 1;
 
2059
        }
 
2060
        in_pt.ptr += point_size;
 
2061
        in_fct.pNoFacet += facet_size; 
 
2062
      }
 
2063
      ++pddilist;
 
2064
      if (verts_in_list > 2) {
 
2065
        pddolist->numPoints = verts_in_list;
 
2066
        ++out_listnum;
 
2067
        ++out_vert->numLists;
 
2068
        ++pddolist;
 
2069
      }
 
2070
    }
 
2071
 
 
2072
    /*
 
2073
     * Only return facet list if one was passed in. Reduces the
 
2074
     * information that must be processed by the rest of the pipeline.
 
2075
     */
 
2076
    if (return_facet_list) *output_fct = fct_list;
 
2077
       
 
2078
    return(Success);
 
2079
}
 
2080
 
 
2081
/*++
 
2082
 |
 
2083
 |  miDepthCueTriStrip(pddc, input_vert, input_fct, output_vert, output_fct)
 
2084
 |
 
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. 
 
2088
 |     
 
2089
 |
 
2090
 --*/
 
2091
static
 
2092
ddpex3rtn
 
2093
miDepthCueTriStrip(pRend, input_vert, input_fct, output_vert)
 
2094
 
 
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 */
 
2099
{
 
2100
    miDDContext         *pddc = (miDDContext *)(pRend->pDDContext);
 
2101
    miListHeader                *out_vert;
 
2102
    listofddFacet               *fct_list;
 
2103
    ddFLOAT                     pt_depth;
 
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;
 
2110
    int                         facet_size;
 
2111
    int                         numFacets=0;
 
2112
    int                         i,j;
 
2113
    ddpex3rtn                   status;
 
2114
    ddDepthCueEntry             *dcue_entry;
 
2115
 
 
2116
    /* look for empty list header */
 
2117
    if (input_vert->numLists == 0) return(Success);
 
2118
 
 
2119
    /* validate CC version of Depth Cue information */
 
2120
    if (pddc->Static.misc.flags & CC_DCUEVERSION)
 
2121
        Compute_CC_Dcue(pRend, pddc);
 
2122
 
 
2123
    /* check to make sure depth cuing is enabled */
 
2124
    if (pddc->Static.misc.cc_dcue_entry.mode == PEXOff) {
 
2125
        *output_vert = input_vert;
 
2126
        return(Success);
 
2127
    }
 
2128
 
 
2129
    /* Else, depth cue! Use one of the pre-defined 4D list for output */
 
2130
    *output_vert = out_vert = MI_NEXTTEMPDATALIST(pddc);
 
2131
 
 
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);
 
2136
 
 
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;
 
2142
 
 
2143
    pddilist = input_vert->ddList;
 
2144
    pddolist = out_vert->ddList;
 
2145
 
 
2146
    DD_VertPointSize(input_vert->type, inpoint_size);
 
2147
    DD_VertPointSize(out_vert->type, outpoint_size);
 
2148
 
 
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;
 
2153
 
 
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),
 
2158
                            outpoint_size);
 
2159
      if (!(out_pt.ptr = pddolist->pts.ptr)) return(BadAlloc);
 
2160
 
 
2161
      for (j = 0, in_pt.ptr = pddilist->pts.ptr,
 
2162
        out_pt.ptr = pddolist->pts.ptr;
 
2163
        j < pddilist->numPoints; j++) {
 
2164
 
 
2165
        /* First copy over coordinate data */
 
2166
        pt_depth = in_pt.p4Dpt->z;
 
2167
        *out_pt.p4Dpt = *in_pt.p4Dpt;
 
2168
        in_pt.p4Dpt++;
 
2169
        out_pt.p4Dpt++;
 
2170
 
 
2171
        /*
 
2172
         * Next color
 
2173
         * Colour is derived first from the vertex, second from the
 
2174
         * facet, and third from the current PC attributes.
 
2175
         */
 
2176
        if (DD_IsVertColour(input_vert->type)){
 
2177
          in_color = in_pt.pRgbFloatClr;
 
2178
          in_pt.pRgbFloatClr++;
 
2179
        }
 
2180
        else {
 
2181
          if ((in_fct.pNoFacet) && (DD_IsFacetColour(input_fct->type)))
 
2182
            in_color = in_fct.pFacetRgbFloat;
 
2183
          else {
 
2184
            in_color =
 
2185
                &(pddc->Static.attrs->surfaceColour.colour.rgbFloat);
 
2186
          }
 
2187
        }
 
2188
 
 
2189
        APPLY_DEPTH_CUEING(pddc->Static.misc.cc_dcue_entry,
 
2190
                 pt_depth, in_color, out_pt.pRgbFloatClr)
 
2191
 
 
2192
        out_pt.pRgbFloatClr++;
 
2193
 
 
2194
        /*
 
2195
         * Next normals
 
2196
         * Normals are derived first from the vertex, second from the
 
2197
         * facet (note that we insured above that there were facet normals).
 
2198
         */
 
2199
        if DD_IsVertNormal(input_vert->type) {
 
2200
          *out_pt.pNormal = *in_pt.pNormal;
 
2201
          in_pt.pNormal++;
 
2202
          out_pt.pNormal++;
 
2203
        }
 
2204
 
 
2205
        /* Next pass along edge info if there is any */
 
2206
        if (DD_IsVertEdge(out_vert->type)) {
 
2207
          *out_pt.pEdge = *in_pt.pEdge;
 
2208
          in_pt.pEdge++;
 
2209
          out_pt.pEdge++;
 
2210
        }
 
2211
 
 
2212
      }  
 
2213
      if ((in_fct.pNoFacet)) in_fct.pNoFacet += facet_size;
 
2214
      pddilist++;
 
2215
      pddolist++;
 
2216
    }
 
2217
    return(Success);
 
2218
}
 
2219
 
 
2220
 
 
2221
 
 
2222
 
 
2223