1 /* Copyright (C) 1992-1998 The Geometry Center
2  * Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips
3  *
4  * This file is part of Geomview.
5  *
6  * Geomview is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published
8  * by the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * Geomview is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Geomview; see the file COPYING.  If not, write
18  * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
19  * USA, or visit http://www.gnu.org.
20  */
21 
22 #if HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25 
26 #if 0
27 static char copyright[] = "Copyright (C) 1992-1998 The Geometry Center\n\
28 Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips";
29 #endif
30 
31 #include "mgP.h"
32 #include "mgpsP.h"
33 #include "polylistP.h"
34 #include "mgpswindows.h"
35 
36 
37 /* Author: Daeron Meyer */
38 
39 void	mgps_polygon( int nv, HPoint3 *v, int nn, Point3 *n,
40 	      	          int nc, ColorA *c );
41 void	mgps_mesh(int wrap, int nu, int nv, HPoint3 *p, Point3 *n, Point3 *nq,
42 		  ColorA *c );
43 void	mgps_line( HPoint3 *p1, HPoint3 *p2 );
44 void	mgps_polyline( int nv, HPoint3 *verts, int nc, ColorA *colors,
45 			int wrap );
46 void	mgps_polylist(  int np, Poly *p, int nv, Vertex *v,
47 			int pl_flags );
48 void	mgps_drawnormal(HPoint3 *p, Point3 *n);
49 
50 void	mgps_closer();
51 void	mgps_farther();
52 
53 static ColorA *C2;
54 
55 /*-----------------------------------------------------------------------
56  * Function:	mgps_polygon
57  * Description:	draw a polygon
58  * Author:	Daeron Meyer
59  * Notes:	See mg.doc.
60  *
61  */
62 void
mgps_polygon(int nv,HPoint3 * V,int nn,Point3 * N,int nc,ColorA * C)63 mgps_polygon(int nv,  HPoint3 *V,
64 	     int nn,  Point3 *N,
65 	     int nc,  ColorA *C)
66 {
67   int		count;
68   HPoint3     *v;
69   Point3      *n;
70   int			flag, ninc, smooth;
71 
72 /*  fprintf(stderr,"X11: draw a polygon\n"); */
73 
74   flag = _mgc->astk->ap.flag;
75   if ((_mgc->astk->mat.override & MTF_DIFFUSE) &&
76       !(_mgc->astk->flags & MGASTK_SHADER)) nc = 0;
77   ninc = (nn > 1);
78   smooth = IS_SMOOTH(_mgc->astk->ap.shading);
79 /*
80   fprintf(stderr,"cinc = %d, nc = %d, nn = %d\n", cinc, nc, nn);
81 */
82   if (nc == 0)
83     C = (ColorA*)&_mgc->astk->ap.mat->diffuse;
84 
85   if ((flag & APF_FACEDRAW) && (flag & APF_EDGEDRAW)) {
86     /* put polygon in display list */
87 
88     if (smooth && (nc > 0))
89       mgps_add(MGX_BGNSEPOLY, 0, NULL, NULL);
90     else
91       mgps_add(MGX_BGNEPOLY, 0, NULL, NULL);
92 
93     mgps_add(MGX_ECOLOR, 0, NULL, &_mgc->astk->ap.mat->edgecolor);
94 							    /* edge color */
95     mgps_add(MGX_COLOR, 0, NULL, C);			    /* face color */
96 
97     if (smooth)
98       mgps_add(MGX_CVERTEX, nv, V, C);
99     else
100       mgps_add(MGX_VERTEX, nv, V, NULL);
101 
102     mgps_add(MGX_END, 0, NULL, NULL);
103   }
104   else
105     if (flag & APF_FACEDRAW) {
106       /* put polygon in display list */
107       if (smooth)
108         mgps_add(MGX_BGNSPOLY, 0, NULL, NULL);
109       else
110         mgps_add(MGX_BGNPOLY, 0, NULL, NULL);
111 
112       mgps_add(MGX_COLOR, 0, NULL, C);
113 
114       if (smooth && (nc > 0))
115         mgps_add(MGX_CVERTEX, nv, V, C);
116       else
117         mgps_add(MGX_VERTEX, nv, V, NULL);
118 
119       mgps_add(MGX_END, 0, NULL, NULL);
120     }
121     else
122       if (flag & APF_EDGEDRAW) {
123 	mgps_add(MGX_BGNLINE, 0, NULL, NULL);
124 	mgps_add(MGX_ECOLOR, 0, NULL, &_mgc->astk->ap.mat->edgecolor);
125 	mgps_add(MGX_VERTEX, nv, V, NULL);
126         mgps_add(MGX_VERTEX, 1, V, NULL);
127 	mgps_add(MGX_END, 0, NULL, NULL);
128       }
129 
130   if (flag & APF_NORMALDRAW)
131   {
132     mgps_closer();
133     mgps_add(MGX_ECOLOR, 0, NULL, &_mgc->astk->ap.mat->normalcolor);
134     for (n = N, v = V, count = 0; count<nv; ++count, ++v, n += ninc)
135       mgps_drawnormal(v, n);
136     mgps_farther();
137   }
138 }
139 
140 /*-----------------------------------------------------------------------
141  * Function:	mgps_line
142  * Description:	draw a line (one color)
143  * Author:	Daeron Meyer
144  * Notes:	See mg.doc.
145  *
146  */
mgps_line(HPoint3 * p1,HPoint3 * p2)147 void mgps_line( HPoint3 *p1, HPoint3 *p2 )
148 {
149 
150 /*  fprintf(stderr,"X11: draw a line\n"); */
151 
152   /* put a line in the display list */
153 
154   mgps_add(MGX_BGNLINE, 0, NULL, NULL);
155   mgps_add(MGX_VERTEX, 1, p1, NULL);
156   mgps_add(MGX_VERTEX, 1, p2, NULL);
157   mgps_add(MGX_END, 0, NULL, NULL);
158 
159 }
160 
161 /* Construct a prototype polygonal outline for creating fat points.
162  * Curiously, we can do this independently of the position of the point,
163  * if we operate in homogeneous space.
164  */
165 
166 /*-----------------------------------------------------------------------
167  * Function:	mgps_fatpoint
168  * Description:	draw a point (possible width > 1)
169  * Author:	Daeron Meyer
170  * Notes:	See mg.doc.
171  *
172  */
mgps_fatpoint(HPoint3 * v)173 void mgps_fatpoint(HPoint3 *v)
174 {
175   HPoint3 a;
176   HPoint3 *p, *q;
177   float vw;
178 
179 /*  fprintf(stderr,"X11: make a fat-point\n"); */
180 
181   if (!(_mgc->has & HAS_POINT))
182     mg_makepoint();
183 
184   /* Compute w component of point after projection to screen */
185   vw = v->x * _mgc->O2S[0][3] + v->y * _mgc->O2S[1][3]
186       + v->z * _mgc->O2S[2][3] + v->w * _mgc->O2S[3][3];
187   if (vw <= 0) return;
188 
189 #define  PUT(p)                                         \
190         a.x = v->x + p->x*vw; a.y = v->y + p->y*vw;     \
191         a.z = v->z + p->z*vw; a.w = v->w + p->w*vw;     \
192         mgps_add(MGX_VERTEX, 1, &a, NULL);
193 
194   p = VVEC(_mgc->point, HPoint3);
195   q = p + VVCOUNT(_mgc->point);
196 
197   mgps_add(MGX_BGNPOLY, 0, NULL, NULL);
198   do
199   {
200     PUT(p);
201   } while (++p < q);
202   mgps_add(MGX_END, 0, NULL, NULL);
203 
204 }
205 
206 
207 /*-----------------------------------------------------------------------
208  * Function:	mgps_polyline
209  * Description:	draw a polyline (possibly more than 2 vertices)
210  * Author:	Daeron Meyer
211  * Notes:	See mg.doc.
212  *
213  */
214 
mgps_polyline(int nv,HPoint3 * v,int nc,ColorA * c,int wrapped)215 void mgps_polyline( int nv, HPoint3 *v, int nc, ColorA *c, int wrapped )
216 {
217   int remain;
218 /*  fprintf(stderr,"X11: draw a polyline\n"); */
219 
220   if (!(wrapped & 2)) {
221     if (_mgpsc->znudge) mgps_closer();
222   }
223   if (nv == 1)
224   {
225     if (nc > 0)
226       mgps_add(MGX_ECOLOR, 0, NULL, c);
227 
228     if (_mgc->astk->ap.linewidth > 1)
229     {
230       mgps_add(MGX_COLOR, 0, NULL, c);
231       mgps_fatpoint(v);
232     }
233     else
234     {
235       mgps_add(MGX_BGNSLINE, 0, NULL, NULL);
236       mgps_add(MGX_CVERTEX, 1, v, c);
237       mgps_add(MGX_END, 0, NULL, NULL);
238     }
239   }
240   else
241     if (nv > 0)
242     {
243         mgps_add(MGX_BGNSLINE, 0, NULL, NULL);
244 
245       if (wrapped & 1)
246       {
247 	if (nc > 0)
248         {
249 	  mgps_add(MGX_ECOLOR, 0, NULL, (c + nc - 1));
250 	  mgps_add(MGX_CVERTEX, 1, (v + nv - 1), (c + nc - 1));
251         }
252         else
253 	  mgps_add(MGX_CVERTEX, 1, (v + nv - 1), c);
254       }
255 
256       for (;;)
257       {
258 	remain = nv > 254 ? 254 : nv;
259 	nv -= remain;
260 	do
261 	{
262 	  if (--nc > 0)
263           {
264 	    mgps_add(MGX_ECOLOR, 0, NULL, c);
265 	    mgps_add(MGX_CVERTEX, 1, v++, c++);
266           }
267           else
268 	    mgps_add(MGX_CVERTEX, 1, v++, c);
269 
270 	} while (--remain > 0);
271 	if (nv == 0)
272 	  break;
273 	if (nc > 0)
274 	  mgps_add(MGX_ECOLOR, 0, NULL, c);
275 	mgps_add(MGX_CVERTEX, 1, v, c);
276 	mgps_add(MGX_END, 0, NULL, NULL);
277 	mgps_add(MGX_BGNSLINE, 0, NULL, NULL);
278       }
279       mgps_add(MGX_END, 0, NULL, NULL);
280     }
281   if (!(wrapped & 4) && _mgpsc->znudge)
282     mgps_farther();
283 }
284 
285 
286 /*-----------------------------------------------------------------------
287  * Function:	mgps_polylist
288  * Description:	draws a Polylist: collection of Polys
289  * Author:	Daeron Meyer
290  * Notes:	see mg.doc
291  */
mgps_polylist(int np,Poly * _p,int nv,Vertex * V,int pl_flags)292 void mgps_polylist( int np, Poly *_p, int nv, Vertex *V, int pl_flags )
293 {
294   int		i, j;
295   Poly		*p;
296   Vertex 	**v, *vp, **vh;
297   struct mgastk *ma = _mgc->astk;
298   int plflags = pl_flags;
299   int flag, shading;
300   int nonsurf = -1;
301 
302   flag = ma->ap.flag;
303   shading = ma->ap.shading;
304 
305 /*  fprintf(stderr,"X11: draw a polylist %d\n",np); */
306 
307   switch(shading) {
308   case APF_FLAT:
309     plflags &= ~PL_HASVN;
310     if (plflags & PL_HASPCOL) {
311       plflags &= ~PL_HASVCOL;
312     }
313     break;
314   case APF_SMOOTH: plflags &= ~PL_HASPN; break;
315   case APF_VCFLAT: plflags &= ~PL_HASVN; break;
316   default: plflags &= ~(PL_HASVN|PL_HASPN); break;
317   }
318 
319   if ((_mgc->astk->mat.override & MTF_DIFFUSE) &&
320       !(_mgc->astk->flags & MGASTK_SHADER))
321     plflags &= ~(PL_HASVCOL | PL_HASPCOL);
322 
323   if (flag & APF_FACEDRAW)
324   {
325     for (p = _p, i = 0; i < np; i++, p++)
326     {
327 
328       v = p->v;
329       if ((j = p->n_vertices) <= 2)
330 	nonsurf = i;
331       else
332       {
333         if (flag & APF_EDGEDRAW)
334 	{
335 	  if (shading == APF_FLAT || shading == APF_CONSTANT) {
336 	    mgps_add(MGX_BGNEPOLY, 0, NULL, NULL);
337 	  } else
338           if (plflags & PL_HASVCOL)
339 	    mgps_add(MGX_BGNSEPOLY, 0, NULL, NULL);
340           else
341 	    mgps_add(MGX_BGNEPOLY, 0, NULL, NULL);
342           mgps_add(MGX_ECOLOR, 0, NULL, &_mgc->astk->ap.mat->edgecolor);
343 	}
344 	else
345           {
346 	    if (shading == APF_FLAT || shading == APF_CONSTANT) {
347 	      mgps_add(MGX_BGNPOLY, 0, NULL, NULL);
348 	    } else
349             if (plflags & PL_HASVCOL)
350 	      mgps_add(MGX_BGNSPOLY, 0, NULL, NULL);
351 	    else
352 	      mgps_add(MGX_BGNPOLY, 0, NULL, NULL);
353 	  }
354 
355 	if (plflags & PL_HASPCOL)
356 	  mgps_add(MGX_COLOR, 0, NULL, &p->pcol);
357 	else
358 	  if (plflags & PL_HASVCOL)	        /* if we have per vertex */
359 	    mgps_add(MGX_COLOR, 0, NULL, &(*v)->vcol);
360 	  else
361 	    mgps_add(MGX_COLOR, 0, NULL, &(ma->ap.mat->diffuse));
362 	vh = v;
363 	do
364 	{
365 	  if (plflags & PL_HASVCOL) mgps_add(MGX_CVERTEX, 1, &(*v)->pt, &(*v)->vcol);
366 	    else
367 	      mgps_add(MGX_CVERTEX, 1, &(*v)->pt, &(*vh)->vcol);
368 
369 	  v++;
370 	} while (--j > 0);
371 
372         mgps_add(MGX_END, 0, NULL, NULL);
373       }
374     }
375   }
376   if (flag & (APF_EDGEDRAW | APF_NORMALDRAW) || nonsurf > 0)
377   {
378     if (_mgpsc->znudge) mgps_closer();
379 
380     if (flag & APF_EDGEDRAW && !(flag & APF_FACEDRAW))
381     {
382       mgps_add(MGX_ECOLOR, 0, NULL, &_mgc->astk->ap.mat->edgecolor);
383       for (p = _p, i = 0; i < np; i++, p++)
384       {
385 	mgps_add(MGX_BGNLINE, 0, NULL, NULL);
386 	for (j = 0, v = p->v; j < p->n_vertices; j++, v++)
387 	  mgps_add(MGX_VERTEX, 1, &(*v)->pt, NULL);
388 	mgps_add(MGX_VERTEX, 1, &(*(p->v))->pt, NULL);
389 	mgps_add(MGX_END, 0, NULL, NULL);
390       }
391 
392     }
393 
394     if (flag & APF_NORMALDRAW)
395     {
396       mgps_add(MGX_ECOLOR, 0, NULL, &_mgc->astk->ap.mat->normalcolor);
397       if (pl_flags & PL_HASPN)
398       {
399 	for (p = _p, i = 0; i < np; i++, p++)
400 	{
401 	  for (j = 0, v = p->v; j < p->n_vertices; j++, v++)
402 	    mgps_drawnormal(&(*v)->pt, &p->pn);
403 	}
404       }
405       else
406       if (pl_flags & PL_HASVN)
407       {
408 	for (vp = V, i = 0; i < nv; i++, vp++)
409 	  mgps_drawnormal(&vp->pt, &vp->vn);
410       }
411     }
412 
413     for (p = _p, i = 0; i <= nonsurf; p++, i++)
414     {
415       v = p->v;
416       switch (j = p->n_vertices)
417       {
418 	case 1:
419 	  mgps_add(MGX_BGNLINE, 0, NULL, NULL);
420 	  if (pl_flags & PL_HASVCOL)
421 	    mgps_add(MGX_ECOLOR, 0, NULL, &(*v)->vcol);
422 	  mgps_add(MGX_VERTEX, 1, &(*v)->pt, NULL);
423 	  mgps_add(MGX_END, 0, NULL, NULL);
424 	  break;
425 	case 2:
426 	  mgps_add(MGX_BGNLINE, 0, NULL, NULL);
427 	  do
428 	  {
429 	    if (pl_flags & PL_HASVCOL)
430 	      mgps_add(MGX_ECOLOR, 0, NULL, &(*v)->vcol);
431 	    mgps_add(MGX_VERTEX, 1, &(*v)->pt, NULL);
432 	    v++;
433 	  } while (--j > 0);
434 	  mgps_add(MGX_END, 0, NULL, NULL);
435 	  break;
436       }
437     }
438     if (_mgpsc->znudge) mgps_farther();
439   }
440 }
441 
442 #define HAS_N   1
443 #define HAS_C   2
444 #define HAS_SMOOTH 4
445 
446 /*-----------------------------------------------------------------------
447  * Function:	mgpspolymeshrow
448  * Description:	draw one row of a mesh
449  * Author:	Daeron Meyer
450  * Notes:	See mg.doc.
451  *
452  */
mgpspolymeshrow(int wrap,int has,int off,int count,HPoint3 * P,Point3 * N,ColorA * C,int flag,float * CE,int first)453 void mgpspolymeshrow(int wrap, int has, int off, int count, HPoint3 *P,
454 			Point3 *N, ColorA *C, int flag, float *CE, int first)
455 {
456   int k;
457   int edges = flag & APF_EDGEDRAW;
458   int faces = flag & APF_FACEDRAW;
459 
460   if (wrap & MM_UWRAP)
461   {
462     k = count - 1;
463     if (edges && faces)
464     {
465       if (has & HAS_SMOOTH)
466         mgps_add(MGX_BGNSEPOLY, 0, NULL, NULL);
467       else
468         mgps_add(MGX_BGNEPOLY, 0, NULL, NULL);
469 
470       mgps_add(MGX_ECOLOR, 0, NULL, CE);
471     }
472     else
473     if (faces)
474     {
475       if (has & HAS_SMOOTH)
476         mgps_add(MGX_BGNSPOLY, 0, NULL, NULL);
477       else
478         mgps_add(MGX_BGNPOLY, 0, NULL, NULL);
479     }
480     else
481     {
482        mgps_add(MGX_BGNLINE, 0, NULL, NULL);
483        mgps_add(MGX_ECOLOR, 0, NULL, CE);
484     }
485     if (C)
486     {
487       mgps_add(MGX_COLOR, 0, NULL, C+off+k);
488       C2 = C+off+k;
489     }
490     else
491       mgps_add(MGX_COLOR, 0, NULL, C2);
492 
493     if (has & HAS_SMOOTH)
494     {
495       if (C)
496       {
497 	mgps_add(MGX_CVERTEX, 1, P+off+k, C+off+k);
498 	mgps_add(MGX_CVERTEX, 1, P+k, C+k);
499 	mgps_add(MGX_CVERTEX, 1, P, C);
500 	mgps_add(MGX_CVERTEX, 1, P+off, C+off);
501         C2 = C+off;
502       }
503       else
504       {
505 	mgps_add(MGX_CVERTEX, 1, P+off+k, C2);
506 	mgps_add(MGX_CVERTEX, 1, P+k, C2);
507 	mgps_add(MGX_CVERTEX, 1, P, C2);
508 	mgps_add(MGX_CVERTEX, 1, P+off, C2);
509       }
510     }
511     else
512     {
513       mgps_add(MGX_VERTEX, 1, P+off+k, NULL);
514       mgps_add(MGX_VERTEX, 1, P+k, NULL);
515       mgps_add(MGX_VERTEX, 1, P, NULL);
516       mgps_add(MGX_VERTEX, 1, P+off, NULL);
517     }
518     mgps_add(MGX_END, 0, NULL, NULL);
519   }
520   k = count;
521   do
522   {
523     if (edges && faces)
524     {
525       if (has & HAS_SMOOTH)
526         mgps_add(MGX_BGNSEPOLY, 0, NULL, NULL);
527       else
528         mgps_add(MGX_BGNEPOLY, 0, NULL, NULL);
529 
530       mgps_add(MGX_ECOLOR, 0, NULL, CE);
531     }
532     else
533     if (faces)
534     {
535       if (has & HAS_SMOOTH)
536         mgps_add(MGX_BGNSPOLY, 0, NULL, NULL);
537       else
538         mgps_add(MGX_BGNPOLY, 0, NULL, NULL);
539     }
540     else
541     {
542       mgps_add(MGX_BGNLINE, 0, NULL, NULL);
543       mgps_add(MGX_ECOLOR, 0, NULL, CE);
544 /* ADDED */
545       if (first)
546         mgps_add(MGX_VERTEX, 1, P+1+off, NULL);
547 /* END */
548     }
549 
550     if (C)
551     {
552       mgps_add(MGX_COLOR, 0, NULL, C+off);
553       C2 = C+off;
554     }
555 
556     if (has & HAS_SMOOTH)
557     {
558       if (C) { mgps_add(MGX_CVERTEX, 1, P+off, C+off); C2 = C; }
559       else mgps_add(MGX_CVERTEX, 1, P+off, C2);
560       if (C) { mgps_add(MGX_CVERTEX, 1, P++, C++); C2 = C; }
561       else mgps_add(MGX_CVERTEX, 1, P++, C2);
562       if (C) { mgps_add(MGX_CVERTEX, 1, P, C); C2 = C; }
563       else mgps_add(MGX_CVERTEX, 1, P, C2);
564       if (C) { mgps_add(MGX_CVERTEX, 1, P+off, C+off); C2 = C; }
565       else mgps_add(MGX_CVERTEX, 1, P+off, C2);
566     }
567     else
568     {
569       mgps_add(MGX_VERTEX, 1, P+off, NULL);
570       if (C) C++;
571       if (N) N++;
572       mgps_add(MGX_VERTEX, 1, P++, NULL);
573       mgps_add(MGX_VERTEX, 1, P, NULL);
574       mgps_add(MGX_VERTEX, 1, P+off, NULL);
575     }
576 
577     mgps_add(MGX_END, 0, NULL, NULL);
578 
579   } while (--k > 1);
580 
581 }
582 
583 /*-----------------------------------------------------------------------
584  * Function:	mgpssubmesh
585  * Description:	divide up mesh and draw by rows
586  * Author:	Daeron Meyer
587  * Notes:	See mg.doc.
588  *
589  */
mgpssubmesh(int wrap,int nu,int nv,int umin,int umax,int vmin,int vmax,HPoint3 * meshP,Point3 * meshN,ColorA * meshC)590 void mgpssubmesh(int wrap, int nu, int nv, int umin, int umax, int vmin,
591 		int vmax, HPoint3 *meshP, Point3 *meshN, ColorA *meshC)
592 {
593   int v;
594   int ucnt;
595   HPoint3 *P;
596   Point3 *N;
597   ColorA *C;
598   int prev;
599   int du;
600   int i;
601   int has;
602   Appearance *ap;
603 
604 
605   if (nu <= 0 || nv <= 0)
606     return;
607 
608   ap = &_mgc->astk->ap;
609   if ((_mgc->astk->mat.override & MTF_DIFFUSE) &&
610       !(_mgc->astk->flags & MGASTK_SHADER))
611     meshC = 0;
612 
613   has = 0;
614   if (meshN && !(_mgc->astk->flags & MGASTK_SHADER))
615     has = HAS_N;
616   if (meshC)
617     has |= HAS_C;
618   if (IS_SMOOTH(ap->shading))
619     has |= HAS_SMOOTH;
620 
621   if ( ap->flag & (APF_FACEDRAW | APF_EDGEDRAW) ) /* BUG? */
622   {
623     if (!(has & HAS_C))
624       mgps_add(MGX_COLOR, 0, NULL, &ap->mat->diffuse);
625 
626     C2 = (ColorA *) &ap->mat->diffuse;
627 
628     v = vmax - vmin + 1;
629     du = umin + vmin * nu;
630 
631     if (wrap & MM_VWRAP)
632     {
633       prev = nu * (v - 1);
634     }
635     else
636     {
637       du += nu;
638       prev = -nu;
639       v--;
640     }
641 
642     do
643     {
644       P = meshP + du;
645       N = meshN + du;
646       C = meshC + du;
647       ucnt = umax - umin + 1;
648       mgpspolymeshrow(wrap, has, prev, ucnt, P,
649 			has & HAS_N ? N : NULL,
650 			has & HAS_C ? C : NULL,
651 			ap->flag, (float *)&ap->mat->edgecolor, (int)(v!=1));
652 
653       prev = -nu;
654       du += nu;
655     } while (--v > 0);
656   }
657 
658   if (ap->flag & APF_NORMALDRAW && meshN != NULL)
659   {
660     mgps_add(MGX_ECOLOR, 0, NULL, &ap->mat->normalcolor);
661 
662     if (_mgpsc->znudge)
663       mgps_closer();
664     for (i = nu*nv, P = meshP, N = meshN; --i >= 0; P++, N++)
665       mgps_drawnormal(P, N);
666     if (_mgpsc->znudge)
667       mgps_farther();
668   }
669 }
670 
671 /*-----------------------------------------------------------------------
672  * Function:	mgps_mesh
673  * Description:	draw a mesh
674  * Author:	Daeron Meyer
675  * Notes:	See mg.doc.
676  *
677  */
mgps_mesh(int wrap,int nu,int nv,HPoint3 * P,Point3 * N,Point3 * NQ,ColorA * C)678 void mgps_mesh(int wrap, int nu, int nv, HPoint3 *P, Point3 *N, Point3 *NQ,
679 	       ColorA *C )
680 {
681   mgpssubmesh( wrap, nu, nv, 0, nu-1, 0, nv-1, P, N, C);
682 }
683 
684 /*-----------------------------------------------------------------------*
685  * end of mesh drawing functions:					 *
686  *-----------------------------------------------------------------------*/
687 
688 /*
689  * Z-shift routines: for moving edges closer than faces, etc.
690  */
691 void
mgps_init_zrange()692 mgps_init_zrange()
693 {
694   _mgpsc->znudge = 1;
695   _mgpsc->znudgeby = 0.0;
696 }
697 
698 void
mgps_closer()699 mgps_closer()
700 {
701 /*  _mgpsc->znudgeby = 0.001; */
702 }
703 
704 void
mgps_farther()705 mgps_farther()
706 {
707   _mgpsc->znudgeby =  0.0;
708 }
709 
710 void
mgps_findcam()711 mgps_findcam()
712 {
713 }
714 
715 /* There is a basic problem now with 4-d points and 3-d normal vectors.
716 For now, we'll just ignore the 4-th coordinate of the point when
717 computing the tip of the normal vector.  This will work OK with all
718 existing models, but for genuine 4-d points it won't work.  But,
719 come to think of it, what is the correct interpretation of the
720 normal vector when the points live in 4-d?
721 */
722 void
mgps_drawnormal(HPoint3 * p,Point3 * n)723 mgps_drawnormal(HPoint3 *p, Point3 *n)
724 {
725   Point3 tp;
726   HPoint3 end;
727   Pt3Coord scale, w, s;
728 
729 /*  fprintf(stderr,"X11: draw a normal\n"); */
730   if (p->w <= 0.0) return;
731   if (p->w != 1) {
732     HPt3ToPt3(p, &tp);
733     p = (HPoint3 *)(void *)&tp;
734   }
735 
736   scale = _mgc->astk->ap.nscale;
737   if (_mgc->astk->ap.flag & APF_EVERT) {
738     HPoint3 *cp = &_mgc->cpos;
739     if (!(_mgc->has & HAS_CPOS)) {
740       mg_findcam();
741     }
742     if ((w = cp->w) != 1.0 && w != 0.0) {
743       s = (p->x*w-cp->x)*n->x + (p->y*w-cp->y)*n->y + (p->z*w-cp->z)*n->z;
744     } else {
745       s = (p->x-cp->x)*n->x + (p->y-cp->y)*n->y + (p->z-cp->z)*n->z;
746     }
747     if (s > 0) {
748       scale = -scale;
749     }
750   }
751   end.x = p->x + scale*n->x;
752   end.y = p->y + scale*n->y;
753   end.z = p->z + scale*n->z;
754   end.w = 1.0;
755   mgps_add(MGX_BGNLINE, 0, NULL, NULL);
756   mgps_add(MGX_VERTEX, 1, p, NULL);
757   mgps_add(MGX_VERTEX, 1, &end, NULL);
758   mgps_add(MGX_END, 0, NULL, NULL);
759 
760 }
761