1 /*
2  * Copyright (C) 1997-2005, R3vis Corporation.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17  * USA, or visit http://www.gnu.org/copyleft/lgpl.html.
18  *
19  * Original Contributor:
20  *   Wes Bethel, R3vis Corporation, Marin County, California
21  * Additional Contributor(s):
22  *
23  * The OpenRM project is located at http://openrm.sourceforge.net/.
24  */
25 /*
26  * $Id: rmdraw2.c,v 1.20 2005/07/02 17:48:45 wes Exp $
27  * Version: $Name: OpenRM-1-6-0-2-RC2 $
28  * $Revision: 1.20 $
29  * $Log: rmdraw2.c,v $
30  * Revision 1.20  2005/07/02 17:48:45  wes
31  * Updated rasterpos offset code for sprites to support 3D as well as 2D.
32  * Some minor z-coordinate buglets remain for 3D sprite positioning - see
33  * the comments in code for details.
34  *
35  * Revision 1.19  2005/06/26 18:50:11  wes
36  * Numerous updates:
37  * (1) Correct computation of viewport matrix, stuff into RMstate.
38  * (2) Refine code that repositions the glRasterPosition for RM_SPRITE primitives;
39  * 	works well in 2D, still needs a little help for 3D.
40  * (3) Update RM_SPRITE draw code to take into account text justification parms.
41  *
42  * Revision 1.18  2005/06/06 02:04:29  wes
43  * Lots of small additions to clean up compiler warnings.
44  *
45  * Revision 1.17  2005/05/28 16:25:57  wes
46  * Fixed bug where the pickable quad associated with bitmap-based
47  * primitives (RM_BITMAP, RM_TEXT, etc.) was incorrectly placed when
48  * text justification attributes RM_CENTER or RM_RIGHT were in effect.
49  *
50  * Revision 1.16  2005/05/16 01:01:37  wes
51  * Update some primitive draw routines to use private_rmSetGLTexCoordFunc
52  * to obtain the correct OpenGL texture coordinate function.
53  *
54  * Revision 1.15  2005/05/15 15:20:42  wes
55  * New internal routine to set the appropriate OpenGL texture coordinate function
56  * as a function of RMprimitive TC data characteristics.
57  *
58  * Revision 1.14  2005/05/06 16:35:26  wes
59  * Fixed buglet whereby prims specified with 0 verts would generate an
60  * incomplete OpenGL display list, thereby causing a domino-effect
61  * of errors.
62  *
63  * Revision 1.13  2005/03/16 16:43:17  wes
64  * Fixed a text rendering bug introduced during code merge.
65  *
66  * Revision 1.12  2005/02/27 19:34:04  wes
67  * Added support for application supplied texture object IDs and display lists.
68  *
69  * Revision 1.11  2005/02/19 16:23:56  wes
70  * Distro sync and consolidation.
71  * Added support for multitexturing.
72  *
73  * Revision 1.10  2005/02/12 00:54:50  wes
74  * Preliminary multitexturing support for RMprimitives: qmesh, quads, tstrip,
75  * triangles, and indexed triangles.
76  *
77  * Revision 1.9  2005/01/23 17:00:22  wes
78  * Copyright updated to 2005.
79  *
80  * Revision 1.8  2004/09/28 00:45:13  wes
81  * Modified rmQuads to support per-face colors and/or normals. Moved
82  * rmQuads from rmdraw1.c to rmdraw2.c
83  *
84  * Revision 1.7  2004/03/10 01:47:06  wes
85  * Added rendering code for RM_INDEXED_QUAD_STRIP prim type.
86  *
87  * Revision 1.6  2004/02/23 03:04:32  wes
88  * New primitives: RM_QUAD_STRIP, RM_INDEXED_TRIANGLES, RM_INDEXED_QUADS,
89  * RM_INDEXED_TRIANGLE_STRIP.
90  *
91  * Revision 1.5  2004/01/16 16:44:05  wes
92  * Updated copyright line for 2004.
93  *
94  * Revision 1.4  2003/10/03 19:21:17  wes
95  * Improved error checking and reporting in the rmText rendering function.
96  *
97  * Revision 1.3  2003/07/20 14:44:41  wes
98  * Modified some declarations for RM support routines to support per-line
99  * color in the disjoint lines primitives.
100  *
101  * Revision 1.2  2003/02/02 02:07:15  wes
102  * Updated copyright to 2003.
103  *
104  * Revision 1.1.1.1  2003/01/28 02:15:23  wes
105  * Manual rebuild of rm150 repository.
106  *
107  * Revision 1.17  2003/01/16 22:21:17  wes
108  * Updated all source files to reflect new organization of header files:
109  * all header files formerly located in include/rmaux, include/rmi, include/rmv
110  * are now located in include/rm.
111  *
112  * Revision 1.16  2002/12/02 16:24:56  wes
113  * Bug fixes:
114  * (1) fixed memory leak in rmPrimitiveSetText;
115  * (2) fixed problem with textProps not being applied to 2nd and later
116  * strings in an RM_TEXT text primitive.
117  *
118  * Revision 1.15  2002/11/14 15:34:51  wes
119  * Minor editing for beautification.
120  *
121  * Revision 1.14  2002/08/29 22:20:32  wes
122  *
123  * Massive upgrade to accommodate dynamic object reallocation within
124  * the component manager, and within the context cache. Use the
125  * debug #define DEBUG_LEVEL DEBUG_REALLOC_TRACE to get a printf
126  * whenever a realloc occurs. With this upgrade, there are no
127  * OpenRM limits on the size of the scene graph. There will be external
128  * limits, such as the amount of RAM and the amount of space available
129  * to your OpenGL implementation.
130  *
131  * Revision 1.13  2002/06/17 00:57:01  wes
132  * Fixed numerical problem related to calcuation of quad used when doing
133  * GL_SELECT on bitmaps, sprites and text. Condensed the code used to
134  * compute and draw those pickable quads; the new routines make use of
135  * the internal routine private_rmNewWCfromDCOffset rather than compute
136  * it separately. Added SHOW_PICKABLE_QUADS #define to draw the pickable
137  * quads during normal rendering for visual reality check.
138  *
139  * Revision 1.12  2002/06/02 15:14:18  wes
140  *
141  * Added RMstateCache code to help eliminate the number of state changes
142  * made during the render traversal. The RMstateCache tracks
143  * the actual OpenGL rendering state w/o the need for querying OpenGL
144  * directly, and  is queried by draw code that then decides if any
145  * real state changes are required given the configuration of data
146  * within an RMprimitive.
147  *
148  * Revision 1.11  2002/04/30 19:31:22  wes
149  * Fixed a bug in the display of indexed text/bitmap primitives.
150  *
151  * Revision 1.10  2001/10/15 00:04:53  wes
152  * Changed dispatching of characters in rmText from single char at a time
153  * to string at a time.  The older code had some debug stuff in it that
154  * checked the raster position after the glVertex2/3f() call, but before
155  * the glBitmap() call. That calling sequence seems to cause problems for
156  * Win32.
157  *
158  * Added an RMstate parm to the parm list for the setup funcs inside
159  * draw routines for lines, text and images. This will cause lighting
160  * to be enabled or disabled as a function of whether or not fogging
161  * is active. It would be nice if fogging could be enabled, but lighting
162  * disabled.
163  *
164  * Revision 1.9  2001/05/26 14:35:49  wes
165  * Added error checking code to rmSprite().
166  *
167  * Revision 1.8  2001/03/31 17:12:38  wes
168  * v1.4.0-alpha-2 checkin.
169  *
170  * Revision 1.7  2000/12/05 03:01:59  wes
171  * Fixed problem with rmText in which default text properties were
172  * malloc'ed, but never free'd.
173  *
174  * Revision 1.6  2000/12/03 22:34:37  wes
175  * Mods for thread safety- RMpipe added as parm to display list
176  * calls.
177  *
178  * Revision 1.5  2000/08/31 02:07:11  wes
179  * No significant changes.
180  *
181  * Revision 1.4  2000/08/23 23:24:21  wes
182  * DO_LISTS define moved from rmogl.c to rmprivat.h. All display
183  * list code removed from rmBitmap (will be reinserted later).
184  *
185  * Revision 1.3  2000/08/19 14:58:29  wes
186  * Culled unused code.
187  *
188  * Revision 1.2  2000/04/20 16:29:47  wes
189  * Documentation additions/enhancements, some code rearragement.
190  *
191  * Revision 1.1.1.1  2000/02/28 21:29:40  wes
192  * OpenRM 1.2 Checkin
193  *
194  * Revision 1.1.1.1  2000/02/28 17:18:48  wes
195  * Initial entry - pre-RM120 release, source base for OpenRM 1.2.
196  *
197  */
198 
199 #include <rm/rm.h>
200 #include "rmprivat.h"
201 #include "rmprivatps.h"
202 
203 /*
204  * 6/12/02 wes
205  * for debugging purposes, you can set SHOW_PICKABLE_QUADS to a
206  * non-zero value. this will cause the pickable quads associated with
207  * rmText, rmBitmap and rmSprite primitives to be drawn *in addition to*
208  * the source bitmap, text or sprite. usually, * these "helper" objects
209  * are not drawn except during selection mode.
210  */
211 #define SHOW_PICKABLE_QUADS 0
212 /*#define SHOW_PICKABLE_QUADS 1   */
213 
214 
215 /*
216  * this file contains RMprimitive "draw" routines for those
217  * primitives that DO NOT easily map to OpenGL vertex arrays.
218  */
219 
220 extern void rmuCone(void (*colorfunc)(const float *), float *color, RMvertex3D *p1, RMvertex3D *p2, float radius1 ,int subdivisions, RMpipe *p);
221 
222 /*
223  * Begin glVertex* and pals macro/function layer
224  *
225  * win-32 notes:
226  *
227  * un*x treats glVertex* and cousins as a normal function (pointer).
228  * therefore, it is possible to access those functions through a pointer.
229  * in MS VC, the glVertex* and pals have a verbose declaration which renders
230  * indirect access (via a pointer) next to impossible.
231  *
232  * in order to remedy this situation, we use either macros (UNIX) or
233  * a subroutine layer (win-32) to temporarily work around this problem.
234  *
235  */
236 
237 #ifdef RM_WIN
238 
239 void
rmglVertex3fv(const GLfloat * v)240 rmglVertex3fv (const GLfloat *v)
241 {
242    glVertex3fv(v);
243 }
244 
245 void
rmglVertex2fv(const GLfloat * v)246 rmglVertex2fv (const GLfloat *v)
247 {
248    glVertex2fv(v);
249 }
250 
251 void
rmglNormal3fv(const GLfloat * v)252 rmglNormal3fv (const GLfloat *v)
253 {
254    glNormal3fv(v);
255 }
256 
257 void
rmglColor3fv(const GLfloat * a)258 rmglColor3fv (const GLfloat *a)
259 {
260    glColor3fv(a);
261 }
262 
263 void
rmglColor4fv(const GLfloat * a)264 rmglColor4fv (const GLfloat *a)
265 {
266    glColor4fv(a);
267 }
268 
269 void
rmglRasterPos2fv(const GLfloat * v)270 rmglRasterPos2fv (const GLfloat *v)
271 {
272    glRasterPos2fv(v);
273 }
274 
275 void
rmglRasterPos3fv(const GLfloat * v)276 rmglRasterPos3fv (const GLfloat *v)
277 {
278    glRasterPos3fv(v);
279 }
280 
281 void
rmglTexCoord1fv(const GLfloat * v)282 rmglTexCoord1fv (const GLfloat *v)
283 {
284     glTexCoord1fv(v);
285 }
286 
287 void
rmglTexCoord2fv(const GLfloat * v)288 rmglTexCoord2fv (const GLfloat *v)
289 {
290     glTexCoord2fv(v);
291 }
292 
293 void
rmglTexCoord3fv(const GLfloat * v)294 rmglTexCoord3fv (const GLfloat *v)
295 {
296     glTexCoord3fv(v);
297 }
298 
299 #endif
300 
301 /* PRIVATE */
302 void
glNoOp(const float * f)303 glNoOp (const float *f)
304 {
305     /* do nothing */
306     f = NULL; 			/* foil compiler warning */
307 }
308 
309 
310 /* PRIVATE */
311 void
private_rmSetGLColorFunc(int cvecsize,int ncolors,void (** cfuncptr)(const float *))312 private_rmSetGLColorFunc (int cvecsize,
313 			  int ncolors,
314 			  void (**cfuncptr)(const float *))
315 {
316     /* set OpenGL color routine as a function of the  color vector length */
317     if (ncolors == 0 || cvecsize == 0)
318 	*cfuncptr = glNoOp;
319     else
320     {
321 	if (cvecsize == 3)
322 	    *cfuncptr = rmglColor3fv;
323 	else
324 	{
325 	    if (cvecsize == 4)
326 		*cfuncptr = rmglColor4fv;
327 	    else
328 		*cfuncptr = glNoOp; /* warning? */
329 	}
330     }
331 }
332 
333 /* PRIVATE */
334 void
private_rmSetGLTexCoordFunc(int tcvecsize,int ntc,void (** tcfuncptr)(const float *))335 private_rmSetGLTexCoordFunc (int tcvecsize,
336 			     int ntc,
337 			     void (**tcfuncptr)(const float *))
338 {
339     /* set OpenGL texture coord routine as a function of tc vector length */
340     if (ntc == 0 || tcvecsize == 0)
341 	*tcfuncptr = glNoOp;
342     else
343     {
344 	switch(tcvecsize)
345         {
346 	case 2:
347 	    *tcfuncptr = rmglTexCoord2fv;
348 	    break;
349 	case 3:
350 	    *tcfuncptr = rmglTexCoord3fv;
351 	    break;
352 	case 1:
353 	    *tcfuncptr = rmglTexCoord1fv;
354 	    break;
355 	default:
356 	    rmError("private_rmSetGLTexCoordFunc error: input tcveclen != 1,2, or 3 yet ntc != 0. Please file a bug report. ");
357 	    break;
358 	}
359     }
360 }
361 
362 
363 /* PRIVATE */
364 void
private_rmStateGetTextJustify(const RMstate * s,RMenum * hjustify,RMenum * vjustify)365 private_rmStateGetTextJustify (const RMstate *s,
366 			       RMenum *hjustify,
367 			       RMenum *vjustify)
368 {
369     extern RMenum RM_DEFAULT_HJUSTIFY, RM_DEFAULT_VJUSTIFY;
370 
371     if (s->textProps == NULL)
372     {
373 	*hjustify = RM_DEFAULT_HJUSTIFY;
374 	*vjustify = RM_DEFAULT_VJUSTIFY;
375     }
376     else
377     {
378 	*hjustify = s->textProps->hJustify;
379 	*vjustify = s->textProps->vJustify;
380     }
381 }
382 
383 
384 /* precomputed trig tables */
385 #define TRIG_RES 360
386 double cos_table[TRIG_RES], sin_table[TRIG_RES];
387 
388 /* PRIVATE */
389 void
private_initTrigTables(void)390 private_initTrigTables (void)
391 {
392     int    i;
393     double t, dt;
394 
395     t = 0.0;
396     dt = RM_TWO_PI / (double)TRIG_RES;
397 
398     for (i = 0; i < TRIG_RES; i++, t += dt)
399     {
400 	cos_table[i] = cos(t);
401 	sin_table[i] = sin(t);
402     }
403 }
404 
405 
406 /* PRIVATE */
407 static void
rmuCircle2d(int subdivisions)408 rmuCircle2d (int subdivisions)
409 {
410     int   i;
411     float t, dt;
412     float v[2];
413 
414     /* draw a unit convex polygon at (0,0) */
415     if (subdivisions > TRIG_RES)
416 	subdivisions = TRIG_RES;
417 
418     t = 0.0;
419     dt = (float)(TRIG_RES) / (float)(subdivisions);
420 
421     glBegin(GL_POLYGON);
422     for (i = 0; i < subdivisions; i++, t += dt)
423     {
424 	v[0] = cos_table[(int)t];
425 	v[1] = sin_table[(int)t];
426 	glVertex2fv(v);
427     }
428     glEnd();
429 }
430 
431 
432 /* PRIVATE */
433 static void
rmuEllipse2d(int subdivisions,float a,float b)434 rmuEllipse2d (int subdivisions,
435 	      float a,		/* vertical scale */
436 	      float b)		/* horizontal scale */
437 {
438     int   i;
439     float t, dt;
440     float v[2];
441 
442     /* draw a unit convex polygon at (0,0) with the desired scaling */
443     if (subdivisions > TRIG_RES)
444 	subdivisions = TRIG_RES;
445 
446     t = 0.0;
447     dt = (float)(TRIG_RES) / (float)(subdivisions);
448 
449     glBegin(GL_POLYGON);
450     for (i = 0; i < subdivisions; i++, t += dt)
451     {
452 	v[0] = cos_table[(int)t] * b;
453 	v[1] = sin_table[(int)t] * a;
454 	glVertex2fv(v);
455     }
456     glEnd();
457 }
458 
459 /* PRIVATE */
460 static void
private_rmSetupBitmapPickMatrices(RMstate * s,RMmatrix * vpm,RMmatrix * vpm_inv,RMmatrix * forward,RMmatrix * inv)461 private_rmSetupBitmapPickMatrices (RMstate *s,
462 				   RMmatrix *vpm,
463 				   RMmatrix *vpm_inv,
464 				   RMmatrix *forward,
465 				   RMmatrix *inv)
466 {
467     RMmatrix m;
468 
469     rmMatrixIdentity(vpm);
470 
471     private_rmComputeViewportMatrix(s->vp, (float)s->w, (float)s->h, vpm);
472 
473     rmMatrixInverse(vpm, vpm_inv);
474 
475     rmMatrixMultiply(&(s->modelView), &(s->projection), &m);
476     *forward = m;
477 
478     rmMatrixInverse(&m, inv);
479 }
480 
481 /* PRIVATE */
482 static void
private_rmDrawBitmapPickableQuads(RMmatrix * vpm,RMmatrix * vpm_invOrig,RMmatrix * forwardOrig,RMmatrix * inv,RMvertex3D * v,int horigin,int vorigin,int bitmap_width,int bitmap_height)483 private_rmDrawBitmapPickableQuads (RMmatrix *vpm,
484 				   RMmatrix *vpm_invOrig,
485 				   RMmatrix *forwardOrig,
486 				   RMmatrix *inv,
487 				   RMvertex3D *v,
488 				   int horigin,
489 				   int vorigin,
490 				   int bitmap_width,
491 				   int bitmap_height)
492 {
493     RMvertex3D vnew[4];
494 
495     private_rmNewWCfromDCOffset(v, -horigin, -vorigin, vnew,
496 				vpm, vpm_invOrig, forwardOrig, inv);
497     private_rmNewWCfromDCOffset(v, bitmap_width-horigin, -vorigin, vnew+1,
498 				vpm, vpm_invOrig, forwardOrig, inv);
499     private_rmNewWCfromDCOffset(v, bitmap_width-horigin, bitmap_height-vorigin, vnew+2,
500 				vpm, vpm_invOrig, forwardOrig, inv);
501     private_rmNewWCfromDCOffset(v, -horigin, bitmap_height-vorigin, vnew+3,
502 				vpm, vpm_invOrig, forwardOrig, inv);
503 
504     glBegin(GL_QUADS);
505     glVertex3fv((float *)(vnew));
506     glVertex3fv((float *)(vnew+1));
507     glVertex3fv((float *)(vnew+2));
508     glVertex3fv((float *)(vnew+3));
509     glEnd();
510 }
511 
512 /* PRIVATE
513  * draw routine for the app-provided display list primitive
514  */
515 void
OGLPRIMPARMLIST()516 rmAppDisplayList OGLPRIMPARMLIST()
517 {
518 
519 #if (DEBUG_LEVEL & DEBUG_GLERRORCHECK)
520     rmGLGetError("rmAppDisplayList() - before calling app display list");
521 #endif
522 
523     glCallList(p->flags1);
524 
525     /* foil compiler warning */
526     r = NULL;
527     s = NULL;
528     renderPipe = NULL;
529     rsc = NULL;
530 
531 #if (DEBUG_LEVEL & DEBUG_GLERRORCHECK)
532     rmGLGetError("rmAppDisplayList() - after calling app display list");
533 #endif
534 }
535 
536 /* PRIVATE
537  *
538  * draw routine for quadmesh routines
539  */
540 void
OGLPRIMPARMLIST()541 rmQuadmesh OGLPRIMPARMLIST()
542 {
543     float *nrow0=NULL, *nrow1=NULL;
544     float *vrow0=NULL, *vrow1=NULL;
545     float *crow0=NULL, *crow1=NULL;
546     float *tcrow0 = NULL, *tcrow1 = NULL;
547     int    usize, vsize;
548     int   *dims;
549     int    iv, iu;
550 
551     /* for verts */
552     float *v;
553     int    vstride, nverts, vveclen;
554 
555     /* color data */
556     float *c = NULL;
557     int    cstride, ncolors, cveclen;
558 
559     /* texture coord data */
560     float *tc = NULL;
561     int    tcstride;
562     int    ntc, tcveclen;
563 
564     /* normals */
565     float *n;
566     int    nstride, nveclen, nnormals;
567     int    listStat;
568 
569     /* vertex, normal, color, tc functions */
570     void (*vertexfunc)(const float *);
571     void (*normalfunc)(const float *);
572     void (*colorfunc)(const float *);
573     void (*tcfunc)(const float *);
574 
575     int haveMTCs = 0;
576 
577 #if (DEBUG_LEVEL & DEBUG_GLSTATECHECK)
578     private_glStateCheck(s);
579 #endif
580 
581     private_colorMaterialStateManip(p, s, rsc);
582     private_lightingStateManip(p, s, rsc, RM_FALSE);
583 
584     listStat = private_rmPrimitiveDisplayListBegin(renderPipe, p);
585     if (listStat == 0)
586 	return;
587 
588     r = NULL; 			/* foil compile warning */
589 
590     /* get vertex data */
591     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
592 
593     /* get color data */
594     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
595 
596     /* get texture coord data  */
597     private_rmGetBlobData(BLOB_TC_INDEX, p, &tcstride, &ntc, (void **)&tc, &tcveclen);
598 
599     /* get normals info */
600     private_rmGetBlobData(BLOB_NORMAL_INDEX, p, &nstride, &nnormals, (void **)&n, &nveclen);
601 
602     /* get the size info for the qmesh */
603     private_rmGetBlobData(BLOB_QMESHDIMS_INDEX, p, NULL, NULL, (void *)&dims, NULL);
604 
605     if (p->multiTextureCoordBlobsMask != 0)
606 	haveMTCs = 1;
607 
608     vrow0 = v;
609     nrow0 = n;
610     crow0 = c;
611     tcrow0 = tc;
612 
613     usize = dims[0];
614     vsize = dims[1];
615 
616     if (vveclen == 3)
617         vertexfunc = rmglVertex3fv;
618     else
619         vertexfunc = rmglVertex2fv;
620     vrow1 = vrow0 + usize*vstride;
621 
622     if (nrow0 != NULL)
623     {
624 	nrow1 = nrow0 + usize*nstride;
625 	normalfunc = rmglNormal3fv;
626     }
627     else
628     {
629 	nrow0 = nrow1 = NULL;
630 	normalfunc = glNoOp;
631     }
632 
633     if ((ncolors != usize*vsize) && (cstride != 0))
634     {
635 	rmWarning(" only per-vertex colors are supported with the quadmesh. use quads as an alternative. drawing the quadmesh without colors.");
636 	cstride = 0;
637 	colorfunc = glNoOp;
638     }
639     else
640     {
641 	private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
642 	crow1 = crow0 + (usize * cstride);
643     }
644 
645     if (ntc == 0)
646 	tcfunc = glNoOp;
647     else
648 	private_rmSetGLTexCoordFunc(tcveclen, ntc, &tcfunc);
649 
650     tcrow1 = tcrow0 + (usize * tcstride);
651 
652     for (iv = 0; iv < (vsize - 1); iv++)
653     {
654 	glBegin(GL_QUAD_STRIP);
655 
656 	for (iu = 0; iu < usize; iu++)
657         {
658 	    (*colorfunc)((float *)(crow1 + (iu * cstride)));
659 	    (*tcfunc)((float *)(tcrow1 + (iu * tcstride)));
660 	    (*normalfunc)((float *)(nrow1 + (iu * nstride)));
661 	    if (haveMTCs)
662 		private_dispatchMTCs(renderPipe, p, (iv+1) * usize + iu);
663 
664 	    (*vertexfunc)((float *)(vrow1 + (iu * vstride)));
665 
666 	    (*colorfunc)((float *)(crow0 + (iu * cstride)));
667 	    (*tcfunc)((float *)(tcrow0 + (iu * tcstride)));
668 	    (*normalfunc)((float *)(nrow0 + (iu * nstride)));
669 
670 	    if (haveMTCs)
671 		private_dispatchMTCs(renderPipe, p, iv * usize + iu);
672 
673 	    (*vertexfunc)((float *)(vrow0 + (iu * vstride)));
674 	}
675 
676 	glEnd();
677 
678 	vrow0 = vrow1;
679 	vrow1 += usize * vstride;
680 
681 	nrow0 = nrow1;
682 	nrow1 += usize * nstride;
683 
684 	crow0 = crow1;
685 	crow1 += usize * cstride;
686 
687 	tcrow0 = tcrow1;
688 	tcrow1 += usize * tcstride;
689     }
690     private_rmPrimitiveDisplayListEnd(renderPipe, p, listStat);
691 }
692 
693 
694 /* PRIVATE */
695 void
OGLPRIMPARMLIST()696 rmSpheres OGLPRIMPARMLIST()
697 {
698     /* for verts */
699     float *v;
700     int    vstride, nverts, vveclen;
701 
702     /* color data */
703     float *c = NULL;
704     int    cstride, ncolors, cveclen;
705 
706     /* radius data */
707     float *radii = NULL;
708     int    rstride, nradii, rveclen;
709 
710     int    i, listStat;
711     void (*vertexfunc)(const float *), (*colorfunc)(const float *);
712     float  dummy_radius = 0.0;
713 
714     private_lightingStateManip(p, s, rsc, RM_TRUE);
715     private_colorMaterialStateManip(p, s, rsc);
716 
717     listStat = private_rmPrimitiveDisplayListBegin(renderPipe, p);
718     if (listStat == 0)
719 	return;
720 
721     r = NULL; 			/* foil compiler warning */
722 
723     /* get vertex data */
724     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
725 
726     /* get color data */
727     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
728 
729     /* get radius data */
730     private_rmGetBlobData(BLOB_SCALE_INDEX, p, &rstride, &nradii, (void **)&radii, &rveclen);
731 
732     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
733 
734     if (vveclen == 3)
735         vertexfunc = rmglVertex3fv;
736     else if (vveclen == 2)
737         vertexfunc = rmglVertex2fv;
738 
739     if (nradii == 0)
740     {
741 	radii = &dummy_radius;
742 	rstride = 0;
743     }
744 
745     for (i = 0; i < nverts; i++, v += vstride, radii += rstride, c += cstride)
746     {
747 	void rmuSphere(void (*colorfunc) (const float *), float *color, RMvertex3D *p1, float radius,  int model_switch, RMpipe *p);
748 
749 	if (*radii != 0.0F)
750 	{
751 #if 0
752 	    /* tmp hack to test improved rendering when transparent.  */
753 	    /* this actually works surprisingly well..need to promote
754 	     this approach to a higher level. */
755 
756 	    if (s->renderpass == RM_RENDERPASS_TRANSPARENT)
757 	    {
758 		glEnable(GL_CULL_FACE);
759 		glCullFace(GL_FRONT);
760 		rmuSphere(colorfunc, c, (RMvertex3D *)v, *radii,
761 			  rmPrimitiveGetModelFlag(p), renderPipe);
762 		glCullFace(GL_BACK);
763 		rmuSphere(colorfunc, c, (RMvertex3D *)v, *radii,
764 			  rmPrimitiveGetModelFlag(p), renderPipe);
765 		glDisable(GL_CULL_FACE);
766 	    }
767 	    else
768 #endif
769 	    rmuSphere(colorfunc, c, (RMvertex3D *)v, *radii,
770 		      rmPrimitiveGetModelFlag(p), renderPipe);
771 	}
772 	else
773 	{
774 	    /* we should be able to detect that the radius values
775 	       for the entire prim are null and to deal with them differently
776 	       (more efficiently) than doing them one-by-one here. */
777 
778 	    glBegin(GL_POINTS);
779 	    (*colorfunc)(c);
780 	    (*vertexfunc)(v);
781 	    glEnd();
782 	}
783     }
784     private_rmPrimitiveDisplayListEnd(renderPipe, p, listStat);
785 }
786 
787 
788 /* PRIVATE */
789 void
OGLPRIMPARMLIST()790 rmCones OGLPRIMPARMLIST()
791 {
792     /* for verts */
793     int    vstride, nverts, vveclen;
794     float *v;
795 
796     /* color data */
797     int    cstride, ncolors, cveclen;
798     float *c = NULL;
799 
800     /* radius data */
801     int    rstride, nradii, rveclen;
802     float *radii = NULL;
803 
804     /* cones */
805     int    i, ncones, listStat;
806     float  dummy_radius = 0.0;
807     void (*vertexfunc)(const float *), (*colorfunc)(const float *);
808 
809     private_lightingStateManip(p, s, rsc, RM_TRUE);
810     private_colorMaterialStateManip(p, s, rsc);
811 
812     listStat = private_rmPrimitiveDisplayListBegin(renderPipe, p);
813     if (listStat == 0)
814 	return;
815 
816     r = NULL;			/* foil compiler warning */
817 
818     /* get vertex data */
819     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
820 
821     ncones = nverts >> 1;	/* each vertex pair defines a cone (base,top) */
822     /* get color data */
823     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
824 
825     /* get radius data */
826     private_rmGetBlobData(BLOB_SCALE_INDEX, p, &rstride, &nradii, (void **)&radii, &rveclen);
827 
828     if (vveclen == 3)
829         vertexfunc = rmglVertex3fv;
830     else
831         vertexfunc = rmglVertex2fv;
832 
833     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
834 
835     if (radii == NULL)
836     {
837         dummy_radius = 0.0;
838 	radii = &dummy_radius;
839 	rstride = 0;
840     }
841 
842     for (i = 0; i < ncones; i++, v += 2 * vstride, c += cstride, radii += rstride)
843     {
844 	RMvertex3D *p1, *p2;
845 
846 	p1 = (RMvertex3D *)v;
847 	p2 = (RMvertex3D *)(v + vstride);
848 
849 	rmuCone(colorfunc, c, p1, p2, *radii, rmPrimitiveGetModelFlag(p), renderPipe);
850     }
851     private_rmPrimitiveDisplayListEnd(renderPipe, p, listStat);
852 }
853 
854 
855 /* PRIVATE */
856 void
OGLPRIMPARMLIST()857 rmCylinders OGLPRIMPARMLIST()
858 {
859     /* for verts */
860     float *v;
861     int    vstride, nverts, vveclen;
862 
863     /* color data */
864     float *c = NULL;
865     int    cstride, ncolors, cveclen;
866 
867     /* radius data */
868     float *radii = NULL;
869     int    rstride, nradii, rveclen;
870 
871     int    i, listStat, ncylinders;
872     void (*colorfunc)(const float *);
873     float  dummy_radius;
874 
875     private_lightingStateManip(p, s, rsc, RM_TRUE);
876     private_colorMaterialStateManip(p, s, rsc);
877 
878     listStat = private_rmPrimitiveDisplayListBegin(renderPipe, p);
879     if (listStat == 0)
880 	return;
881 
882     r = NULL; 			/* foil compiler warning */
883 
884     /* get vertex data */
885     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
886 
887     ncylinders = nverts >> 1;	/* each vertex pair defines a cone (base,top) */
888 
889     /* get color data */
890     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
891 
892     /* get radius data */
893     private_rmGetBlobData(BLOB_SCALE_INDEX, p, &rstride, &nradii, (void **)&radii, &rveclen);
894 
895     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
896 
897     /* for now, assume 1 radius value per cylinder..so that they're
898      straight (non-tapered) cylinders. also, we assume the layout of
899      vertices is like that of disjoint lines..so that if we have
900      n vertices, we'll render n/2 cylinders. */
901 
902     if (radii == NULL)
903     {
904         dummy_radius = 0.;
905 	radii = &dummy_radius;
906 	rstride = 0;
907     }
908 
909     for (i = 0; i < ncylinders; i++, v += 2 * vstride, c += cstride, radii += rstride)
910     {
911 	RMvertex3D *p1, *p2;
912 
913 	void rmuCylinder(void (*colorfunc)(const float *), float *color, RMvertex3D *p1, RMvertex3D *p2,float radius1, int subdivisions, RMpipe *p);
914 
915 	p1 = (RMvertex3D *)v;
916 	p2 = (RMvertex3D *)(v + vstride);
917 
918 	rmuCylinder(colorfunc, c, p1, p2, *radii, rmPrimitiveGetModelFlag(p), renderPipe);
919     }
920     private_rmPrimitiveDisplayListEnd(renderPipe, p, listStat);
921 }
922 
923 
924 /* PRIVATE */
925 void
OGLPRIMPARMLIST()926 rmMarkers2D OGLPRIMPARMLIST()
927 {
928     /* for verts */
929     float *v;
930     int    vstride, nverts, vveclen;
931 
932     /* color data */
933     float *c = NULL;
934     int    cstride, ncolors, cveclen;
935 
936     /* scale data */
937     float *scales;
938     int    sstride, nscales, sveclen;
939 
940     int    i, j;
941     void (*vertexfunc)(const float *), (*colorfunc)(const float *);
942 
943     RMinternalMarker2D *m;
944     int                 nmarker_prims;
945     RMmatrix            mx;
946 
947     float m00, m10, m01, m11, m30, m31;
948 
949     /*
950      * 5/11/02
951      * this code not yet tested - no demo programs that exercise 2d markers.
952      */
953     private_colorMaterialStateManip(p, s, rsc);
954     private_lightingStateManip(p, s, rsc, RM_FALSE);
955 
956     /* get vertex data */
957     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
958     if (nverts == 0)
959 	return;
960 
961     r = NULL;  		/* foil compiler warning */
962     renderPipe = NULL; 		/* foil compiler warning */
963 
964     /* get color data */
965     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
966 
967     /* get radius data */
968     private_rmGetBlobData(BLOB_SCALE_INDEX, p, &sstride, &nscales, (void **)&scales, &sveclen);
969 
970     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
971 
972     /* we could check to make sure only 2d vertices are permitted here... */
973     if (vveclen == 3)
974         vertexfunc = rmglVertex3fv;
975     else
976         vertexfunc = rmglVertex2fv;
977 
978     private_rmPrimitiveGetItem(p, RM_PRIMITIVE_MARKERS2D_PRIM, &nmarker_prims, (void **)&m);
979     rmMatrixIdentity(&mx);
980 
981     /* need to use render state interface here. */
982     {
983 	RMmatrix m;
984 	rmMatrixMultiply(&(s->modelView), &(s->projection), &m);
985 	rmMatrixInverse(&m, &m);
986 
987 	mx.m[0][0] = 1. / m.m[1][1];
988 	mx.m[1][1] = s->aspect_ratio / m.m[0][0];
989     }
990 
991     m00 = s->model.m[0][0];
992     m10 = s->model.m[1][0];
993     m01 = s->model.m[0][1];
994     m11 = s->model.m[1][1];
995     m30 = s->model.m[3][0];
996     m31 = s->model.m[3][1];
997 
998     if (nmarker_prims != 1)
999     {
1000 	rmWarning("rmMarkers2D() error: at this time, only one markerprim per RMprimitive is permitted. This restriction will be removed in a future release. Drawing only the first one.");
1001     }
1002 
1003     /* temp - we assume that nmarker_prims == 1. */
1004     for (i = 0; i < nverts; i++, v += vstride, c += cstride, scales += sstride)
1005     {
1006         float *v2, v3[3];
1007 
1008         glPushMatrix();
1009 
1010 	/* translate to the proper x/y location. this translation
1011 	 accounts for scale, etc in the model-view-projection matrix.
1012 	 the markers
1013 	 will be positioned correctly, but will be rotation-invariant. */
1014 
1015 	mx.m[3][0] = v[0] * m00 + v[1] * m10 + m30;
1016 	mx.m[3][1] = v[0] * m01 + v[1] * m11 + m31;
1017 
1018 	glMultMatrixf(&(mx.m[0][0]));
1019 
1020 	(*colorfunc)(c);
1021 
1022 	v2 = (float *)(rmInternalMarker2DGetVerts(m));
1023 
1024 	glBegin( rmInternalMarker2DGetBFlag(m) );
1025 
1026 	for (j = 0; j < rmInternalMarker2DGetNpts(m); j++, v2 += 2)
1027         {
1028 	    v3[0] = v2[0] * *scales ;
1029 	    v3[1] = v2[1] * *scales ;
1030 	    (*vertexfunc)(v3);
1031 	}
1032 	glEnd();
1033 
1034 	glPopMatrix();
1035     }
1036 }
1037 
1038 
1039 /* unit cube geometry */
1040 static RMvertex3D ibox[6][4] =
1041 {
1042     {{1.0, 0.0, 0.0}, {1.0, 0.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 1.0, 0.0}}, /* +x face */
1043     {{0.0, 0.0, 1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 1.0, 1.0}}, /* -x face */
1044     {{0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}, {1.0, 1.0, 1.0}, {0.0, 1.0, 1.0}}, /* +y face */
1045     {{0.0, 0.0, 1.0}, {1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}, /* -y face */
1046     {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}}, /* front face */
1047     {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, {0.0, 1.0, 1.0}, {1.0, 1.0, 1.0}}  /* back face */
1048 };
1049 
1050 /* unit cube normals */
1051 static RMvertex3D iboxnorms[6] =
1052 {
1053     {1.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, -1.0}, {0.0, 0.0, 1.0}
1054 };
1055 
1056 
1057 /* PRIVATE */
1058 void
OGLPRIMPARMLIST()1059 rmBox3d OGLPRIMPARMLIST()
1060 {
1061     /* for verts */
1062     float *v;
1063     int    vstride, nverts, vveclen;
1064 
1065     /* color data */
1066     float *c = NULL;
1067     int    cstride, ncolors, cveclen;
1068 
1069     int         i, j, k, listStat;
1070     void      (*vertexfunc)(const float *), (*colorfunc)(const float *);
1071     RMvertex3D *rv;
1072     RMvertex3D  tbox[6][4];
1073 
1074     private_lightingStateManip(p, s, rsc, RM_TRUE);
1075     private_colorMaterialStateManip(p, s, rsc);
1076     private_textureStateManip(p, s, rsc);
1077 
1078     listStat = private_rmPrimitiveDisplayListBegin(renderPipe, p);
1079     if (listStat == 0)
1080 	return;
1081 
1082     r = NULL; 			/* foil compiler warning */
1083 
1084     /* get vertex data */
1085     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
1086 
1087     /* get color data */
1088     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
1089 
1090     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
1091 
1092     if (vveclen == 3)
1093 	vertexfunc = rmglVertex3fv;
1094     else /* an error */
1095     {
1096 	rmError("rmBox3D() error: box3d primitives MUST have 3d vertices. \n");
1097 	return;
1098     }
1099 
1100     rv = (RMvertex3D *)v;
1101 
1102     for (i = 0; i < (nverts / 2); i++, rv += 2, c += cstride)
1103     {
1104 	float sx, sy, sz;
1105 
1106 	sx = rv[1].x - rv[0].x;
1107 	sy = rv[1].y - rv[0].y;
1108 	sz = rv[1].z - rv[0].z;
1109 
1110 	for (k = 0; k < 6; k++)
1111 	{
1112 	    for (j = 0; j < 4; j++)
1113 	    {
1114 		tbox[k][j].x = ibox[k][j].x * sx;
1115 		tbox[k][j].y = ibox[k][j].y * sy;
1116 		tbox[k][j].z = ibox[k][j].z * sz;
1117 	    }
1118 	}
1119 
1120 	glPushMatrix();
1121 	glTranslatef(rv->x,rv->y,rv->z); /* won't work with 2d vertices */
1122 
1123 	glBegin(GL_QUADS);
1124 	(*colorfunc)(c);
1125 	for (j = 0; j < 6; j++)
1126 	{
1127 /*	    glColor3fv((float *)&(debug_colors[j]));  */ /* debug */
1128 	    glNormal3fv((float *)&(iboxnorms[j]));
1129 	    for (k = 3; k >= 0; k--)
1130 	    {
1131 		(*vertexfunc)((float *)&(tbox[j][k]));
1132 	    }
1133 	}
1134 	glEnd();
1135 
1136 	glPopMatrix();
1137     }
1138     private_rmPrimitiveDisplayListEnd(renderPipe, p, listStat);
1139 }
1140 
1141 
1142 /* PRIVATE */
1143 void
OGLPRIMPARMLIST()1144 rmBox3dWire OGLPRIMPARMLIST()
1145 {
1146     /* for verts */
1147     int    vstride, nverts, vveclen;
1148     float *v;
1149 
1150     /* color data */
1151     int    cstride, ncolors, cveclen;
1152     float *c = NULL;
1153 
1154     /* box */
1155     int         i, listStat;
1156     RMvertex3D *rv;
1157     void      (*vertexfunc)(const float *), (*colorfunc)(const float *);
1158 
1159     private_colorMaterialStateManip(p, s, rsc);
1160     private_lightingStateManip(p, s, rsc, RM_FALSE);
1161     private_textureStateManip(p, s, rsc);
1162 
1163     listStat = private_rmPrimitiveDisplayListBegin(renderPipe, p);
1164     if (listStat == 0)
1165 	return;
1166 
1167     r = NULL; 			/* foil compiler warning */
1168 
1169     /* vertex data */
1170     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
1171 
1172     /* get color data */
1173     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
1174 
1175     private_rmSetGLColorFunc(cveclen,ncolors, &colorfunc);
1176 
1177     if (vveclen == 3)
1178 	vertexfunc = rmglVertex3fv;
1179     else /* an error */
1180     {
1181 	rmError("rmBox3DWire() error: box3dwire primitives MUST have 3d vertices. \n");
1182 	return;
1183     }
1184 
1185     rv = (RMvertex3D *)v;
1186 
1187     for (i = 0; i < (nverts / 2); i++, rv += 2, c += cstride)
1188     {
1189 	float sx, sy, sz;
1190 
1191 	sx = rv[1].x - rv[0].x;
1192 	sy = rv[1].y - rv[0].y;
1193 	sz = rv[1].z - rv[0].z;
1194 
1195 	glPushMatrix();
1196 	glTranslatef(rv->x, rv->y, rv->z); /* won't work with 2d vertices */
1197 
1198 	glBegin(GL_LINE_STRIP);
1199 	(*colorfunc)(c);
1200 
1201 	glVertex3f(0.0F, 0.0F ,0.0F);
1202 	glVertex3f(sx, 0.0F, 0.0F);
1203 	glVertex3f(sx, sy, 0.0F);
1204 	glVertex3f(0.0F, sy, 0.0F);
1205 
1206 	glVertex3f(0.0F, 0.0F, 0.0F);
1207 	glVertex3f(0.0F, 0.0F, sz);
1208 	glVertex3f(0.0F, sy, sz);
1209 	glVertex3f(0.0F, sy, 0.0F);
1210 
1211 	glVertex3f(0.0F, sy, sz);
1212 	glVertex3f(sx, sy, sz);
1213 	glVertex3f(sx, sy, 0.0F);
1214 	glVertex3f(sx, 0.0F, 0.0F);
1215 
1216 	glVertex3f(sx, 0.0F, sz);
1217 	glVertex3f(sx, sy, sz);
1218 	glVertex3f(sx, 0.0F, sz);
1219 	glVertex3f(0.0F, 0.0F, sz);
1220 
1221 	glEnd();
1222 
1223 	glPopMatrix();
1224     }
1225     private_rmPrimitiveDisplayListEnd(renderPipe, p, listStat);
1226 }
1227 
1228 
1229 /* PRIVATE */
1230 void
OGLPRIMPARMLIST()1231 rmCircle2d OGLPRIMPARMLIST()
1232 {
1233     /*
1234      * TODO: 12/5/99
1235      * circles need to have display-list code added.
1236      *
1237      * ------ general info
1238      * for each of verts, color &  texture, we need
1239      * 1. stride, for memory accessing
1240      * 2. veclen, for proper gl function call
1241      *
1242      * the main delivery loop is over vertices. we check the number of
1243      * colors, norms & textures to ensure that we have either none or
1244      * per-vertex of each.
1245      */
1246     int    i;
1247     void (*colorfunc)(const float *);
1248     float  dummy = 1.0, scale;
1249 
1250     /* for verts */
1251     float *v;
1252     int    vstride, nverts, vveclen;
1253 
1254     /* color data */
1255     float *c = NULL;
1256     int    cstride, ncolors, cveclen;
1257 
1258     /* for radius data */
1259     float *radii= NULL;
1260     int    rstride, rveclen, nradii;
1261 
1262     RMmatrix m;
1263 
1264     private_colorMaterialStateManip(p, s, rsc);
1265     private_lightingStateManip(p, s, rsc, RM_FALSE);
1266 
1267     /* get vertex data */
1268     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
1269 
1270     /* get color data */
1271     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
1272 
1273     /* get radius info */
1274     private_rmGetBlobData(BLOB_SCALE_INDEX, p, &rstride, &nradii, (void **)&radii, &rveclen);
1275     if (radii == NULL)
1276     {
1277 	radii = &dummy;
1278 	rstride = 0;
1279 	nradii = 0;
1280     }
1281 
1282     /*
1283      * do validity checking:
1284      * 1. ncolors must be 0 or equal to nverts/2
1285      * 2. ntcoords must be 0 or equal to nverts/2
1286      */
1287     if (ncolors != 0 && ncolors != nverts)
1288     {
1289 	rmError("error: rmCircle2D() only per-circle color is supported. \n");
1290 	return;
1291     }
1292 
1293     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
1294 
1295     rmMatrixMultiply(&(s->model), &(s->projection), &m);
1296     rmMatrixMultiply(&m, &(s->vpm), &m);
1297 
1298     scale = RM_MIN(m.m[0][0], m.m[1][1]);
1299 
1300     for (i = 0; i < nverts; i++, v += vstride, c+= cstride, radii += rstride)
1301     {
1302 	int      subdivisions = 9;
1303 	RMmatrix m;
1304 
1305         glPushMatrix();
1306 	rmMatrixIdentity(&m);
1307 
1308 	m.m[0][0] = m.m[1][1] = m.m[2][2] = *radii;
1309 	m.m[3][0] = v[0];
1310 	m.m[3][1] = v[1];
1311 	m.m[3][2] = 0.0F;
1312 	glMultMatrixf((const GLfloat *)&(m.m[0][0]));
1313 	(*colorfunc)(c);
1314 
1315 	subdivisions = *radii * scale; /* this formulation results in line segments which are about 3 pixels long */
1316 
1317 	    rmuCircle2d(subdivisions);
1318 
1319 	glPopMatrix();
1320     }
1321     r = NULL; 			/* foil compiler warning */
1322     renderPipe = NULL; 		/* foil compiler warning */
1323 }
1324 
1325 
1326 /* PRIVATE
1327  *
1328  * because we use glRect() for drawing 2D boxes, the use of texture coords is not supported
1329  */
1330 void
OGLPRIMPARMLIST()1331 rmBox2d OGLPRIMPARMLIST()
1332 {
1333     /* for verts */
1334     int    vstride, nverts, vveclen;
1335     float *v, *v2;
1336 
1337     /* color data */
1338     int    cstride, ncolors, cveclen;
1339     int    i, nboxes, listStat;
1340     float *c = NULL;
1341     void (*vertexfunc)(const float *), (*colorfunc)(const float *);
1342 
1343     private_colorMaterialStateManip(p, s, rsc);
1344     private_lightingStateManip(p, s, rsc, RM_FALSE);
1345 
1346     listStat = private_rmPrimitiveDisplayListBegin(renderPipe, p);
1347     if (listStat == 0)
1348 	return;
1349 
1350     r = NULL; 			/* foil compiler warning */
1351 
1352     /* vertex data */
1353     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
1354 
1355     /* get color data */
1356     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
1357 
1358     /*
1359      * do validity checking:
1360      * 1. ncolors must be 0 or equal to nverts/2
1361      */
1362     if ((ncolors != 0) && (ncolors != (nverts/2)))
1363     {
1364 	rmError("error: rmBox2D() only per-box color is supported. \n");
1365 	return;
1366     }
1367 
1368     if (vveclen == 3)		/* why check for 3D vertices on 2D boxes? */
1369         vertexfunc = rmglVertex3fv;
1370     else			/* assume vveclen == 2 */
1371         vertexfunc = rmglVertex2fv;
1372 
1373     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
1374 
1375     nboxes = nverts / 2;
1376     v2 = v + vstride;
1377 
1378     for (i = 0; i < nboxes; i++, c += cstride)
1379     {
1380 	(*colorfunc)(c);
1381 	glRectfv((GLfloat *)(v), (GLfloat *)(v2));
1382 
1383 	v = v2 += vstride;
1384 	v2 += vstride;
1385     }
1386 
1387     private_rmPrimitiveDisplayListEnd(renderPipe, p, listStat);
1388 }
1389 
1390 
1391 /* PRIVATE */
1392 void
OGLPRIMPARMLIST()1393 rmEllipse2d OGLPRIMPARMLIST()
1394 {
1395     /* for verts */
1396     float *v;
1397     int    vstride, nverts, vveclen;
1398 
1399     /* color data */
1400     float *c = NULL;
1401     int    cstride, ncolors, cveclen;
1402 
1403     /* for radius data */
1404     float *radii = NULL;
1405     int    rstride, rveclen, nradii;
1406 
1407     /* for rotation data */
1408     float *rotdata;
1409     int    rotstride, rotveclen, nrots;
1410 
1411     int      i;
1412     float    scale;
1413     RMmatrix m;
1414     void   (*colorfunc)(const float *);
1415     float    dummy_rotate = 0.0;
1416 
1417     private_colorMaterialStateManip(p, s, rsc);
1418     private_lightingStateManip(p, s, rsc, RM_FALSE);
1419 
1420     /* get vertex data */
1421     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
1422 
1423     /* get color data */
1424     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
1425 
1426     /* get radius info */
1427     private_rmGetBlobData(BLOB_SCALE_INDEX, p, &rstride, &nradii, (void **)&radii, &rveclen);
1428 
1429     /* rotation data is stuffed into the blob otherwise used
1430        for indices. if we ever want to do indexed ellipses (?), then
1431        we'll have to use a different data blob. */
1432 
1433     private_rmGetBlobData(BLOB_INDEX_INDEX, p, &rotstride, &nrots, (void **)&rotdata, &rotveclen);
1434 
1435     if (rotdata == NULL)
1436     {
1437 	rotdata = &dummy_rotate;
1438 	rotstride = 0;
1439     }
1440 
1441     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
1442 
1443     rmMatrixMultiply(&(s->model), &(s->projection), &m);
1444     rmMatrixMultiply(&m, &(s->vpm), &m);
1445 
1446     scale = RM_MIN(m.m[0][0], m.m[1][1]);
1447 
1448     /* careful on rveclen: we assume radius pairs w/o having to explicitly set veclen on the blob */
1449     for (i = 0; i < nverts; i++, v += vstride, c+= cstride, radii += 2, rotdata += rotstride)
1450     {
1451 	RMmatrix m;
1452 	int      subdivisions;
1453 	float    rval;
1454 	float    cval, sval;
1455 
1456         glPushMatrix();
1457 
1458 	/* assume input in degrees */
1459 	{
1460 	    int idegrees;
1461 	    /*
1462 	     * input rotation value is expressed in terms of 10th's
1463 	     * of degrees. our cos/sin table resolution is 1 degree, so
1464 	     * we just throw away the additional resolution by dividing
1465 	     * by 10.
1466 	     */
1467 	    idegrees = (int)(*rotdata * 0.10F);
1468 	    idegrees = idegrees % 360;
1469 	    idegrees = (idegrees < 0) ? idegrees + 360 : idegrees;
1470 
1471 	    cval = cos_table[idegrees];
1472 	    sval = sin_table[idegrees];
1473 	}
1474 
1475 	rmMatrixIdentity(&m);
1476 
1477 	m.m[0][0] = m.m[1][1] = cval;
1478 	m.m[0][1] = sval;
1479 	m.m[1][0] = -sval;
1480 
1481 	m.m[3][0] = v[0];
1482 	m.m[3][1] = v[1];
1483 	m.m[3][2] = 0.0F;
1484 	glMultMatrixf((const GLfloat *)&(m.m[0][0]));
1485 	(*colorfunc)(c);
1486 
1487 	rval = RM_MAX(radii[0], radii[1]);	/* radii must be defined */
1488 	subdivisions = rval * scale; 		/* this formulation results in line segments which are about 3 pixels long */
1489 
1490 
1491 	rmuEllipse2d(subdivisions, radii[0], radii[1]);
1492 
1493 
1494 	glPopMatrix();
1495     }
1496 
1497     r = NULL; 			/* foil compiler warning */
1498     renderPipe = NULL; 		/* foil compiler warning */
1499 }
1500 
1501 
1502 /* PRIVATE */
1503 void
OGLPRIMPARMLIST()1504 rmSprite OGLPRIMPARMLIST()
1505 {
1506     /*
1507      * display listing is handled a little differently for sprites &
1508      * bitmaps. the display list is associated with the RMimage object,
1509      * not the RMprimitive based upon the observation that the image
1510      * data itself is a higher-payload object than a vertex or two,
1511      * and to allow for this code to deal with weird raster position
1512      * placement issues that come up in OpenGL when drawing image
1513      * based data.
1514      */
1515 
1516     /* for verts */
1517     float    *v;
1518     int       vstride, nverts, vveclen;
1519     void    (*vertexfunc)(const float *);
1520 
1521     int       i;
1522     RMimage **sprite_list, *sprite;
1523     RMmatrix  vpm, vpm_inv, forward, inv;
1524     float     horigin = 0.0F, vorigin = 0.0F;
1525     GLenum    format, gltype;
1526 
1527     RMenum   hjustify, vjustify;
1528 
1529     /* get vertex data */
1530     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
1531 
1532     private_lightingStateManip(p, s, rsc, RM_FALSE);
1533 
1534     if (vveclen == 2)
1535 	vertexfunc = rmglRasterPos2fv;
1536     else /* assume vincr = 3 */
1537 	vertexfunc = rmglRasterPos3fv;
1538 
1539     /* get justification settings specified for text */
1540     private_rmStateGetTextJustify(s, &hjustify, &vjustify);
1541 
1542     /*
1543      * now, grab the sprites. note that indexed sprites are not
1544      * currently supported.
1545      */
1546     private_rmPrimitiveGetItem(p, RM_PRIMITIVE_SPRITES, &i, (void **)&sprite_list);
1547 
1548     private_rmSetupBitmapPickMatrices(s, &vpm, &vpm_inv, &forward, &inv);
1549 
1550     for (i = 0; i < nverts; i++, v += vstride)
1551     {
1552 	float xzoom, yzoom;
1553 
1554 	sprite = sprite_list[i];
1555 
1556 	if (sprite == NULL)
1557 	    rmError("error in rmSprite() - NULL image pointer encountered in an RM_SPRITE primitive. \n");
1558 
1559 	rmImageGetPixelZoom(sprite, &xzoom, &yzoom);
1560 
1561 	horigin = 0.0F;
1562 	if (hjustify == RM_CENTER)
1563 	    horigin = (float)sprite->w * xzoom * 0.5F;
1564 	else if (hjustify == RM_RIGHT)
1565 	    horigin = (float)sprite->w * xzoom;
1566 
1567 	vorigin = 0.0F;
1568 	if (vjustify == RM_CENTER)
1569 	    vorigin = (float)sprite->h * yzoom * 0.5F;
1570 	else if (vjustify == RM_TOP)
1571 	    vorigin = (float)sprite->h * yzoom;
1572 
1573 	if (s->rendermode == GL_SELECT || SHOW_PICKABLE_QUADS)
1574         {
1575             /*
1576 	     * in pick mode, we have to generate some pickable geometry
1577 	     * since glDrawPixels doesn't generate anything we can pick.
1578 	     * This hunk of code draws pickable geometry.
1579              */
1580 	    int w, h;
1581 	    RMvertex3D t;
1582 
1583 	    w = sprite->w * xzoom;
1584 	    h = sprite->h * yzoom;
1585 
1586 	    t.x = v[0];
1587 	    t.y = v[1];
1588 	    t.z = (vveclen == 2) ? 0.0F : v[2];
1589 
1590             private_rmDrawBitmapPickableQuads(&vpm, &vpm_inv, &forward,&inv,
1591 					      &t, horigin, vorigin, w, h);
1592         }
1593 
1594 	if ((s->rendermode != GL_SELECT) || (SHOW_PICKABLE_QUADS))
1595         {
1596 	    /*
1597 	     * In rendering mode, compute the pixel location of the
1598 	     * vertex value associated with the sprite. The final pixel
1599 	     * coordinate will reflect the transformation of world
1600 	     * coordinates to pixel coordinates as well as the offset
1601 	     * resulting from the requested justification.
1602 	     */
1603 	    RMvertex3D dc;
1604 	    RMvertex3D drawVertex;
1605 	    RMvertex3D t;
1606 	    float      xmove=0.0F, ymove=0.0F;
1607 	    int        adjustRasterpos = 0;
1608 
1609 	    t.x = v[0];
1610 	    t.y = v[1];
1611 	    t.z = (vveclen == 2) ? 0.0F : v[2];
1612 
1613 	    if (vveclen == 2)
1614 		private_rmDCFromWC2(&t, &dc, 1, s);
1615 	    else
1616 		private_rmDCFromWC3(&t, &dc, 1, s);
1617 
1618 	    dc.x -= horigin;
1619 	    dc.y -= vorigin;
1620 
1621 	    /* check to see if the requested vertex position is outside
1622 	     the viewport. */
1623 
1624 	    if ((dc.x <= 0.0F) || (dc.y <= 0.0F) || /* off to left or bottom */
1625 		(dc.x >= s->w) || (dc.y >= s->h)) /* off to top or right */
1626 	    {
1627 		RMvertex3D newDC;
1628 		float dx, dy;
1629 
1630 		/* put the new vertex at the center of the screen */
1631 		newDC.x = (float)(s->w) * 0.5;
1632 		newDC.y = (float)(s->h) * 0.5;
1633 		newDC.z = dc.z;
1634 
1635 		/* what is the pixel delta from current vertex location in
1636 		   pixel coordinates to pixel coordinates of proposed
1637 		   new vertex?  */
1638 		dx = newDC.x - dc.x;
1639 		dy = newDC.y - dc.y;
1640 
1641 		/*
1642 		 * compute the new world coordinate. This approach produces
1643 		 * the correct projected screen location, but the z-coordinate
1644 		 * isn't exactly correct. If you have fog turned on, you may
1645 		 * see a discontinous shade change when the sprite crosses
1646 		 * over the left or bottom window boundary.
1647 		 */
1648 		private_rmNewWCfromDCOffset((RMvertex3D *)v, dx, dy,
1649 					    &drawVertex,
1650 					    &vpm, &vpm_inv, &forward, &inv);
1651 		xmove = -1.0F * dx;
1652 		ymove = -1.0F * dy;
1653 
1654 		adjustRasterpos = 1;
1655 	    }
1656 	    else
1657 	    {
1658 		/*
1659 		 * the vertex with justification lies within the viewport.
1660 		 * compute a new world coordinate for use in drawing
1661 		 * the sprite.
1662 		 */
1663 		private_rmNewWCfromDCOffset(&t, -horigin, -vorigin,
1664 					    &drawVertex,
1665 					    &vpm, &vpm_inv, &forward, &inv);
1666 		adjustRasterpos = 0;
1667 	    }
1668 
1669 
1670 	    (*vertexfunc)((GLfloat *)&drawVertex);
1671 
1672 	    /* warning!! generates a bitmap feedback token!! */
1673 	    if (adjustRasterpos == 1)
1674 		glBitmap(0, 0, 0, 0, (GLfloat)xmove, (GLfloat)ymove, NULL);
1675 
1676 	    glPixelZoom ((GLfloat)xzoom, (GLfloat)yzoom);
1677 
1678 	    format = private_rmImageGetOGLFormat(sprite);
1679 	    gltype = private_rmImageGetOGLType(sprite);
1680 
1681 	    private_glDrawPixels(private_rmImageGetWidth(sprite), private_rmImageGetHeight(sprite), format, gltype, (const GLvoid *)(private_rmImageGetPixelData(sprite)), sprite);
1682 
1683 	    /* all sprite/image display list stuff was ripped out
1684 	     during the SBIR work. */
1685 #if 0
1686 	    /* try to build a display list for this image */
1687 	    if (private_rmImageGetDirtyFlag(sprite) == RM_TRUE)
1688 	    {
1689 		private_rmImageSetDirtyFlag(sprite,RM_FALSE);
1690 		if (sprite->d1 != -1)
1691 		{
1692 		    glDeleteLists(sprite->d1, 1);
1693 		    sprite->d1 = -1;
1694 		}
1695 	    }
1696 
1697 	    if (sprite->d1 == -1)
1698 	    {
1699 
1700 #if DO_LISTS
1701 		sprite->d1 = glGenLists(1);
1702 
1703 		glNewList(sprite->d1, GL_COMPILE_AND_EXECUTE);
1704 #endif
1705 
1706 
1707 		/* enable pixel transfer mode if there's a vismap present */
1708 		private_glDrawPixels(private_rmImageGetWidth(sprite), private_rmImageGetHeight(sprite), format, gltype, (const GLvoid *)(private_rmImageGetPixelData(sprite)), sprite);
1709 
1710 
1711 
1712 		/* 10/5/200 all RMimage display list stuff removed during
1713 		 SBIR work.*/
1714 #if DO_LISTS
1715 		glEndList();
1716 #endif
1717 
1718 	    }
1719 	    else
1720 		glCallList(sprite->d1);
1721 #endif
1722 	}
1723     }
1724     r = NULL; 			/* foil compiler warning */
1725     renderPipe = NULL; 		/* foil compiler warning */
1726 }
1727 
1728 
1729 /* PRIVATE */
1730 void
OGLPRIMPARMLIST()1731 rmBitmap OGLPRIMPARMLIST()
1732 {
1733     /* for verts */
1734     float *v;
1735     int    vstride, nverts, vveclen;
1736 
1737     /* color data */
1738     float *c = NULL;
1739     int    cstride, ncolors, cveclen;
1740 
1741     int    i;
1742 
1743     void (*vertexfunc)(const float *);
1744     void (*colorfunc)(const float *);
1745 
1746     RMmatrix vpm, vpm_inv, forward, inv;
1747     RMenum   hjustify, vjustify;
1748     GLfloat  horigin, vorigin;
1749     int      nbitmaps;
1750 
1751     RMbitmap **bmp_list, *bmp;
1752 
1753     /* get vertex data */
1754     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
1755 
1756     /* get color data */
1757     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
1758 
1759     private_colorMaterialStateManip(p, s, rsc);
1760     private_lightingStateManip(p, s, rsc, RM_FALSE);
1761 
1762     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
1763 
1764     if (vveclen == 2)
1765 	vertexfunc = rmglRasterPos2fv;
1766     else /* assume vincr = 3 */
1767 	vertexfunc = rmglRasterPos3fv;
1768 
1769     private_rmStateGetTextJustify(s, &hjustify, &vjustify);
1770 
1771     private_rmPrimitiveGetItem(p, RM_PRIMITIVE_BITMAPS, &nbitmaps, (void **)&bmp_list);
1772 
1773     if (nbitmaps != nverts)
1774     {
1775 	rmError(" the number of bitmaps is not the same as the number of vertices in a bitmap primitive. \n");
1776 	return;
1777     }
1778 
1779     if (s->rendermode == GL_SELECT || SHOW_PICKABLE_QUADS)
1780     {
1781 	/*
1782 	 * in select mode, we're going to draw a bunch of quads rather
1783 	 * than text bitmaps: bitmaps are not pickable, whereas quads
1784 	 * are.  in order to do that, we need some matrices.
1785 	 */
1786 	private_rmSetupBitmapPickMatrices(s, &vpm, &vpm_inv, &forward, &inv);
1787     }
1788 
1789     for (i = 0; i < nverts; i++, v += vstride, c += cstride)
1790     {
1791 	int bw, bh, bytes;
1792 
1793 	bmp = bmp_list[i];
1794 	rmBitmapGetSize(bmp, &bw, &bh, &bytes);
1795 
1796         if (c)
1797 	    (*colorfunc)(c);
1798 
1799 	horigin = 0.0F;
1800 	if (hjustify == RM_CENTER)
1801 	    horigin = (GLfloat)(bw >> 1);
1802 	else
1803 	    if (hjustify == RM_RIGHT)
1804 		horigin = (GLfloat)(bw);
1805 
1806 	vorigin = 0.0F;
1807 
1808 	if (vjustify == RM_CENTER)
1809 	    vorigin = (GLfloat)(bh >> 1);
1810 	else if (vjustify == RM_TOP)
1811 	    vorigin = (GLfloat)(bh);
1812 
1813 	if (s->rendermode == GL_SELECT || SHOW_PICKABLE_QUADS)
1814 	{
1815 	    /* in select mode, draw quads using the matrices we computed earlier */
1816 	   RMvertex3D t;
1817 	   t.x = v[0];
1818 	   t.y = v[1];
1819 	   if (vveclen == 2)
1820 	     t.z = 0.0F;
1821 	   else
1822 	     t.z = v[2];
1823 
1824  	   private_rmDrawBitmapPickableQuads(&vpm, &vpm_inv, &forward, &inv,
1825 					     &t, horigin, vorigin, bw, bh);
1826 	}
1827 	if ((s->rendermode != GL_SELECT) || (SHOW_PICKABLE_QUADS))
1828 	{
1829 	    /* otherwise, we're in normal draw mode.  spit out the bitmaps */
1830 	    (*colorfunc)((float *)c);
1831 	    (*vertexfunc)((float *)v);
1832 	    glBitmap((GLsizei)(bw), (GLsizei)(bh), horigin, vorigin, (GLfloat) 0.0F, (GLfloat)0.0F, (const GLubyte *)(private_rmBitmapGetPixelData(bmp)));
1833 	}
1834     }
1835 
1836     r = NULL; 			/* foil compiler warning */
1837     renderPipe = NULL; 		/* foil compiler warning */
1838 }
1839 
1840 
1841 /* PRIVATE */
1842 void
OGLPRIMPARMLIST()1843 rmIndexedBitmap OGLPRIMPARMLIST()
1844 {
1845     /*
1846      * todo: display list stuff.
1847      */
1848     rmError(" rmIndexedBitmap is broken. \n");
1849 
1850     /* foil compiler warning */
1851     r = NULL;
1852     p = NULL;
1853     s = NULL;
1854     renderPipe = NULL;
1855     rsc = NULL;
1856 }
1857 
1858 
1859 /* PRIVATE
1860  *
1861  * draw routine for indexed text prims
1862  */
1863 void
OGLPRIMPARMLIST()1864 rmIndexedText OGLPRIMPARMLIST()
1865 {
1866     rmText(p, r, s, renderPipe, rsc);
1867 }
1868 
1869 
1870 /* PRIVATE
1871  *
1872  * draw routine for text prims
1873  */
1874 void
OGLPRIMPARMLIST()1875 rmText OGLPRIMPARMLIST()
1876 {
1877     /* for verts */
1878     float *v;
1879     int    vstride, nverts, vveclen;
1880 
1881     /* color data */
1882     float *c = NULL;
1883     int    cstride, ncolors, cveclen;
1884 
1885     /* index data */
1886     int   *indices, istride, nindices, iveclen;
1887     int    i, j;
1888 
1889     void (*vertexfunc)(const float *);
1890     void (*colorfunc)(const float *);
1891 
1892     RMenum hjustify, vjustify;
1893     int    do_indices;
1894 
1895     RMtextPrim *parray;
1896     int          numtextprims;
1897     RMtextProps *tp;
1898     RMfontRegistry *fr;
1899 
1900     int usingTempTextProps = 0;
1901 
1902     RMmatrix     vpm, vpm_inv, forward, inv;
1903 
1904     private_colorMaterialStateManip(p, s, rsc);
1905 
1906     private_lightingStateManip(p, s, rsc, RM_FALSE);
1907 
1908     /* get vertex data */
1909     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
1910 
1911     /* get color data */
1912     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
1913 
1914     /* get index data */
1915     private_rmGetBlobData(BLOB_INDEX_INDEX, p, &istride, &nindices, (void **)&indices, &iveclen);
1916 
1917     if (indices != NULL)
1918 	do_indices = 1;
1919     else
1920 	do_indices = 0;
1921 
1922     if (vveclen == 3)
1923         vertexfunc = rmglRasterPos3fv;
1924     else
1925         vertexfunc = rmglRasterPos2fv;
1926 
1927     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
1928 
1929     if (private_rmPrimitiveGetText(p, &numtextprims, &parray) == RM_WHACKED)
1930     {
1931        rmWarning(" rmText() rendering function error: the input primitive has no text strings defined. \n");
1932        return; /* 9/29/03 - need to verify that a simple return here is OK. */
1933     }
1934 
1935     /* loop to verify that we have proper width & height info
1936      using the current RMtextProps info. */
1937     tp = s->textProps;
1938 
1939     if (tp == NULL)
1940     {
1941 	tp = private_rmDefaultTextProps(renderPipe);
1942 	usingTempTextProps = 1;
1943     }
1944 
1945     /*
1946      * 10/2000 - thread-safety work:
1947      * 1. private_rmPrepareBitmapFont will conditionally build display
1948      *    lists for the English alphabet using the requested font and style
1949      * 2. get the rmFontRegistry handle for that font family on the
1950      *    named RMpipe - it contains display list indices used for
1951      *    drawing bitmaps.
1952      */
1953     private_rmPrepareBitmapFont(tp, renderPipe); /* build display lists */
1954 
1955     fr = private_rmFontRegistryEntry(tp->fontEnum, tp->sizeEnum, tp->italicEnum, tp->boldEnum, renderPipe->contextCache->pipeFontRegistry);
1956 
1957     /* assertion check on "fr" here? */
1958 
1959 
1960     for (i = 0; i < numtextprims; i++)
1961     {
1962 
1963 	/*
1964 	 * 10/2000 TODO
1965 	 * the following routine computes the character width
1966 	 * and height of a character string when rendered given
1967 	 * font family and style info. this info is needed for
1968 	 * picking (selection) and for justification. in an
1969 	 * earlier (non thread-safe) version of OpenRM, we cached
1970 	 * some info in the RMtextPrim. we need to update this
1971 	 * code so that we need not recompute character width
1972 	 * and height during each frame rendering.
1973 	 */
1974 	int indx;
1975 
1976 	if (do_indices == 1)
1977 	    indx = indices[i];
1978 	else
1979 	    indx = i;
1980 
1981 	private_rmTextPrimComputeCW(parray + indx, fr, renderPipe);
1982     }
1983 
1984     private_rmStateGetTextJustify(s, &hjustify, &vjustify);
1985 
1986     /* need w,h of the bitmaps in order to do justification & picking */
1987     if (s->rendermode == GL_SELECT || SHOW_PICKABLE_QUADS)
1988     {
1989 	private_rmSetupBitmapPickMatrices(s, &vpm, &vpm_inv, &forward, &inv);
1990     }
1991 
1992     for (i = 0, j = 0; i < nverts; i++, v += vstride, c += cstride)
1993     {
1994 	int          bw, bh;
1995 	int          horigin = 0, vorigin = 0;
1996 	RMtextPrim *pt;
1997 
1998 	if (do_indices == 1)
1999 	    pt = parray + indices[i];
2000 	else
2001 	    pt = parray + i;
2002 	bw = pt->bw;
2003 	bh = pt->bh;
2004 
2005 	horigin = 0.0F;
2006 	if (hjustify == RM_CENTER)
2007 	    horigin = (GLfloat)(bw >> 1);
2008 	else
2009 	    if (hjustify == RM_RIGHT)
2010 		horigin = (GLfloat)(bw);
2011 
2012 	vorigin = 0.0F;
2013 	if (vjustify == RM_CENTER)
2014 	    vorigin = (GLfloat)(bh >> 1);
2015 	else
2016 	    if (vjustify == RM_TOP)
2017 		vorigin = (GLfloat)(bh);
2018 
2019 	if (s->rendermode == GL_SELECT || SHOW_PICKABLE_QUADS)
2020 	{
2021 	    RMvertex3D tv;
2022 
2023 	    tv.x = v[0];
2024 	    tv.y = v[1];
2025 
2026 	    /* 6/12/02 add code so that src z-coord is used if
2027 	     present. this fixes a picking bug. */
2028 
2029 	    if (vveclen == 2)
2030 	      tv.z = 0.0;
2031 	    else
2032 	      tv.z = v[2];
2033 
2034 	    private_rmDrawBitmapPickableQuads(&vpm, &vpm_inv, &forward, &inv,
2035 					      &tv, horigin, vorigin, bw, bh);
2036 
2037 	} /* end selection mode */
2038 	if ((s->rendermode == GL_RENDER) || SHOW_PICKABLE_QUADS)
2039 	{
2040 	    char *str;
2041 
2042 	    (*colorfunc)(c);
2043 	    (*vertexfunc)(v);
2044 
2045 	    str = pt->string;
2046 
2047 	    {
2048 		if (horigin != 0 || vorigin != 0)
2049 		{
2050 		    glBitmap(0, 0, 0, 0, -horigin, -vorigin, NULL);
2051 		}
2052 
2053 		glPushAttrib(GL_LIST_BIT);
2054 		glListBase(fr->listbase - 32);
2055 
2056 		glCallLists(strlen(str), GL_UNSIGNED_BYTE, str);
2057 		glPopAttrib();
2058 	    }
2059 	}
2060 
2061 	if (do_indices == 1)
2062 	    j++;
2063     } /* loop over nverts */
2064 
2065     if (usingTempTextProps == 1)
2066 	rmTextPropsDelete(tp);
2067 
2068     r = NULL; 			/* foil compiler warning */
2069 }
2070 
2071 
2072 /* PRIVATE */
2073 void
OGLPRIMPARMLIST()2074 rmIndexedTriangleFan OGLPRIMPARMLIST()
2075 {
2076     void (*vertexfunc)(const float *), (*colorfunc)(const float *);
2077     void (*tcfunc)(const float *), (*normalfunc)(const float *);
2078 
2079     /* for verts */
2080     float *v;
2081     int    vstride, nverts, vveclen;
2082 
2083     /* color data */
2084     float *c = NULL;
2085     int    cstride, ncolors, cveclen;
2086 
2087     /* texture coord data */
2088     float *tc = NULL;
2089     int    tcstride;
2090     int    ntc, tcveclen;
2091 
2092     /* normals */
2093     float *n;
2094     int    nstride, nveclen, nnormals;
2095 
2096     /* indices */
2097     int *indices;
2098     int  nindices, iveclen, istride;
2099 
2100     int i, listStat;
2101 
2102     /* get vertex data */
2103     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
2104 
2105     /* get indices */
2106     private_rmGetBlobData(BLOB_INDEX_INDEX, p, &istride, &nindices, (void **)&indices, &iveclen);
2107 
2108     if ((nindices == 0) || (nverts == 0)) /* check for early termination */
2109 	return;
2110 
2111     private_colorMaterialStateManip(p, s, rsc);
2112     private_lightingStateManip(p, s, rsc, RM_FALSE);
2113 
2114     listStat = private_rmPrimitiveDisplayListBegin(renderPipe, p);
2115     if (listStat == 0)
2116 	return;
2117 
2118     r = NULL; 			/* foil compiler warning */
2119 
2120     /* get color data */
2121     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
2122 
2123     private_rmGetBlobData(BLOB_TC_INDEX, p, &tcstride, &ntc, (void **)&tc, &tcveclen);
2124 
2125     /* get normals info */
2126     private_rmGetBlobData(BLOB_NORMAL_INDEX, p, &nstride, &nnormals, (void **)&n, &nveclen);
2127 
2128     if (vveclen == 3)
2129         vertexfunc = rmglVertex3fv;
2130     else			/* assume vveclen == 2 */
2131         vertexfunc = rmglVertex2fv;
2132 
2133     if (n != NULL)		/* assume normals are in R3*/
2134 	normalfunc = rmglNormal3fv;
2135     else
2136 	normalfunc = glNoOp;
2137 
2138     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
2139 
2140     if (ntc == 0)
2141 	tcfunc = glNoOp;
2142     else
2143 	private_rmSetGLTexCoordFunc(tcveclen, ntc, &tcfunc);
2144 
2145     glBegin(GL_TRIANGLE_FAN);
2146     for (i = 0; i < nindices; i++)
2147     {
2148 	int indx = indices[i];
2149 
2150 	(*colorfunc)(c + (indx * cstride));
2151 	(*normalfunc)(n + (indx * nstride));
2152 	(*tcfunc)(tc + (indx * tcstride));
2153         (*vertexfunc)(v + (indx * vstride));
2154     }
2155     glEnd();
2156 
2157     private_rmPrimitiveDisplayListEnd(renderPipe, p, listStat);
2158 }
2159 
2160 /* PRIVATE */
2161 void
OGLPRIMPARMLIST()2162 rmIndexedQuads OGLPRIMPARMLIST()
2163 {
2164     void (*vertexfunc)(const float *), (*colorfunc)(const float *);
2165     void (*tcfunc)(const float *), (*normalfunc)(const float *);
2166 
2167     /* for verts */
2168     float *v;
2169     int    vstride, nverts, vveclen;
2170 
2171     /* color data */
2172     float *c = NULL;
2173     int    cstride, ncolors, cveclen;
2174 
2175     /* texture coord data */
2176     float *tc = NULL;
2177     int    tcstride;
2178     int    ntc, tcveclen;
2179 
2180     /* normals */
2181     float *n;
2182     int    nstride, nveclen, nnormals;
2183 
2184     /* indices */
2185     int *indices;
2186     int  nindices, iveclen, istride;
2187 
2188     int i, listStat;
2189 
2190 
2191     /* get indices */
2192     private_rmGetBlobData(BLOB_INDEX_INDEX, p, &istride, &nindices, (void **)&indices, &iveclen);
2193 
2194     /* get vertex data */
2195     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
2196     if ((nindices == 0) || (nverts == 0)) /* check for early termination */
2197 	return;
2198 
2199     private_colorMaterialStateManip(p, s, rsc);
2200     private_lightingStateManip(p, s, rsc, RM_FALSE);
2201 
2202     listStat = private_rmPrimitiveDisplayListBegin(renderPipe, p);
2203     if (listStat == 0)
2204 	return;
2205 
2206     r = NULL; 			/* foil compiler warning */
2207 
2208     /* get color data */
2209     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
2210 
2211     private_rmGetBlobData(BLOB_TC_INDEX, p, &tcstride, &ntc, (void **)&tc, &tcveclen);
2212 
2213     /* get normals info */
2214     private_rmGetBlobData(BLOB_NORMAL_INDEX, p, &nstride, &nnormals, (void **)&n, &nveclen);
2215 
2216     if (vveclen == 3)
2217         vertexfunc = rmglVertex3fv;
2218     else			/* assume vveclen == 2 */
2219         vertexfunc = rmglVertex2fv;
2220 
2221     if (n != NULL)		/* assume normals are in R3*/
2222 	normalfunc = rmglNormal3fv;
2223     else
2224 	normalfunc = glNoOp;
2225 
2226     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
2227 
2228     if (ntc == 0)
2229 	tcfunc = glNoOp;
2230     else
2231 	private_rmSetGLTexCoordFunc(tcveclen, ntc, &tcfunc);
2232 
2233     glBegin(GL_QUADS);
2234     for (i = 0; i < nindices; i++)
2235     {
2236 	int indx = indices[i];
2237 
2238 	(*colorfunc)(c + (indx * cstride));
2239 	(*normalfunc)(n + (indx * nstride));
2240 	(*tcfunc)(tc + (indx * tcstride));
2241         (*vertexfunc)(v + (indx * vstride));
2242     }
2243     glEnd();
2244 
2245     private_rmPrimitiveDisplayListEnd(renderPipe, p, listStat);
2246 }
2247 
2248 /* PRIVATE */
2249 void
OGLPRIMPARMLIST()2250 rmIndexedTriangles OGLPRIMPARMLIST()
2251 {
2252     void (*vertexfunc)(const float *), (*colorfunc)(const float *);
2253     void (*tcfunc)(const float *), (*normalfunc)(const float *);
2254 
2255     /* for verts */
2256     float *v;
2257     int    vstride, nverts, vveclen;
2258 
2259     /* color data */
2260     float *c = NULL;
2261     int    cstride, ncolors, cveclen;
2262 
2263     /* texture coord data */
2264     float *tc = NULL;
2265     int    tcstride;
2266     int    ntc, tcveclen;
2267 
2268     /* normals */
2269     float *n;
2270     int    nstride, nveclen, nnormals;
2271 
2272     /* indices */
2273     int *indices;
2274     int  nindices, iveclen, istride;
2275 
2276     /* multitexturing */
2277     int haveMTCs = 0;
2278 
2279     int i, listStat;
2280 
2281     /* get indices */
2282     private_rmGetBlobData(BLOB_INDEX_INDEX, p, &istride, &nindices, (void **)&indices, &iveclen);
2283 
2284     /* get vertex data */
2285     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
2286     if ((nverts == 0) || (nindices == 0)) /* check for early termination */
2287 	return;
2288 
2289     r = NULL; 			/* foil compiler warning */
2290 
2291     private_colorMaterialStateManip(p, s, rsc);
2292     private_lightingStateManip(p, s, rsc, RM_FALSE);
2293 
2294     listStat = private_rmPrimitiveDisplayListBegin(renderPipe, p);
2295     if (listStat == 0)
2296 	return;
2297 
2298     /* get color data */
2299     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
2300 
2301     private_rmGetBlobData(BLOB_TC_INDEX, p, &tcstride, &ntc, (void **)&tc, &tcveclen);
2302 
2303     /* get normals info */
2304     private_rmGetBlobData(BLOB_NORMAL_INDEX, p, &nstride, &nnormals, (void **)&n, &nveclen);
2305 
2306     if (vveclen == 3)
2307         vertexfunc = rmglVertex3fv;
2308     else			/* assume vveclen == 2 */
2309         vertexfunc = rmglVertex2fv;
2310 
2311     if (n != NULL)		/* assume normals are in R3 */
2312 	normalfunc = rmglNormal3fv;
2313     else
2314 	normalfunc = glNoOp;
2315 
2316     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
2317 
2318     if (ntc == 0)
2319 	tcfunc = glNoOp;
2320     else
2321 	private_rmSetGLTexCoordFunc(tcveclen, ntc, &tcfunc);
2322 
2323     if (p->multiTextureCoordBlobsMask != 0)
2324 	haveMTCs = 1;
2325 
2326     glBegin(GL_TRIANGLES);
2327     for (i = 0; i < nindices; i++)
2328     {
2329 	int indx = indices[i];
2330 
2331 	(*colorfunc)(c + (indx * cstride));
2332 	(*normalfunc)(n + (indx * nstride));
2333 	(*tcfunc)(tc + (indx * tcstride));
2334 	if (haveMTCs)
2335 	    private_dispatchMTCs(renderPipe, p, indx);
2336         (*vertexfunc)(v + (indx * vstride));
2337     }
2338     glEnd();
2339 
2340     private_rmPrimitiveDisplayListEnd(renderPipe, p, listStat);
2341 }
2342 
2343 /* PRIVATE */
2344 void
OGLPRIMPARMLIST()2345 rmIndexedQuadStrip OGLPRIMPARMLIST()
2346 {
2347     void (*vertexfunc)(const float *), (*colorfunc)(const float *);
2348     void (*tcfunc)(const float *), (*normalfunc)(const float *);
2349 
2350     /* for verts */
2351     float *v;
2352     int    vstride, nverts, vveclen;
2353 
2354     /* color data */
2355     float *c = NULL;
2356     int    cstride, ncolors, cveclen;
2357 
2358     /* texture coord data */
2359     float *tc = NULL;
2360     int    tcstride;
2361     int    ntc, tcveclen;
2362 
2363     /* normals */
2364     float *n;
2365     int    nstride, nveclen, nnormals;
2366 
2367     /* indices */
2368     int *indices;
2369     int  nindices, iveclen, istride;
2370 
2371     int i, listStat;
2372 
2373     /* get indices */
2374     private_rmGetBlobData(BLOB_INDEX_INDEX, p, &istride, &nindices, (void **)&indices, &iveclen);
2375 
2376     /* get vertex data */
2377     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
2378     if ((nverts == 0) || (nindices == 0)) /* check for early termination */
2379 	return;
2380 
2381     private_colorMaterialStateManip(p, s, rsc);
2382     private_lightingStateManip(p, s, rsc, RM_FALSE);
2383 
2384     listStat = private_rmPrimitiveDisplayListBegin(renderPipe, p);
2385     if (listStat == 0)
2386 	return;
2387 
2388     r = NULL; 			/* foil compiler warning */
2389 
2390     /* get color data */
2391     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
2392 
2393     private_rmGetBlobData(BLOB_TC_INDEX, p, &tcstride, &ntc, (void **)&tc, &tcveclen);
2394 
2395     /* get normals info */
2396     private_rmGetBlobData(BLOB_NORMAL_INDEX, p, &nstride, &nnormals, (void **)&n, &nveclen);
2397 
2398     if (vveclen == 3)
2399         vertexfunc = rmglVertex3fv;
2400     else			/* assume vveclen == 2 */
2401         vertexfunc = rmglVertex2fv;
2402 
2403     if (n != NULL)		/* assume normals are in R3 */
2404 	normalfunc = rmglNormal3fv;
2405     else
2406 	normalfunc = glNoOp;
2407 
2408     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
2409 
2410     if (ntc == 0)
2411 	tcfunc = glNoOp;
2412     else
2413 	private_rmSetGLTexCoordFunc(tcveclen, ntc, &tcfunc);
2414 
2415     glBegin(GL_QUAD_STRIP);
2416     for (i = 0; i < nindices; i++)
2417     {
2418 	int indx = indices[i];
2419 
2420 	(*colorfunc)(c + (indx * cstride));
2421 	(*normalfunc)(n + (indx * nstride));
2422 	(*tcfunc)(tc + (indx * tcstride));
2423         (*vertexfunc)(v + (indx * vstride));
2424     }
2425     glEnd();
2426 
2427     private_rmPrimitiveDisplayListEnd(renderPipe, p, listStat);
2428 }
2429 
2430 /* PRIVATE */
2431 void
OGLPRIMPARMLIST()2432 rmIndexedTriangleStrip OGLPRIMPARMLIST()
2433 {
2434     void (*vertexfunc)(const float *), (*colorfunc)(const float *);
2435     void (*tcfunc)(const float *), (*normalfunc)(const float *);
2436 
2437     /* for verts */
2438     float *v;
2439     int    vstride, nverts, vveclen;
2440 
2441     /* color data */
2442     float *c = NULL;
2443     int    cstride, ncolors, cveclen;
2444 
2445     /* texture coord data */
2446     float *tc = NULL;
2447     int    tcstride;
2448     int    ntc, tcveclen;
2449 
2450     /* normals */
2451     float *n;
2452     int    nstride, nveclen, nnormals;
2453 
2454     /* indices */
2455     int *indices;
2456     int  nindices, iveclen, istride;
2457 
2458     int i, listStat;
2459 
2460     /* get indices */
2461     private_rmGetBlobData(BLOB_INDEX_INDEX, p, &istride, &nindices, (void **)&indices, &iveclen);
2462 
2463     /* get vertex data */
2464     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
2465     if ((nverts == 0) || (nindices == 0)) /* check for early termination */
2466 	return;
2467 
2468     private_colorMaterialStateManip(p, s, rsc);
2469     private_lightingStateManip(p, s, rsc, RM_FALSE);
2470 
2471     listStat = private_rmPrimitiveDisplayListBegin(renderPipe, p);
2472     if (listStat == 0)
2473 	return;
2474 
2475     r = NULL; 			/* foil compiler warning */
2476 
2477     /* get color data */
2478     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
2479 
2480     private_rmGetBlobData(BLOB_TC_INDEX, p, &tcstride, &ntc, (void **)&tc, &tcveclen);
2481 
2482     /* get normals info */
2483     private_rmGetBlobData(BLOB_NORMAL_INDEX, p, &nstride, &nnormals, (void **)&n, &nveclen);
2484 
2485     if (vveclen == 3)
2486         vertexfunc = rmglVertex3fv;
2487     else			/* assume vveclen == 2 */
2488         vertexfunc = rmglVertex2fv;
2489 
2490     if (n != NULL)		/* assume normals are in R3 */
2491 	normalfunc = rmglNormal3fv;
2492     else
2493 	normalfunc = glNoOp;
2494 
2495     private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
2496 
2497     if (ntc == 0)
2498 	tcfunc = glNoOp;
2499     else
2500 	private_rmSetGLTexCoordFunc(tcveclen, ntc, &tcfunc);
2501 
2502     glBegin(GL_TRIANGLE_STRIP);
2503     for (i = 0; i < nindices; i++)
2504     {
2505 	int indx = indices[i];
2506 
2507 	(*colorfunc)(c + (indx * cstride));
2508 	(*normalfunc)(n + (indx * nstride));
2509 	(*tcfunc)(tc + (indx * tcstride));
2510         (*vertexfunc)(v + (indx * vstride));
2511     }
2512     glEnd();
2513 
2514     private_rmPrimitiveDisplayListEnd(renderPipe, p, listStat);
2515 }
2516 
2517 /* PRIVATE
2518  *
2519  * 8/14/04 - updated code to accommodate per-face colors, normals, etc.
2520  * When optional data items (colors, normals) are specified per-vertex,
2521  * then we use vertex arrays. Otherwise, we use a slower path through
2522  * OpenGL.
2523  */
2524 void
OGLPRIMPARMLIST()2525 rmQuads OGLPRIMPARMLIST()
2526 {
2527     /* for verts */
2528     float *v;
2529     int    vstride, nverts, vveclen;
2530 
2531     /* color data */
2532     float *c = NULL;
2533     int    cstride, ncolors, cveclen;
2534 
2535     /* texture coord data */
2536     float *tc = NULL;
2537     int    tcstride;
2538     int    ntc, tcveclen;
2539 
2540     /* normals */
2541     float *n;
2542     int    nstride, nveclen, nnormals;
2543 
2544     int listStat;
2545 
2546     int perVertexColor=0, perFaceColor=0;
2547     int perVertexNormals=0, perFaceNormals=0;
2548     int useVertexArrays=1;
2549 
2550     int haveMTCs = 0;
2551 
2552     private_lightingStateManip(p,s, rsc, RM_FALSE);
2553     private_colorMaterialStateManip(p,s, rsc);
2554 
2555     listStat = private_rmPrimitiveDisplayListBegin(renderPipe,p);
2556 
2557     if (listStat == 0)
2558 	return;
2559 
2560     r = NULL; 			/* foil compiler warning */
2561 
2562     /* get vertex data */
2563     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nverts, (void **)&v, &vveclen);
2564 
2565     /* get color data */
2566     private_rmGetBlobData(BLOB_COLOR_INDEX, p, &cstride, &ncolors, (void **)&c, &cveclen);
2567 
2568     /* get texture coord data - NOTE: (2/2000) tc's & quads not tested */
2569     private_rmGetBlobData(BLOB_TC_INDEX, p, &tcstride, &ntc, (void **)&tc, &tcveclen);
2570 
2571     /* get normals info */
2572     private_rmGetBlobData(BLOB_NORMAL_INDEX, p, &nstride, &nnormals, (void **)&n, &nveclen);
2573 
2574     /*
2575      * check to see which code path to use
2576      */
2577     if (ncolors != 0)
2578     {
2579         if (ncolors == nverts)
2580 	    perVertexColor = 1;
2581 	else if ((ncolors << 2) == nverts)
2582 	{
2583 	    perFaceColor = 1;
2584 	    useVertexArrays = 0;
2585 	}
2586     }
2587 
2588     if (nnormals != 0)
2589     {
2590         if (nnormals == nverts)
2591 	    perVertexNormals = 1;
2592 	else if ((nnormals << 2) == nverts)
2593 	{
2594 	    perFaceNormals = 1;
2595 	    useVertexArrays = 0;
2596 	}
2597     }
2598 
2599     if (p->multiTextureCoordBlobsMask != 0)
2600     {
2601 	useVertexArrays = 0; 	/* slow path until we figure out how to
2602 				   use vertex arrays with MTCs. */
2603 	haveMTCs = 1;
2604     }
2605 
2606     if (useVertexArrays == 1)
2607     {
2608         private_rmEnableVertexArrays(nverts, ncolors, nnormals, ntc, 0, 0);
2609 
2610 	glVertexPointer(vveclen, GL_FLOAT, sizeof(float) * vstride, (const GLvoid *)v);
2611 
2612 	if (ncolors != 0)
2613 	    glColorPointer(cveclen, GL_FLOAT, sizeof(float) * cstride, (const GLvoid *)c);
2614 
2615 	if (ntc != 0)
2616 	    glTexCoordPointer(tcveclen, GL_FLOAT,sizeof(float) * tcstride, (const GLvoid *)tc);
2617 
2618 	if (nnormals != 0)
2619 	    glNormalPointer(GL_FLOAT, sizeof(float) * nstride, (const GLvoid *)n);
2620 
2621 	glDrawArrays(GL_QUADS, 0, nverts);
2622     }
2623     else
2624     {
2625         /* vertex, normal, color, tc functions */
2626         void (*vertexfunc)(const float *);
2627 	void (*normalfunc)(const float *);
2628 	void (*colorfunc)(const float *);
2629 	void (*tcfunc)(const float *);
2630 	int i;
2631 
2632 	if (vveclen == 3)
2633 	    vertexfunc = rmglVertex3fv;
2634 	else
2635 	    vertexfunc = rmglVertex2fv;
2636 
2637 	if (nnormals != 0)
2638 	    normalfunc = rmglNormal3fv;
2639 	else
2640 	    normalfunc = glNoOp;
2641 
2642 	if (ncolors != 0)
2643 	    private_rmSetGLColorFunc(cveclen, ncolors, &colorfunc);
2644 	else
2645  	    colorfunc = glNoOp;
2646 
2647 	if (ntc == 0)
2648 	    tcfunc = glNoOp;
2649 	else
2650 	    private_rmSetGLTexCoordFunc(tcveclen, ntc, &tcfunc);
2651 
2652 	glBegin(GL_QUADS);
2653 
2654 	for (i=0; i < nverts; i++)
2655 	{
2656 	    if (nnormals != 0)
2657 	        (*normalfunc)(n), n += nstride;
2658 	    if (ncolors != 0)
2659 	        (*colorfunc)(c), c += cstride;
2660 	    if (ntc != 0)
2661 		(*tcfunc)(tc), tc += tcstride;
2662 	    if (haveMTCs)
2663 		private_dispatchMTCs(renderPipe, p, i);
2664 
2665   	    (*vertexfunc)(v);
2666 	    i++;
2667 	    v += vstride;
2668 
2669 	    if (nnormals != 0)
2670 	        (*normalfunc)(n), n += nstride;
2671 	    if (perVertexColor)
2672 	        (*colorfunc)(c), c += cstride;
2673 	    if (ntc != 0)
2674 		(*tcfunc)(tc), tc += tcstride;
2675 	    if (haveMTCs)
2676 		private_dispatchMTCs(renderPipe, p, i);
2677 
2678   	    (*vertexfunc)(v);
2679 	    i++;
2680 	    v += vstride;
2681 
2682 	    if (nnormals != 0)
2683 	        (*normalfunc)(n), n += nstride;
2684 	    if (perVertexColor)
2685 	        (*colorfunc)(c), c += cstride;
2686 	    if (ntc != 0)
2687 		(*tcfunc)(tc), tc += tcstride;
2688 	    if (haveMTCs)
2689 		private_dispatchMTCs(renderPipe, p, i);
2690 
2691   	    (*vertexfunc)(v);
2692 	    i++;
2693 	    v += vstride;
2694 
2695 	    if (nnormals != 0)
2696 	        (*normalfunc)(n), n += nstride;
2697 	    if (perVertexColor)
2698 	        (*colorfunc)(c), c += cstride;
2699 	    if (ntc != 0)
2700 		(*tcfunc)(tc), tc += tcstride;
2701 	    if (haveMTCs)
2702 		private_dispatchMTCs(renderPipe, p, i);
2703 
2704   	    (*vertexfunc)(v);
2705 	    i++;
2706 	    v += vstride;
2707 	}
2708 
2709 	glEnd();
2710     }
2711 
2712 
2713     private_rmPrimitiveDisplayListEnd(renderPipe, p, listStat);
2714 }
2715 
2716 /* PRIVATE */
2717 /*
2718  * dispatch
2719  */
2720 void
private_dispatchMTCs(RMpipe * pipe,RMprimitive * prim,int vertexIndx)2721 private_dispatchMTCs(RMpipe *pipe,
2722 		     RMprimitive *prim,
2723 		     int vertexIndx)
2724 {
2725     int i;
2726     int offset;
2727     int mask;
2728     RMprimitiveDataBlob *b;
2729 
2730     mask = prim->multiTextureCoordBlobsMask;
2731     for (i=0; (i < RM_MAX_MULTITEXTURES) && (mask != 0); i++)
2732     {
2733 	if (mask & 0x1)
2734 	{
2735 	    GLint target = GL_TEXTURE0_ARB + i;
2736 	    float *f;
2737 
2738 	    b = prim->multiTextureCoordBlobs + i;
2739 	    offset = private_rmBlobGetStride(b) / sizeof(float) * vertexIndx;
2740 	    f = (float *)private_rmBlobGetData(b) + offset;
2741 
2742 	    switch (private_rmBlobGetVeclen(b))
2743 	    {
2744 	    case 1:
2745 		(*(pipe->caps->multiTexCoord1fvARB))(target, f);
2746 		break;
2747 	    case 2:
2748 		(*(pipe->caps->multiTexCoord2fvARB))(target, f);
2749 		break;
2750 	    case 3:
2751 		(*(pipe->caps->multiTexCoord3fvARB))(target, f);
2752 		break;
2753 	    default:
2754 		printf(" private_dispatchMTS - blob vector length is not 1, 2 or 3. \n");
2755 		break;
2756 	    }
2757 	}
2758 	mask = mask >> 1;
2759     }
2760 }
2761 
2762 /* EOF */
2763