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: rmprim.c,v 1.15 2005/06/09 00:45:29 wes Exp $
27  * Version: $Name: OpenRM-1-6-0-2-RC2 $
28  * $Revision: 1.15 $
29  * $Log: rmprim.c,v $
30  * Revision 1.15  2005/06/09 00:45:29  wes
31  * More compiler warning fixes turned up by Windows build.
32  *
33  * Revision 1.14  2005/06/06 02:04:29  wes
34  * Lots of small additions to clean up compiler warnings.
35  *
36  * Revision 1.13  2005/05/06 16:37:31  wes
37  * Fixed buglet whereby 1D texture coords had the wrong stride assigned.
38  *
39  * Revision 1.12  2005/02/27 19:34:04  wes
40  * Added support for application supplied texture object IDs and display lists.
41  *
42  * Revision 1.11  2005/02/19 16:42:30  wes
43  * Distro sync and consolidation.
44  * Remove dead code.
45  *
46  * Revision 1.10  2005/02/12 00:55:20  wes
47  * Preliminary support for multitexturing.
48  *
49  * Revision 1.9  2005/01/23 17:08:25  wes
50  * Copyright updated to 2005.
51  * Updates to support access and use of extensions; multitexturing on all
52  * platforms, use of 3d texture extension to realize implementation of
53  * volume rendering and related functions on Windows platforms.
54  *
55  * Revision 1.8  2004/03/10 01:46:41  wes
56  * Added RM_INDEXED_QUAD_STRIP primitive type.
57  *
58  * Revision 1.7  2004/02/23 03:04:32  wes
59  * New primitives: RM_QUAD_STRIP, RM_INDEXED_TRIANGLES, RM_INDEXED_QUADS,
60  * RM_INDEXED_TRIANGLE_STRIP.
61  *
62  * Revision 1.6  2004/01/16 16:47:07  wes
63  * Updated copyright line for 2004.
64  *
65  * Revision 1.5  2003/04/05 14:13:07  wes
66  * Add code to rmNodeAddPrimitive that will leave the mutex in an unlocked
67  * state upon detection of an error condition, and premature routine exit.
68  *
69  * Revision 1.4  2003/02/14 00:18:55  wes
70  * Remove dead code.
71  *
72  * Revision 1.3  2003/02/02 17:50:57  wes
73  * Added bounding boxes to RMprimitives, as a supplement to node-level bboxes.
74  * The RMprimitive level bboxes are needed for the retained-mode CR work.
75  *
76  * Revision 1.2  2003/02/02 02:07:15  wes
77  * Updated copyright to 2003.
78  *
79  * Revision 1.1.1.1  2003/01/28 02:15:23  wes
80  * Manual rebuild of rm150 repository.
81  *
82  * Revision 1.11  2003/01/16 22:21:17  wes
83  * Updated all source files to reflect new organization of header files:
84  * all header files formerly located in include/rmaux, include/rmi, include/rmv
85  * are now located in include/rm.
86  *
87  * Revision 1.10  2003/01/11 18:44:22  wes
88  * Added global control over whether or not display lists are used during
89  * rendering by adding the new RMpipe controls rmPipeSetDisplayListEnable()
90  * and rmPipeGetDisplayListEnable().
91  *
92  * Revision 1.9  2002/12/02 16:24:56  wes
93  * Bug fixes:
94  * (1) fixed memory leak in rmPrimitiveSetText;
95  * (2) fixed problem with textProps not being applied to 2nd and later
96  * strings in an RM_TEXT text primitive.
97  *
98  * Revision 1.8  2002/09/22 17:34:06  wes
99  * Updated private_rmPrimitiveSetItem() to return the correct status to
100  * parent routines, such as rmPrimitiveSetVertex3D.
101  *
102  * Revision 1.7  2002/06/02 15:16:40  wes
103  * Added RMstateCache code to help eliminate the number of state changes
104  * made during the render traversal. The RMstateCache tracks
105  * the actual OpenGL rendering state w/o the need for querying OpenGL
106  * directly, and  is queried by draw code that then decides if any
107  * real state changes are required given the configuration of data
108  * within an RMprimitive.
109  *
110  * Revision 1.6  2002/04/30 19:33:05  wes
111  * Updated copyright dates.
112  *
113  * Revision 1.5  2001/03/31 17:12:39  wes
114  * v1.4.0-alpha-2 checkin.
115  *
116  * Revision 1.4  2000/12/03 22:33:55  wes
117  * Mods for thread-safety.
118  *
119  * Revision 1.3  2000/05/17 14:24:04  wes
120  * Added RM_POLYS (thanks to Matt and Todd of VRCO).
121  *
122  * Revision 1.2  2000/04/20 16:29:47  wes
123  * Documentation additions/enhancements, some code rearragement.
124  *
125  * Revision 1.1.1.1  2000/02/28 21:29:40  wes
126  * OpenRM 1.2 Checkin
127  *
128  * Revision 1.1.1.1  2000/02/28 17:18:48  wes
129  * Initial entry - pre-RM120 release, source base for OpenRM 1.2.
130  *
131  */
132 
133 #include <rm/rm.h>
134 #include "rmprivat.h"
135 #include <string.h>
136 
137 /*
138  * this file contains routines that interface to the RMprimitive object.
139  * the trickiest thing about primitives is that large-payload data
140  * in primitives (verts, normals, etc) are stored in "data blobs."
141  * most of the rmPrimitiveSet* routines that cache large-payload data
142  * call an internal routine that maps from the requested data type
143  * (verts, normals, indices, etc) into a "data blob" map.
144  */
145 
146 /* PRIVATE declarations */
147 RMenum private_rmPrimitiveSetItem(RMprimitive *p, int tag, int num, int stride, void *stuff, RMenum copy_flag, void (*freefunc)( void *));
148 RMenum private_rmPrimitiveSetMultiTexcoordBlob(RMprimitive *p, int tcTag, int n, int stride,  void *stuff, RMenum copyFlag, void (*freefunc)(void *), int textureUnit);
149 void private_rmPrimitiveSetCacheKey(RMprimitive *p);
150 
151 /*
152  * ----------------------------------------------------
153  * @Name rmPrimitiveNew
154  @pstart
155  RMprimitive * rmPrimitiveNew (RMenum primType)
156  @pend
157 
158  @astart
159  RMenum primType - an RMenum value specifying the RM primitive type.
160     See below for more information  (input).
161  @aend
162 
163  @dstart
164 
165  Use this routine to create a new RMprimitive object of a specified
166  type. Returns a handle to the new RMprimitive upon success, or NULL
167  upon failure.
168 
169  The current list of valid RMenum values for the primType parameter
170  are: RM_LINES, RM_LINE_STRIP, RM_TRIANGLES, RM_TRIANGLE_STRIP,
171  RM_SPHERES, RM_QUADMESH, RM_OCTMESH, RM_TEXT, RM_POINTS, RM_CONES,
172  RM_CYLINDERS, RM_INDEXED_TEXT, RM_QUADS, RM_MARKERS2D, RM_BOX3D_WIRE,
173  RM_CIRCLE2D, RM_ELLIPSE2D, RM_SPRITE, RM_TRIANGLE_FAN,
174  RM_INDEXED_TFAN, RM_POLYS, RM_QUAD_STRIP, RM_INDEXED_QUADS,
175  RM_INDEXED_TRIANGLES, RM_INDEXED_TRIANGLE_STRIP, RM_USERDEFINED_PRIM,
176  RM_APP_DISPLAYLIST.
177 
178  Some of the procedural primitives are assigned default "model flag"
179  attributes (see rmPrimitiveSetModelFlag). These are:
180 
181  RM_SPHERES: RM_SPHERES_32 produces a 32-faced sphere tesselation.
182 
183  RM_OCTMESH: RM_OCTMESH_1 produces a "full resolution" octmesh
184  primitive.
185 
186  RM_CONES: RM_CONES_16 produces a cone consisting of 16 radial
187  subdivisions.
188 
189  RM_CYLINDERS: RM_CYLINDERS_16 produces a cylinder consisting of 16
190  radial subdivisions.
191 
192  When the RMprimitive is created, it has no vertices, normals,
193  etc. and it is not associated with any scene graph node. Use
194  rmNodeAddPrimitive() to add an RMprimitive to a node.
195 
196  @dend
197  * ----------------------------------------------------
198  */
199 RMprimitive *
rmPrimitiveNew(RMenum primType)200 rmPrimitiveNew (RMenum primType)
201 {
202     void       (*rfunc)OGLPRIMPARMLIST() = NULL;
203     RMenum     (*boxFunc)(RMprimitive *);
204 
205     RMprimitive *t;
206     RMprimitiveDataBlob *b;
207     extern RMenum  RM_DEFAULT_PRIMITIVE_DISPLAY_LIST_ENABLE;
208 
209     t = private_rmPrimitiveNew();
210     if (t == NULL)
211     {
212 	rmError("rmPrimitiveNew() error: primitive malloc failure.");
213 	return(NULL);
214     }
215 
216     t->clientData = NULL;
217     t->clientDataFreeFunc = NULL;
218     t->p1 = NULL;
219 
220     t->bmin = t->bmax = NULL;
221 
222     t->flags1 = t->model_flag = 0;
223     rmPrimitiveSetDisplayListEnable(t, RM_DEFAULT_PRIMITIVE_DISPLAY_LIST_ENABLE);
224 
225     b = (RMprimitiveDataBlob *)malloc(sizeof(RMprimitiveDataBlob) * RM_MAXBLOBS_PER_PRIMITIVE);
226     memset(b, 0, sizeof(RMprimitiveDataBlob) * RM_MAXBLOBS_PER_PRIMITIVE);
227     t->blobs = b;
228 
229     /* 2/2005 multitexture support */
230     t->multiTextureCoordBlobs = NULL;
231     t->numMultiTextureCoordBlobs = 0;
232     t->multiTextureCoordBlobsMask = 0;
233 
234     private_rmPrimitiveSetType(t, primType);
235 
236     switch (primType)
237 	{
238 	case RM_APP_DISPLAYLIST:
239 	    rfunc = rmAppDisplayList;
240 	    boxFunc = private_rmPrimitiveNullBoxFunc;
241 	    break;
242 
243 	case RM_LINES:
244 	    rfunc = rmLinesDisjoint;
245 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
246 	    break;
247 
248 	case RM_LINE_STRIP:
249 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
250 	    rfunc = rmLineStrip;
251 	    break;
252 
253 	case RM_TRIANGLES:
254 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
255 	    rfunc = rmTrianglesDisjoint;
256 	    break;
257 
258 	case RM_TRIANGLE_STRIP:
259 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
260 	    rfunc = rmTrianglesConnected;
261 	    break;
262 
263 	case RM_QUAD_STRIP:
264 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
265 	    rfunc = rmQuadStrip;
266 	    break;
267 
268 	case RM_SPHERES:
269 	    rmPrimitiveSetModelFlag(t, RM_SPHERES_32);
270 	    boxFunc = private_rmPrimitiveComputeSpheresBoundingBox;
271 	    rfunc = rmSpheres;
272 	    break;
273 
274 	case RM_QUADMESH:
275 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
276 	    rfunc = rmQuadmesh;
277 	    break;
278 
279 	case RM_OCTMESH:
280 	    rmPrimitiveSetModelFlag(t, RM_OCTMESH_1);
281 	    boxFunc = private_rmPrimitiveComputeOctmeshBoundingBox;
282 	    rfunc = rmOctmesh;
283 	    break;
284 
285 	case RM_TEXT:
286 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
287 	    rfunc = rmText;
288 	    break;
289 
290 	case RM_POINTS:
291 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
292 	    rfunc = rmPoints;
293 	    break;
294 
295 	case RM_CONES:
296 	    rmPrimitiveSetModelFlag(t, RM_CONES_16);
297 	    boxFunc = private_rmPrimitiveComputeConesBoundingBox;
298 	    rfunc = rmCones;
299 	    break;
300 
301 	case RM_CYLINDERS:
302 	    rmPrimitiveSetModelFlag(t, RM_CYLINDERS_16);
303 	    boxFunc = private_rmPrimitiveComputeCylindersBoundingBox;
304 	    rfunc = rmCylinders;
305 	    break;
306 
307 	case RM_INDEXED_TEXT:
308 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
309 	    rfunc = rmIndexedText;
310 	    break;
311 
312 	case RM_QUADS:
313 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
314 	    rfunc = rmQuads;
315 	    break;
316 
317 	case RM_INDEXED_QUADS:
318 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
319 	    rfunc = rmIndexedQuads;
320 	    break;
321 
322 	case RM_INDEXED_QUAD_STRIP:
323 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
324 	    rfunc = rmIndexedQuadStrip;
325 	    break;
326 
327 	case RM_INDEXED_TRIANGLES:
328 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
329 	    rfunc = rmIndexedTriangles;
330 	    break;
331 
332 	case RM_INDEXED_TRIANGLE_STRIP:
333 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
334 	    rfunc = rmIndexedTriangleStrip;
335 	    break;
336 
337 	case RM_MARKERS2D:
338 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
339 	    rfunc = rmMarkers2D;
340 	    break;
341 
342 	case RM_BOX3D:
343 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
344 	    rfunc= rmBox3d;
345 	    break;
346 
347 	case RM_BOX3D_WIRE:
348 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
349 	    rfunc = rmBox3dWire;
350 	    break;
351 
352 	case RM_CIRCLE2D:
353 	    boxFunc = private_rmPrimitiveCompute2DCircleBoundingBox;
354 	    rfunc = rmCircle2d;
355 	    break;
356 
357 	case RM_BOX2D:
358 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
359 	    rfunc = rmBox2d;
360 	    break;
361 
362 	case RM_ELLIPSE2D:
363 	    boxFunc = private_rmPrimitiveCompute2DEllipseBoundingBox;
364 	    rfunc= rmEllipse2d;
365 	    break;
366 
367 	case RM_SPRITE:
368 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
369 	    rfunc = rmSprite;
370 	    break;
371 
372 	case RM_BITMAP:
373 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
374 	    rfunc = rmBitmap;
375 	    break;
376 
377 	case RM_INDEXED_BITMAP:
378 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
379 	    rfunc = rmIndexedBitmap;
380 	    break;
381 
382 	case RM_TRIANGLE_FAN:
383 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
384 	    rfunc = rmTriangleFan;
385 	    break;
386 
387 	case RM_INDEXED_TFAN:
388 	    rfunc = rmIndexedTriangleFan;
389 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
390 	    break;
391 
392 	case RM_POLYS:
393 	    rfunc = rmPolys;
394 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
395 	    break;
396 
397 	default:
398 	    boxFunc = private_rmPrimitiveComputeGenericBoundingBox;
399 	    break;
400 	}
401     t->primitiveComputeBoundingBoxFunc = boxFunc;
402     rmPrimitiveSetRenderFunc(t, rfunc);
403 
404     return(t);
405 }
406 
407 
408 /*
409  * ----------------------------------------------------
410  * @Name rmPrimitiveDelete
411  @pstart
412  void rmPrimitiveDelete (RMprimitive *toDelete)
413  @pend
414 
415  @astart
416 
417  RMprimitive *toDelete - a handle to an RMprimitive to delete
418     (modified).
419  @aend
420 
421  @dstart
422 
423  Use this routine to release resources associated with an RMprimitive.
424 
425  If shared data management was specified (when rmPrimitiveSetVertex3D
426  was called, for example), those application callback functions will
427  be invoked to free large-payload memory.
428 
429  @dend
430  * ----------------------------------------------------
431  */
432 void
rmPrimitiveDelete(RMprimitive * p)433 rmPrimitiveDelete (RMprimitive *p)
434 {
435     /* ignore NULL prims */
436     if (p == NULL)
437 	return;
438 
439     private_rmPrimitiveDelete(p);
440 }
441 
442 
443 /*
444  * ----------------------------------------------------
445  * @Name rmPrimitiveSetRenderFunc
446  @pstart
447  RMenum rmPrimitiveSetRenderFunc (RMprimitive *toModify,
448 			          void (*drawFunc) OGLPRIMPARMLIST() )
449  @pend
450 
451  @astart
452  RMprimitive *toModify - a handle to an RMprimitive (modified).
453 
454  void (*drawFunc) OGLPRIMPARMLIST() - a callback invoked to draw the
455     primitive (input).
456  @aend
457 
458  @dstart
459 
460  This routine assigns the draw callback to an RMprimitive. When an
461  RMprimitive is created with rmPrimitiveNew(), the draw callback is
462  automatically assigned except when rmPrimitiveNew is invoked with
463  RM_USERDEFINED_PRIM. Applications that want to assign a draw function
464  to an RMprimitive should use this function. This routine returns
465  RM_CHILL upon success, or RM_WHACKED upon failure.
466 
467  The draw callback contains raw OpenGL code that performs the
468  rendering.  The parameter list to the draw callback is represented
469  with the macro OGLPRIMPARMLIST(). At this time (June 2002), that macro
470  expands to:
471 
472  (RMprimitive *primToDraw, RMnode *owningNode, RMstate *currentRenderState, RMpipe *renderPipe, RMstateCache *internalStateCache)
473 
474  @dend
475  * ----------------------------------------------------
476  */
477 RMenum
rmPrimitiveSetRenderFunc(RMprimitive * p,void (* renderfunc)OGLPRIMPARMLIST ())478 rmPrimitiveSetRenderFunc (RMprimitive *p,
479 			  void (*renderfunc)OGLPRIMPARMLIST() )
480 {
481     if (RM_ASSERT(p, "rmPrimitiveSetRenderFunc() error: the input RMprimitive pointer is NULL.") == RM_WHACKED)
482 	return(RM_WHACKED);
483 
484     p->renderfunc = renderfunc;
485 
486     return(RM_CHILL);
487 }
488 
489 
490 /*
491  * ----------------------------------------------------
492  * @Name rmPrimitiveGetRenderFunc
493  @pstart
494  void * rmPrimitiveGetRenderFunc (const RMprimitive *toQuery)
495  @pend
496 
497  @astart
498  const RMprimitive *toQuery - a handle to the RMprimitive object to
499     query (input).
500  @aend
501 
502  @dstart
503 
504  Returns to the caller the handle to the draw callback associated with
505  the input RMprimitive.
506 
507  @dend
508  * ----------------------------------------------------
509  */
510 void *
rmPrimitiveGetRenderFunc(const RMprimitive * p)511 rmPrimitiveGetRenderFunc (const RMprimitive *p)
512 {
513     if (RM_ASSERT(p, "rmPrimitiveGetRenderFunc() error: the input RMprimitive is NULL") == RM_WHACKED)
514 	return(NULL);
515 
516     return((void *)(p->renderfunc));
517 }
518 
519 
520 /*
521  * ----------------------------------------------------
522  * @Name rmPrimitiveSetModelFlag
523  @pstart
524  RMenum rmPrimitiveSetModelFlag (RMprimitive *toModify,
525 			         int newVal)
526  @pend
527 
528  @astart
529  RMprimitive *toModify - a handle to an RMprimitive (modified).
530 
531  int newVal - an integer value specifying a new RMprimitive model flag
532     (see below for more info) (input).
533  @aend
534 
535  @dstart
536 
537  Use this routine to modify the "primitive model flag" for an
538  RMprimitive.  Returns RM_CHILL upon success or RM_WHACKED upon
539  failure.
540 
541  The RMprimitive model flag is used to control the rendering
542  resolution of primitives. Only a few RMprimitive types are eligible
543  for this kind of resolution control: RM_SPHERES, RM_CONES,
544  RM_CYLINDERS and RM_OCTMESH.
545 
546  RM_SPHERES model flags: RM_SPHERES_8, RM_SPHERES_32, RM_SPHERES_128,
547  and RM_SPHERES_512. These flags affect the tesselation resolution
548  used when rendering spheres. RM_SPHERES_8 produces an octahedron, and
549  each of the other model flags is a midpoint-subdivision refinement
550  refinement of the octahedron. The RM sphere tesselation model is
551  superior to the one in GLU for two reasons. First, the faces of the
552  tesselation are all equal in area. Second, the faces of the
553  tesselation are triangles, so there are no non-planar faces;
554  gluSphere tesselates a sphere into non-planar quads. Internally, RM
555  builds OpenGL display lists for each sphere tesselation then invokes
556  that display list at render time, positioned and scaled to the
557  specifications of the RMprimitive.
558 
559  RM_CONES and RM_CYLINDERS use the following set: RM_CONES_4,
560  RM_CONES_8, RM_CONES_12, RM_CONES_16, RM_CONES_32, RM_CONES_64, and
561  RM_CONES_128; RM_CYLINDERS_4, RM_CYLINDERS_8, RM_CYLINDERS_12,
562  RM_CYLINDERS_16, RM_CYLINDERS_32, RM_CYLINDERS_64, and
563  RM_CYLINDERS_128. The tesselation of cones and cylinders is nearly
564  identical: the ideal circle (at the base of the cone, and at each end
565  of the cylinder) is discretized with 4, 8, 12, 16, 32, 64 or 128
566  points, respectively. In the case of cones, a single triangle joints
567  each adjacent pair of sample points with the cone apex, while a
568  cylinder uses a pair of triangles to join each pair of sample points
569  between ends of the cylinder. Internally, RM builds OpenGL display
570  lists (t-fans for cones and t-strips for cylinders).
571 
572  RM_OCTMESH: RM_OCTMESH_1, RM_OCTMESH_2, RM_OCTMESH_4, RM_OCTMESH_8,
573  RM_OCTMESH_16. The octmesh primitive model flag can be considered a
574  "divide by" constant. In other words, if the base resolution of the
575  octmesh grid is 64x64x64 and RM_OCTMESH_2 is used, then the
576  resolution of the polygonalized model will be 32x32x32, but will be
577  fill the space (volume) specified by the octmesh grid. This model
578  flag can accelerate rendering of volume data on pixel-fill limited
579  systems.
580 
581  Note: the model flag values are not RMenum's - they are in fact
582  indices into internal tables.  Please don't change the #defines for
583  the the model flags.
584 
585  @dend
586  * ----------------------------------------------------
587  */
588 RMenum
rmPrimitiveSetModelFlag(RMprimitive * p,int newval)589 rmPrimitiveSetModelFlag (RMprimitive *p,
590 			 int newval)
591 {
592     if (RM_ASSERT(p, "rmPrimitiveSetModelFlag() error: the input RMprimitive is NULL") == RM_WHACKED)
593 	return(RM_WHACKED);
594 
595     p->model_flag = newval;
596 
597     return(RM_CHILL);
598 }
599 
600 
601 /*
602  * ----------------------------------------------------
603  * @Name rmPrimitiveGetModelFlag
604  @pstart
605  int rmPrimitiveGetModelFlag (const RMprimitive *toQuery)
606  @pend
607 
608  @astart
609 
610  const RMprimitive *toQuery - a handle to an RMprimitive to query
611     (input).
612  @aend
613 
614  @dstart
615 
616  Returns to the caller the current primitive model flag associated
617  with the RMprimitive object.
618 
619  RM_WHACKED is returned for RMprimitives that don't know about model
620  flags.
621 
622  @dend
623  * ----------------------------------------------------
624  */
625 int
rmPrimitiveGetModelFlag(const RMprimitive * p)626 rmPrimitiveGetModelFlag (const RMprimitive *p)
627 {
628     int rstat;
629 
630     if (RM_ASSERT(p, "rmPrimitiveGetModelFlag() error: the input RMprimitive is NULL. \n") == RM_WHACKED)
631 	return(RM_WHACKED);
632 
633     switch(private_rmPrimitiveGetType(p))
634 	{
635 	case RM_LINES:
636 	case RM_LINE_STRIP:
637 	case RM_TRIANGLES:
638 	case RM_TRIANGLE_STRIP:
639 	case RM_TRIANGLE_FAN:
640 	case RM_QUADMESH:
641 	case RM_POINTS:
642 	case RM_BOX3D:
643 	case RM_BOX3D_WIRE:
644 	case RM_TEXT:
645 	case RM_INDEXED_TEXT:
646 	case RM_QUADS:
647 	case RM_MARKERS2D:
648 	case RM_BOX2D:
649 	case RM_SPRITE:
650 	case RM_BITMAP:
651 	case RM_INDEXED_BITMAP:
652 	case RM_POLYS:
653 	case RM_QUAD_STRIP:
654 	case RM_INDEXED_TFAN:
655 	case RM_INDEXED_QUADS:
656 	case RM_INDEXED_QUAD_STRIP:
657 	case RM_INDEXED_TRIANGLES:
658 	case RM_INDEXED_TRIANGLE_STRIP:
659 	case RM_USERDEFINED_PRIM:
660 	    rstat = (int)RM_WHACKED;
661 	    break;
662 
663 	case RM_ELLIPSE2D:
664 	case RM_CIRCLE2D:
665 	case RM_OCTMESH:
666 	case RM_CONES:
667 	case RM_CYLINDERS:
668 	case RM_SPHERES:
669 	    rstat = private_rmPrimitiveGetModelFlag(p);
670 	    break;
671 
672 	default: /* bogus prim type */
673 	    rstat = (int)RM_WHACKED;
674 	    break;
675 	}
676     return(rstat);
677 }
678 
679 /*
680  * ----------------------------------------------------
681  * @Name rmPrimitiveComputeBoundingBox
682  @pstart
683  RMenum rmPrimitiveComputeBoundingBox (RMprimitive *toModify)
684  @pend
685 
686  @astart
687 
688  RMprimitive *toModify - a handle to an RMprimitive (modified).
689 
690  @aend
691 
692  @dstart
693 
694  Use this routine to automatically compute an RMprimitive's bounding box.
695  This routine returns RM_CHILL upon success, or RM_WHACKED upon failure.
696  Failure will occur if the input RMprimitive is NULL.
697 
698  See the description of rmPrimitiveSetBoundingBox for more details about
699  when an RMprimitive's bounding box should be set, or computed, as well
700  as discussion about the relationship between the RMprimitive and RMnode
701  bounding boxes. Use rmPrimitiveGetBoundingBox() to obtain an RMprimitive's
702  bounding box.
703 
704  @dend
705  * ----------------------------------------------------
706  */
707 RMenum
rmPrimitiveComputeBoundingBox(RMprimitive * p)708 rmPrimitiveComputeBoundingBox(RMprimitive *p)
709 {
710     if (RM_ASSERT(p, "rmPrimitiveComputeBoundingBox() error: the input RMprimitive is NULL.") == RM_WHACKED)
711 	return(RM_WHACKED);
712 
713     if (p->primitiveComputeBoundingBoxFunc == NULL)
714 	return RM_WHACKED;
715 
716     return ((*p->primitiveComputeBoundingBoxFunc)(p));
717 }
718 
719 /*
720  * ----------------------------------------------------
721  * @Name rmPrimitiveSetBoundingBox
722  @pstart
723  RMenum rmPrimitiveSetBoundingBox (RMprimitive *toModify, const RMvertex3D *bmin, const RMvertex3D *bmax)
724  @pend
725 
726  @astart
727 
728  RMprimitive *toModify - a handle to an RMprimitive (modified).
729  const RMvertex3D *bmin, *bmax - handles to RMvertex3D's.
730 
731  @aend
732 
733  @dstart
734 
735  Use this routine to explicitly set the bounding box at an RMprimitive. The
736  bounding box of the RMprimitive toModify will be set to the RMvertex3D
737  values specified in the input parameters bmin and bmax. Returns RM_CHILL
738  upon success, or RM_WHACKED upon failure. If bmin or bmax are NULL, those
739  portions of the RMprimitive's bounding box are removed, leaving the
740  bounding box in an undefined and uninitialized state.
741 
742  The RMprimitive's bounding box is automatically computed by RM in the
743  following circumstances:
744  1. list them
745 
746  The relationship between the RMprimitive and RMnode bounding box is ...
747 
748  @dend
749  * ----------------------------------------------------
750  */
751 RMenum
rmPrimitiveSetBoundingBox(RMprimitive * p,const RMvertex3D * bmin,const RMvertex3D * bmax)752 rmPrimitiveSetBoundingBox(RMprimitive *p,
753 			  const RMvertex3D *bmin,
754 			  const RMvertex3D *bmax)
755 {
756     if (RM_ASSERT(p, "rmPrimitiveSetBoundingBox() error: the input RMprimitive is NULL.") == RM_WHACKED)
757 	return(RM_WHACKED);
758 
759     if (p->bmin != NULL)
760 	free((void *)(p->bmin));
761 
762     if (bmin != NULL)
763     {
764 	p->bmin = rmVertex3DNew(1);
765 	*(p->bmin) = *bmin;
766     }
767 
768     if (p->bmax != NULL)
769 	free((void *)(p->bmax));
770 
771     if (bmax != NULL)
772     {
773 	p->bmax = rmVertex3DNew(1);
774 	*(p->bmax) = *bmax;
775     }
776 
777     return RM_CHILL;
778 }
779 
780 /*
781  * ----------------------------------------------------
782  * @Name rmPrimitiveGetBoundingBox
783  @pstart
784  RMenum rmPrimitiveGetBoundingBox (const RMprimitive *toQuery, RMvertex3D *bminReturn, RMvertex3D *bmaxReturn)
785  @pend
786 
787  @astart
788  const RMprimitive *toQuery - a handle to an RMprimitive (input).
789 
790  RMvertex3D *bminReturn, *bmaxReturn;
791  @aend
792 
793  @dstart
794 
795  Use this routine to obtain an RMprimitive's bounding box. Upon success,
796  RM_CHILL is returned, and the bounding box minimum and maximum are copied
797  into the application-supplied RMvertex3D parameters. If either of the
798  RMprimitive's minimum or maximum bounding box parameters are NULL (i.e.,
799  they have not been initialized), this routine will return RM_WHACKED.
800 
801  The application can request one, or both, of the bounding box minimum or
802  maximum values. In other words, the application may specify NULL for
803  either of the minimum or maximum bounding box return parameters.
804 
805  @dend
806  * ----------------------------------------------------
807  */
808 RMenum
rmPrimitiveGetBoundingBox(const RMprimitive * p,RMvertex3D * bmin,RMvertex3D * bmax)809 rmPrimitiveGetBoundingBox(const RMprimitive *p,
810 			  RMvertex3D *bmin,
811 			  RMvertex3D *bmax)
812 {
813     if (RM_ASSERT(p, "rmPrimitiveGetBoundingBox() error: the input RMprimitive is NULL.") == RM_WHACKED)
814 	return(RM_WHACKED);
815 
816     if (p->bmin == NULL)
817 	return RM_WHACKED;
818 
819     if (bmin != NULL)
820 	*bmin = *(p->bmin);
821 
822     if (p->bmax == NULL)
823 	return RM_WHACKED;
824 
825     if (bmax != NULL)
826 	*bmax = *(p->bmax);
827 
828     return RM_CHILL;
829 }
830 
831 
832 /*
833  * ----------------------------------------------------
834  * @Name rmPrimitiveGetType
835  @pstart
836  RMenum rmPrimitiveGetType (const RMprimitive *toQuery)
837  @pend
838 
839  @astart const RMprimitive *toQuery - a handle to an RMprimitive
840     (input).
841  @aend
842 
843  @dstart
844 
845  Returns to the caller the input RMprimitive's "type" RMenum
846  attribute.  RM_WHACKED is returned if the input RMprimitive is
847  NULL. For a list of RMprimitive type enums, please see
848  rmPrimitiveNew().
849 
850  @dend
851  * ----------------------------------------------------
852  */
853 RMenum
rmPrimitiveGetType(const RMprimitive * t)854 rmPrimitiveGetType (const RMprimitive *t)
855 {
856     if (RM_ASSERT(t, "rmPrimitiveGetType() error: the input RMprimitive is NULL.") == RM_WHACKED)
857 	return(RM_WHACKED);
858 
859     return(private_rmPrimitiveGetType(t));
860 }
861 
862 
863 /*
864  * ----------------------------------------------------
865  * @Name rmPrimitiveSetClientData
866  @pstart
867  RMenum rmPrimitiveSetClientData (RMprimitive *toModify,
868 			          void *clientData,
869 				  void (*cdFreeFunc)(RMprimitive *,void *))
870  @pend
871 
872  @astart
873  RMprimitive *toModify - a handle to an RMprimitive (modified).
874 
875  void *clientData - a handle (input).
876 
877  void (*cdFreeFunc)(RMprimitive *, void *) - a handle to an application
878     callback (input).
879  @aend
880 
881  @dstart
882 
883  This routine stores a memory handle (pointer) in an RMprimitive,
884  returning RM_CHILL upon success or RM_WHACKED upon failure. RM
885  basically ignores this handle; it's use, management and so forth is
886  entirely under control of the application. This is a simple mechanism
887  for applications to store a memory handle in an RMprimitive for
888  subsequent use in an application-specific manner.
889 
890  Client data may be stored in both RMprimitives and RMnodes
891  (rmNodeSetClientData).
892 
893  The "client data" handle may be later accessed using
894  rmPrimitiveGetClientData.
895 
896  The callback function will be invoked when the RMprimitive is
897  deleted.  The callback takes two parameters, a handle to the
898  RMprimitive containing the client data handle, and the client data
899  handle itself. The callback is provided so that applications may
900  delete the data referenced by the client data handle stored in the
901  RMprimitive.
902 
903  When the input client data handle is NULL, the old handle value is
904  effectively overwritten. Any memory pointed to by the old client data
905  handle will be lost (a potential memory leak).
906 
907  @dend
908  * ----------------------------------------------------
909  */
910 RMenum
rmPrimitiveSetClientData(RMprimitive * p,void * cd,void (* cd_free_func)(RMprimitive *,void *))911 rmPrimitiveSetClientData (RMprimitive *p,
912 			  void *cd,
913 			  void (*cd_free_func)(RMprimitive *,void *))
914 {
915     if (RM_ASSERT(p, "rmPrimitiveSetClientData() error: the input RMprimitive is NULL") == RM_WHACKED)
916 	return(RM_WHACKED);
917 
918     p->clientData = cd;
919     p->clientDataFreeFunc = cd_free_func;
920 
921     return(RM_CHILL);
922 }
923 
924 
925 /*
926  * ----------------------------------------------------
927  * @Name rmPrimitiveGetClientData
928  @pstart
929  void * rmPrimitiveGetClientData (const RMprimitive *toQuery)
930  @pend
931 
932  @astart
933  const RMprimitive *toQuery - a handle to an RMprimitive (input).
934  @aend
935 
936  @dstart
937 
938  Use this routine to obtain the client data handle stored in an
939  RMprimitive.
940 
941  @dend
942  * ----------------------------------------------------
943  */
944 void *
rmPrimitiveGetClientData(const RMprimitive * p)945 rmPrimitiveGetClientData (const RMprimitive *p)
946 {
947     if (RM_ASSERT(p, "rmPrimitiveGetClientData() error: the input RMprimitive is NULL") == RM_WHACKED)
948 	return((void *)NULL);
949 
950     return(p->clientData);
951 }
952 
953 
954 /*
955  * ----------------------------------------------------
956  * @Name rmPrimitiveSetVertex2D
957  @pstart
958  RMenum rmPrimitiveSetVertex2D (RMprimitive *toModify,
959 		                int nVertices,
960 			        RMvertex2D *vertexData,
961 			        RMenum copyEnum,
962 			        void (*appFreeFunc)(void *))
963  @pend
964 
965  @astart
966  RMprimitive *toModify - a handle to an RMprimitive (modified).
967 
968  int nVertices - an integer value, specifies the number of vertices
969     that will be assigned to the RMprimitive (input).
970 
971  RMvertex2D *vertexData - a handle to a flat array of RMvertex2D
972     objects (input).
973 
974  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
975     RM_DONT_COPY_DATA (input).
976 
977  void (*appFreeFunc)(void *) - a handle to an application
978     callback. When "copyEnum" is RM_DONT_COPY_DATA, the application
979     must provide a callback used to release memory when the
980     RMprimitive is delete (input).
981  @aend
982 
983  @dstart
984 
985  rmPrimitiveSetVertex2D is one of a family of routines used to assign
986  data to RMprimitives. This routine assigns raw 2D vertex data to an
987  RMprimitive, returning RM_CHILL upon success or RM_WHACKED upon
988  failure.
989 
990  When "copyEnum" is set to RM_COPY_DATA, RM will make a copy of the
991  raw vertex data provided in "vertexData." When "copyEnum" is set to
992  RM_DONT_COPY_DATA, RM will not make a copy of the RMvertex2D data,
993  but instead will simply copy the handle "vertexData" into the
994  RMprimitive, and refer to the caller-supplied memory directly in
995  later operations.
996 
997  When RM_DONT_COPY_DATA is specified, applications must supply a
998  callback function that will be invoked when the RMvertex2D data in an
999  RMprimitive is deleted. Such deletion occurs when the RMprimitive
1000  itself is deleted, the RMnode containing the RMprimitive is deleted
1001  (if the RMprimitive was assigned to an RMnode with rmNodeAddChild()),
1002  or if new RMvertex2D is assigned (more precisely, if new vertex data
1003  is assigned, regardless of whether or not it is 3D or 2D).  The
1004  application callback takes a single parameter: a handle to the
1005  underlying data array that is managed by the application.
1006 
1007  There is no corresponding "get vertex" routine. Primitive vertex data
1008  should be considered write-only by the application.
1009 
1010  @dend
1011  * ----------------------------------------------------
1012  */
1013 RMenum
rmPrimitiveSetVertex2D(RMprimitive * p,int n,RMvertex2D * v,RMenum copy_flag,void (* freefunc)(void *))1014 rmPrimitiveSetVertex2D (RMprimitive *p,
1015 		        int n,
1016 		        RMvertex2D *v,
1017 		        RMenum copy_flag,
1018 		        void (*freefunc)(void *))
1019 {
1020     if ((private_rmPrimSetAssert(p, n, (void *)v, copy_flag, freefunc, "rmPrimitiveSetVertex2D")) == RM_WHACKED)
1021         return(RM_WHACKED);
1022 
1023     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_2DVERTICES, n, sizeof(RMvertex2D), (void *)v, copy_flag, freefunc));
1024 }
1025 
1026 
1027 /*
1028  * ----------------------------------------------------
1029  * @Name rmPrimitiveSetVertex3D
1030  @pstart
1031  RMenum rmPrimitiveSetVertex3D (RMprimitive *toModify,
1032 		                int nVertices,
1033 			        RMvertex3D *vertexData,
1034 			        RMenum copyEnum,
1035 			        void (*appFreeFunc)(void *))
1036  @pend
1037 
1038  @astart
1039  RMprimitive *toModify - a handle to an RMprimitive (modified).
1040 
1041  int nVertices - an integer value, specifies the number of vertices
1042     that will be assigned to the RMprimitive (input).
1043 
1044  RMvertex3D *vertexData - a handle to a flat array of RMvertex3D
1045     objects (input).
1046 
1047  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
1048     RM_DONT_COPY_DATA (input).
1049 
1050  void (*appFreeFunc)(void *) - a handle to an application
1051     callback. When "copyEnum" is RM_DONT_COPY_DATA, the application
1052     must provide a callback used to release memory when the
1053     RMprimitive is delete (input).
1054  @aend
1055 
1056  @dstart
1057 
1058  rmPrimitiveSetVertex3D is one of a family of routines used to assign
1059  data to RMprimitives. This routine assigns raw 3D vertex data to an
1060  RMprimitive, returning RM_CHILL upon success or RM_WHACKED upon
1061  failure.
1062 
1063  When "copyEnum" is set to RM_COPY_DATA, RM will make a copy of the
1064  raw vertex data provided in "vertexData." When "copyEnum" is set to
1065  RM_DONT_COPY_DATA, RM will not make a copy of the RMvertex3D data,
1066  but instead will simply copy the handle "vertexData" into the
1067  RMprimitive, and refer to the caller-supplied memory directly in
1068  later operations.
1069 
1070  When RM_DONT_COPY_DATA is specified, applications must supply a
1071  callback function that will be invoked when the RMvertex3D data in an
1072  RMprimitive is deleted. Such deletion occurs when the RMprimitive
1073  itself is deleted, the RMnode containing the RMprimitive is deleted
1074  (if the RMprimitive was assigned to an RMnode with rmNodeAddChild()),
1075  or if new RMvertex3D is assigned (more precisely, if new vertex data
1076  is assigned, regardless of whether or not it is 3D or 2D).  The
1077  application callback takes a single parameter: a handle to the
1078  underlying data array that is managed by the application.
1079 
1080  There is no corresponding "get vertex" routine. Primitive vertex data
1081  should be considered write-only by the application.
1082 
1083  NOTE: some compilers enforce 8-byte alignment/padding of C
1084  structures.  Since the RMvertex3D object consists of 3 floats, some
1085  compilers will pad memory to produce 8-byte alignment. The underlying
1086  RM data management infrastructure accomodates this added
1087  complexity. However, on such systems, callers that pass in a flat
1088  array of floats cast to RMvertex3D * should be aware that the data is
1089  considered to be a flat array of RMvertex3D objects inside this
1090  routine, not a flat array of floats.
1091 
1092  @dend
1093  * ----------------------------------------------------
1094  */
1095 RMenum
rmPrimitiveSetVertex3D(RMprimitive * p,int n,RMvertex3D * v,RMenum copy_flag,void (* freefunc)(void *))1096 rmPrimitiveSetVertex3D (RMprimitive *p,
1097 		        int n,
1098 		        RMvertex3D *v,
1099 		        RMenum copy_flag,
1100 		        void (*freefunc)(void *))
1101 {
1102     if ((private_rmPrimSetAssert(p, n, (void *)v, copy_flag, freefunc, "rmPrimitiveSetVertex3D")) == RM_WHACKED)
1103         return(RM_WHACKED);
1104 
1105     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_3DVERTICES, n, sizeof(RMvertex3D), (void *)v, copy_flag, freefunc));
1106 }
1107 
1108 
1109 /*
1110  * ----------------------------------------------------
1111  * @Name rmPrimitiveSetColor3D
1112  @pstart
1113  RMenum rmPrimitiveSetColor3D (RMprimitive *toModify,
1114 		               int nColors,
1115 			       RMcolor3D *colorData,
1116 			       RMenum copyEnum,
1117 			       void (*appFreeFunc)(void *))
1118  @pend
1119 
1120  @astart
1121  RMprimitive *toModify - a handle to an RMprimitive (modified).
1122 
1123  int nColors - an integer value, specifies the number of 3-component
1124     colors that will be assigned to the RMprimitive (input).
1125 
1126  RMcolor3D *vertexData - a handle to a flat array of RMcolor3D objects
1127     (input).
1128 
1129  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
1130     RM_DONT_COPY_DATA (input).
1131 
1132  void (*appFreeFunc)(void *) - a handle to an application
1133     callback. When "copyEnum" is RM_DONT_COPY_DATA, the application
1134     must provide a callback used to release memory when the
1135     RMprimitive is delete (input).
1136  @aend
1137 
1138  @dstart
1139 
1140  rmPrimitiveSetColor3D is one of a family of routines used to assign
1141  data to RMprimitives. This routine assigns raw 3-component color data
1142  to an RMprimitive, returning RM_CHILL upon success or RM_WHACKED upon
1143  failure.
1144 
1145  When "copyEnum" is set to RM_COPY_DATA, RM will make a copy of the
1146  raw color data provided in "colorData." When "copyEnum" is set to
1147  RM_DONT_COPY_DATA, RM will not make a copy of the RMcolor3D data, but
1148  instead will simply copy the handle "colorData" into the RMprimitive,
1149  and refer to the caller-supplied memory directly in later operations.
1150 
1151  When RM_DONT_COPY_DATA is specified, applications must supply a
1152  callback function that will be invoked when the RMcolor3D data in an
1153  RMprimitive is deleted. Such deletion occurs when the RMprimitive
1154  itself is deleted, the RMnode containing the RMprimitive is deleted
1155  (if the RMprimitive was assigned to an RMnode with rmNodeAddChild()),
1156  or if new RMcolor3D is assigned (more precisely, if new color data is
1157  assigned, regardless of whether or not it is 3D or 4D).  The
1158  application callback takes a single parameter: a handle to the
1159  underlying data array that is managed by the application.
1160 
1161  There is no corresponding "get colors" routine. Primitive color data
1162  should be considered write-only by the application.
1163 
1164  NOTE: some compilers enforce 8-byte alignment/padding of C
1165  structures.  Since the RMcolor3D object consists of 3 floats, some
1166  compilers will pad memory to produce 8-byte alignment. The underlying
1167  RM data management infrastructure accomodates this added
1168  complexity. However, on such systems, callers that pass in a flat
1169  array of floats cast to RMcolor3D * should be aware that the data is
1170  considered to be a flat array of RMcolor3D objects inside this
1171  routine, not a flat array of floats.
1172 
1173  In RM, 3-component color data is RGB. 4-component colors are RGBA.
1174 
1175  @dend
1176  * ----------------------------------------------------
1177  */
1178 RMenum
rmPrimitiveSetColor3D(RMprimitive * p,int n,RMcolor3D * v,RMenum copy_flag,void (* freefunc)(void *))1179 rmPrimitiveSetColor3D (RMprimitive *p,
1180 		       int n,
1181 		       RMcolor3D *v,
1182 		       RMenum copy_flag,
1183 		       void (*freefunc)(void *))
1184 {
1185     if ((private_rmPrimSetAssert(p, n, (void *)v, copy_flag, freefunc, "rmPrimitiveSetColor3D")) == RM_WHACKED)
1186         return(RM_WHACKED);
1187 
1188     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_3COLORS, n, sizeof(RMvertex3D), (void *)v, copy_flag, freefunc));
1189 }
1190 
1191 
1192 /*
1193  * ----------------------------------------------------
1194  * @Name rmPrimitiveSetColor4D
1195  @pstart
1196  RMenum rmPrimitiveSetColor4D (RMprimitive *toModify,
1197 		               int nColors,
1198 			       RMcolor4D *colorData,
1199 			       RMenum copyEnum,
1200 			       void (*appFreeFunc)(void *))
1201  @pend
1202 
1203  @astart
1204  RMprimitive *toModify - a handle to an RMprimitive (modified).
1205 
1206  int nColors - an integer value, specifies the number of 3-component
1207     colors that will be assigned to the RMprimitive (input).
1208 
1209  RMvertex4D *vertexData - a handle to a flat array of RMcolor4D
1210     objects (input).
1211 
1212  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
1213     RM_DONT_COPY_DATA (input).
1214 
1215  void (*appFreeFunc)(void *) - a handle to an application
1216     callback. When "copyEnum" is RM_DONT_COPY_DATA, the application
1217     must provide a callback used to release memory when the
1218     RMprimitive is delete (input).
1219  @aend
1220 
1221  @dstart
1222 
1223  rmPrimitiveSetColor4D is one of a family of routines used to assign
1224  data to RMprimitives. This routine assigns raw 4-component color data
1225  to an RMprimitive, returning RM_CHILL upon success or RM_WHACKED upon
1226  failure.
1227 
1228  When "copyEnum" is set to RM_COPY_DATA, RM will make a copy of the
1229  raw color data provided in "colorData." When "copyEnum" is set to
1230  RM_DONT_COPY_DATA, RM will not make a copy of the RMcolor4D data, but
1231  instead will simply copy the handle "colorData" into the RMprimitive,
1232  and refer to the caller-supplied memory directly in later operations.
1233 
1234  When RM_DONT_COPY_DATA is specified, applications must supply a
1235  callback function that will be invoked when the RMcolor4D data in an
1236  RMprimitive is deleted. Such deletion occurs when the RMprimitive
1237  itself is deleted, the RMnode containing the RMprimitive is deleted
1238  (if the RMprimitive was assigned to an RMnode with rmNodeAddChild()),
1239  or if new RMcolor4D is assigned (more precisely, if new color data is
1240  assigned, regardless of whether or not it is 3D or 4D).  The
1241  application callback takes a single parameter: a handle to the
1242  underlying data array that is managed by the application.
1243 
1244  There is no corresponding "get colors" routine. Primitive color data
1245  should be considered write-only by the application.
1246 
1247  In RM, 3-component color data is RGB. 4-component colors are RGBA.
1248 
1249  @dend
1250  * ----------------------------------------------------
1251  */
1252 RMenum
rmPrimitiveSetColor4D(RMprimitive * p,int n,RMcolor4D * v,RMenum copy_flag,void (* freefunc)(void *))1253 rmPrimitiveSetColor4D (RMprimitive *p,
1254 		       int n,
1255 		       RMcolor4D *v,
1256 		       RMenum copy_flag,
1257 		       void (*freefunc)(void *))
1258 {
1259     if ((private_rmPrimSetAssert(p, n, (void *)v, copy_flag, freefunc, "rmPrimitiveSetColor4D")) == RM_WHACKED)
1260         return(RM_WHACKED);
1261 
1262     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_4COLORS, n, sizeof(RMvertex4D), (void *)v, copy_flag, freefunc));
1263 }
1264 
1265 
1266 /*
1267  * ----------------------------------------------------
1268  * @Name  rmPrimitiveSetRadii
1269  @pstart
1270  RMenum rmPrimitiveSetRadii (RMprimitive *toModify,
1271 		             int nRadii,
1272 			     float *radii,
1273 			     RMenum copyEnum,
1274 			     void (*freeFunc)(void *))
1275  @pend
1276 
1277  @astart
1278  RMprimitive *toModify - a handle to an RMprimitive (modified).
1279 
1280  int nRadii - an integer values specifying the number of input radius
1281     values, the length of the radii[] array (input).
1282 
1283  float *radii - a flat array of floating point values (input).
1284 
1285  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
1286     RM_DONT_COPY_DATA (input).
1287 
1288  void (*freeFunc)(void *) - a handle to an application callback,
1289     required when copyEnum is RM_DONT_COPY_DATA (input).
1290  @aend
1291 
1292  @dstart
1293 
1294  Use this routine to assign radius values to RMprimitives. Radius
1295  values are used by sphere, cone and cylinder primitives. Returns
1296  RM_CHILL upon success, or RM_WHACKED upon failure.
1297 
1298  When "copyEnum" is set to RM_COPY_DATA, RM will make a copy of the
1299  raw radius data provided in "radii." When "copyEnum" is set to
1300  RM_DONT_COPY_DATA, RM will not make a copy of the radius data, but
1301  instead will simply copy the handle "colorData" into the RMprimitive,
1302  and refer to the caller-supplied memory directly in later operations.
1303 
1304  When RM_DONT_COPY_DATA is specified, applications must supply a
1305  callback function that will be invoked when the radius data in an
1306  RMprimitive is deleted. Such deletion occurs when the RMprimitive
1307  itself is deleted, the RMnode containing the RMprimitive is deleted
1308  (if the RMprimitive was assigned to an RMnode with rmNodeAddChild()),
1309  or if new radius is assigned.  The application callback takes a
1310  single parameter: a handle to the underlying data array that is
1311  managed by the application.
1312 
1313  There is no corresponding "get radii" routine. Primitive radius data
1314  should be considered write-only by the application.
1315 
1316  @dend
1317  * ----------------------------------------------------
1318  */
1319 RMenum
rmPrimitiveSetRadii(RMprimitive * p,int n,float * r,RMenum copy_flag,void (* freefunc)(void *))1320 rmPrimitiveSetRadii (RMprimitive *p,
1321 		     int n,
1322 		     float *r,
1323 		     RMenum copy_flag,
1324 		     void (*freefunc)(void *))
1325 {
1326     if (( private_rmPrimSetAssert(p, n, (void *)r, copy_flag, freefunc, "rmPrimitiveSetRadii")) ==RM_WHACKED)
1327         return(RM_WHACKED);
1328 
1329     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_RADII, n, sizeof(float), (void *)r, copy_flag, freefunc));
1330 }
1331 
1332 
1333 /*
1334  * ----------------------------------------------------
1335  * @Name rmPrimitiveSetNormal3D
1336  @pstart
1337  RMenum rmPrimitiveSetNormal3D (RMprimitive *toModify,
1338 		                int nNormals,
1339 			        RMvertex3D *normalsData,
1340 			        RMenum copyEnum,
1341 			        void (*freeFunc)(void *))
1342  @pend
1343 
1344  @astart
1345  RMprimitive *toModify - a handle to an RMprimitive to modify
1346     (modified).
1347 
1348  int nNormals - an integer value specifying the number of input
1349     normals in the normals[] array (input).
1350 
1351  RMvertex3D *normalsData - a handle to an RMvertex3D array (input).
1352 
1353  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
1354     RM_DONT_COPY_DATA (input).
1355 
1356  void (*freeFunc)(void *) - a handle to an application callback,
1357     required when copyEnum is RM_DONT_COPY_DATA (input).
1358  @aend
1359 
1360  @dstart
1361 
1362  This routine is used to assign a flat array of normals to an
1363  RMprimitive, returning RM_CHILL upon success or RM_WHACKED upon
1364  failure.  In most instances, per-vertex normals are required. Quads
1365  and disjoint triangle primitives allow per-face normals.
1366 
1367  When "copyEnum" is set to RM_COPY_DATA, RM will make a copy of the
1368  raw normals data provided in "normalsData." When "copyEnum" is set to
1369  RM_DONT_COPY_DATA, RM will not make a copy of the RMvertex3D data,
1370  but instead will simply copy the handle "normalsData" into the
1371  RMprimitive, and refer to the caller-supplied memory directly in
1372  later operations.
1373 
1374  When RM_DONT_COPY_DATA is specified, applications must supply a
1375  callback function that will be invoked when the RMvertex3D data in an
1376  RMprimitive is deleted. Such deletion occurs when the RMprimitive
1377  itself is deleted, the RMnode containing the RMprimitive is deleted
1378  (if the RMprimitive was assigned to an RMnode with rmNodeAddChild()),
1379  or if new RMvertex3D is assigned.  The application callback takes a
1380  single parameter: a handle to the underlying data array that is
1381  managed by the application.
1382 
1383  There is no corresponding "get normals" routine. Primitive normal
1384  data should be considered write-only by the application.
1385 
1386  NOTE: some compilers enforce 8-byte alignment/padding of C
1387  structures.  Since the RMvertex3D object consists of 3 floats, some
1388  compilers will pad memory to produce 8-byte alignment. The underlying
1389  RM data management infrastructure accomodates this added
1390  complexity. However, on such systems, callers that pass in a flat
1391  array of floats cast to RMvertex3D * should be aware that the data is
1392  considered to be a flat array of RMvertex3D objects inside this
1393  routine, not a flat array of floats.
1394 
1395  @dend
1396  * ----------------------------------------------------
1397  */
1398 RMenum
rmPrimitiveSetNormal3D(RMprimitive * p,int n,RMvertex3D * r,RMenum copy_flag,void (* freefunc)(void *))1399 rmPrimitiveSetNormal3D (RMprimitive *p,
1400 		        int n,
1401 		        RMvertex3D *r,
1402 		        RMenum copy_flag,
1403 		        void (*freefunc)(void *))
1404 {
1405     if (( private_rmPrimSetAssert(p, n, (void *)r, copy_flag, freefunc, "rmPrimitiveSetNormal3D")) == RM_WHACKED)
1406         return(RM_WHACKED);
1407 
1408     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_NORMALS, n, sizeof(RMvertex3D), (void *)r, copy_flag, freefunc));
1409 }
1410 
1411 
1412 /*
1413  * ----------------------------------------------------
1414  * @Name rmPrimitiveSetTexcoord1D
1415  @pstart
1416  RMenum rmPrimitiveSetTexcoord1D (RMprimitive *toModify,
1417 		                  int nTexCoords,
1418 				  float *texCoordData,
1419 				  RMenum copyEnum,
1420 				  void (*appFreeFunc)(void *))
1421  @pend
1422 
1423  @astart
1424  RMprimitive *toModify - a handle to an RMprimitive (modified).
1425 
1426  int nTexCoords - an integer value, specifies the number of 1D texture
1427     coordinates that will be assigned to the RMprimitive (input).
1428 
1429  float *texCoordData - a handle to a flat array of float (input).
1430 
1431  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
1432     RM_DONT_COPY_DATA (input).
1433 
1434  void (*appFreeFunc)(void *) - a handle to an application
1435     callback. When "copyEnum" is RM_DONT_COPY_DATA, the application
1436     must provide a callback used to release memory when the
1437     RMprimitive is delete (input).
1438  @aend
1439 
1440  @dstart
1441 
1442  rmPrimitiveSetTexcoord1D is one of a family of routines used to
1443  assign data to RMprimitives. This routine assigns 1D texture
1444  coordinates to an RMprimitive, returning RM_CHILL upon success or
1445  RM_WHACKED upon failure.
1446 
1447  When "copyEnum" is set to RM_COPY_DATA, RM will make a copy of the
1448  raw vertex data provided in "texCoordData." When "copyEnum" is set to
1449  RM_DONT_COPY_DATA, RM will not make a copy of the float data,
1450  but instead will simply copy the handle "texCoordData" into the
1451  RMprimitive, and refer to the caller-supplied memory directly in
1452  later operations.
1453 
1454  When RM_DONT_COPY_DATA is specified, applications must supply a
1455  callback function that will be invoked when the texture coordinate
1456  data in an RMprimitive is deleted. Such deletion occurs when the
1457  RMprimitive itself is deleted, the RMnode containing the RMprimitive
1458  is deleted (if the RMprimitive was assigned to an RMnode with
1459  rmNodeAddChild()), or if new texture coordinate data is assigned.
1460  The application callback takes a single parameter: a handle to the
1461  underlying data array that is managed by the application.
1462 
1463  There is no corresponding "get texture coordinate" routine. Primitive
1464  vertex data should be considered write-only by the application.
1465 
1466  @dend
1467  * ----------------------------------------------------
1468  */
1469 RMenum
rmPrimitiveSetTexcoord1D(RMprimitive * p,int n,float * r,RMenum copy_flag,void (* freefunc)(void *))1470 rmPrimitiveSetTexcoord1D (RMprimitive *p,
1471 			  int n,
1472 			  float *r,
1473 			  RMenum copy_flag,
1474 			  void (*freefunc)(void *))
1475 {
1476     if ((private_rmPrimSetAssert(p, n, (void *)r, copy_flag, freefunc, "rmPrimitiveSetTexcoord1D")) == RM_WHACKED)
1477 	return(RM_WHACKED);
1478 
1479     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_1DTCOORDS, n, sizeof(float), (void *)r, copy_flag, freefunc));
1480 }
1481 
1482 /*
1483  * ----------------------------------------------------
1484  * @Name rmPrimitiveSetTexcoord2D
1485  @pstart
1486  RMenum rmPrimitiveSetTexcoord2D (RMprimitive *toModify,
1487 		                  int nTexCoords,
1488 				  RMvertex2D *texCoordData,
1489 				  RMenum copyEnum,
1490 				  void (*appFreeFunc)(void *))
1491  @pend
1492 
1493  @astart
1494  RMprimitive *toModify - a handle to an RMprimitive (modified).
1495 
1496  int nTexCoords - an integer value, specifies the number of 2D texture
1497     coordinates that will be assigned to the RMprimitive (input).
1498 
1499  RMvertex2D *texCoordData - a handle to a flat array of RMvertex2D
1500     objects (input).
1501 
1502  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
1503     RM_DONT_COPY_DATA (input).
1504 
1505  void (*appFreeFunc)(void *) - a handle to an application
1506     callback. When "copyEnum" is RM_DONT_COPY_DATA, the application
1507     must provide a callback used to release memory when the
1508     RMprimitive is delete (input).
1509  @aend
1510 
1511  @dstart
1512 
1513  rmPrimitiveSetTexcoord2D is one of a family of routines used to
1514  assign data to RMprimitives. This routine assigns 2D texture
1515  coordinates to an RMprimitive, returning RM_CHILL upon success or
1516  RM_WHACKED upon failure.
1517 
1518  When "copyEnum" is set to RM_COPY_DATA, RM will make a copy of the
1519  raw vertex data provided in "texCoordData." When "copyEnum" is set to
1520  RM_DONT_COPY_DATA, RM will not make a copy of the RMvertex2D data,
1521  but instead will simply copy the handle "texCoordData" into the
1522  RMprimitive, and refer to the caller-supplied memory directly in
1523  later operations.
1524 
1525  When RM_DONT_COPY_DATA is specified, applications must supply a
1526  callback function that will be invoked when the texture coordinate
1527  data in an RMprimitive is deleted. Such deletion occurs when the
1528  RMprimitive itself is deleted, the RMnode containing the RMprimitive
1529  is deleted (if the RMprimitive was assigned to an RMnode with
1530  rmNodeAddChild()), or if new texture coordinate data is assigned.
1531  The application callback takes a single parameter: a handle to the
1532  underlying data array that is managed by the application.
1533 
1534  There is no corresponding "get texture coordinate" routine. Primitive
1535  vertex data should be considered write-only by the application.
1536 
1537  @dend
1538  * ----------------------------------------------------
1539  */
1540 RMenum
rmPrimitiveSetTexcoord2D(RMprimitive * p,int n,RMvertex2D * r,RMenum copy_flag,void (* freefunc)(void *))1541 rmPrimitiveSetTexcoord2D (RMprimitive *p,
1542 			  int n,
1543 			  RMvertex2D *r,
1544 			  RMenum copy_flag,
1545 			  void (*freefunc)(void *))
1546 {
1547     if ((private_rmPrimSetAssert(p, n, (void *)r, copy_flag, freefunc, "rmPrimitiveSetTexcoord2D")) == RM_WHACKED)
1548 	return(RM_WHACKED);
1549 
1550     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_2DTCOORDS, n, sizeof(RMvertex2D), (void *)r, copy_flag, freefunc));
1551 }
1552 
1553 
1554 
1555 /*
1556  * ----------------------------------------------------
1557  * @Name rmPrimitiveSetTexcoord3D
1558  @pstart
1559  RMenum rmPrimitiveSetTexcoord3D (RMprimitive *toModify,
1560 		                  int nTexcoords,
1561 				  RMvertex3D *texCoordData,
1562 				  RMenum copyEnum,
1563 				  void (*appFreeFunc)(void *))
1564  @pend
1565 
1566  @astart
1567  RMprimitive *toModify - a handle to an RMprimitive (modified).
1568 
1569  int nTexcoords - an integer value, specifies the number of texture
1570     coordinates that will be assigned to the RMprimitive (input).
1571 
1572  RMvertex3D *texCoordData - a handle to a flat array of RMvertex3D
1573     objects (input).
1574 
1575  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
1576     RM_DONT_COPY_DATA (input).
1577 
1578  void (*appFreeFunc)(void *) - a handle to an application
1579     callback. When "copyEnum" is RM_DONT_COPY_DATA, the application
1580     must provide a callback used to release memory when the
1581     RMprimitive is delete (input).
1582  @aend
1583 
1584  @dstart
1585 
1586  rmPrimitiveSetTexcoord3D is one of a family of routines used to
1587  assign data to RMprimitives. This routine assigns raw 3D texture
1588  coordinate data to an RMprimitive, returning RM_CHILL upon success or
1589  RM_WHACKED upon failure.
1590 
1591  When "copyEnum" is set to RM_COPY_DATA, RM will make a copy of the
1592  raw texture coordinate data provided in "texCoordData." When
1593  "copyEnum" is set to RM_DONT_COPY_DATA, RM will not make a copy of
1594  the RMvertex3D data, but instead will simply copy the handle
1595  "texCoordData" into the RMprimitive, and refer to the caller-supplied
1596  memory directly in later operations.
1597 
1598  When RM_DONT_COPY_DATA is specified, applications must supply a
1599  callback function that will be invoked when the RMvertex3D data in an
1600  RMprimitive is deleted. Such deletion occurs when the RMprimitive
1601  itself is deleted, the RMnode containing the RMprimitive is deleted
1602  (if the RMprimitive was assigned to an RMnode with rmNodeAddChild()),
1603  or if new RMvertex3D is assigned (more precisely, if new texture
1604  coordinate data is assigned, regardless of whether or not it is 3D or
1605  2D).  The application callback takes a single parameter: a handle to
1606  the underlying data array that is managed by the application.
1607 
1608  There is no corresponding "get texture coordinate" routine. Primitive
1609  vertex data should be considered write-only by the application.
1610 
1611  NOTE: some compilers enforce 8-byte alignment/padding of C
1612  structures.  Since the RMvertex3D object consists of 3 floats, some
1613  compilers will pad memory to produce 8-byte alignment. The underlying
1614  RM data management infrastructure accomodates this added
1615  complexity. However, on such systems, callers that pass in a flat
1616  array of floats cast to RMvertex3D * should be aware that the data is
1617  considered to be a flat array of RMvertex3D objects inside this
1618  routine, not a flat array of floats.
1619 
1620  @dend
1621  * ----------------------------------------------------
1622  */
1623 RMenum
rmPrimitiveSetTexcoord3D(RMprimitive * p,int n,RMvertex3D * r,RMenum copy_flag,void (* freefunc)(void *))1624 rmPrimitiveSetTexcoord3D (RMprimitive *p,
1625 			  int n,
1626 			  RMvertex3D *r,
1627 			  RMenum copy_flag,
1628 			  void (*freefunc)(void *))
1629 {
1630     if ((private_rmPrimSetAssert(p, n, (void *)r, copy_flag, freefunc, "rmPrimitiveSetTexcoord3D")) == RM_WHACKED)
1631         return(RM_WHACKED);
1632 
1633     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_3DTCOORDS, n, sizeof(RMvertex3D), (void *)r, copy_flag, freefunc));
1634 }
1635 
1636 
1637 /*
1638  * ----------------------------------------------------
1639  * @Name rmPrimitiveSetMultiTexcoord1D
1640  @pstart
1641  RMenum rmPrimitiveSetMultiTexcoord1D (RMprimitive *toModify,
1642 		                       int nTexCoords,
1643 				       float *texCoordData,
1644 				       RMenum copyEnum,
1645 				       void (*appFreeFunc)(void *),
1646 				       int textureUnit)
1647  @pend
1648 
1649  @astart
1650  RMprimitive *toModify - a handle to an RMprimitive (modified).
1651 
1652  int nTexCoords - an integer value, specifies the number of 2D texture
1653     coordinates that will be assigned to the RMprimitive (input).
1654 
1655  float *texCoordData - a handle to a flat array of floats (input).
1656 
1657  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
1658     RM_DONT_COPY_DATA (input).
1659 
1660  void (*appFreeFunc)(void *) - a handle to an application
1661     callback. When "copyEnum" is RM_DONT_COPY_DATA, the application
1662     must provide a callback used to release memory when the
1663     RMprimitive is delete (input).
1664 
1665  int textureUnit - an integer value specifying with which multitexturing
1666     unit the texture coordinates will be used. Valid values are in the
1667     range zero through RM_MAX_MULTITEXTURES-1.
1668  @aend
1669 
1670  @dstart
1671 
1672  rmPrimitiveSetMultiTexcoord1D is nearly identical in function and
1673  return values to rmPrimitiveSetTexcoord1D. The difference is the ability
1674  to assign texture coordinates to a specific texturing unit in a
1675  multitexturing environment.
1676 
1677  Note that while valid values for the input textureUnit parameter are
1678  in the range zero through RM_MAX_MULTITEXTURES-1, this routine performs
1679  no error checking to verify that the textureUnit input value is valid
1680  for a particular OpenGL implementation. The constant RM_MAX_MULTITEXTURES
1681  is independent of the actual number of texture units supported by an
1682  OpenGL implementation. When multitexturing is supported (use the routine
1683  rmPipeGetNumMultitextureUnits to check for the availability on a given
1684  OpenGL implementation), the minimum number of texture units to be supported
1685  is two; our Quadro4 cards have four texture units; Mesa provides eight
1686  texture units.
1687 
1688  @dend
1689  * ----------------------------------------------------
1690  */
1691 RMenum
rmPrimitiveSetMultiTexcoord1D(RMprimitive * p,int n,float * r,RMenum copy_flag,void (* freefunc)(void *),int textureUnit)1692 rmPrimitiveSetMultiTexcoord1D (RMprimitive *p,
1693 			       int n,
1694 			       float *r,
1695 			       RMenum copy_flag,
1696 			       void (*freefunc)(void *),
1697 			       int textureUnit)
1698 {
1699     RMenum stat;
1700     if ((private_rmPrimSetAssert(p, n, (void *)r, copy_flag, freefunc, "rmPrimitiveSetMultiTexcoord1D")) == RM_WHACKED)
1701 	return(RM_WHACKED);
1702 
1703 
1704     stat = private_rmPrimitiveSetMultiTexcoordBlob(p, RM_PRIMITIVE_MULTI_1DTCOORDS, n, sizeof(float), (void *)r, copy_flag, freefunc, textureUnit);
1705 
1706     return stat;
1707 
1708     /*    return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_MULTI_2DTCOORDS, n, sizeof(RMvertex2D), (void *)r, copy_flag, freefunc, textureUnit)); */
1709 }
1710 
1711 
1712 /*
1713  * ----------------------------------------------------
1714  * @Name rmPrimitiveSetMultiTexcoord2D
1715  @pstart
1716  RMenum rmPrimitiveSetMultiTexcoord2D (RMprimitive *toModify,
1717 		                       int nTexCoords,
1718 				       RMvertex2D *texCoordData,
1719 				       RMenum copyEnum,
1720 				       void (*appFreeFunc)(void *),
1721 				       int textureUnit)
1722  @pend
1723 
1724  @astart
1725  RMprimitive *toModify - a handle to an RMprimitive (modified).
1726 
1727  int nTexCoords - an integer value, specifies the number of 2D texture
1728     coordinates that will be assigned to the RMprimitive (input).
1729 
1730  RMvertex2D *texCoordData - a handle to a flat array of RMvertex2D
1731     objects (input).
1732 
1733  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
1734     RM_DONT_COPY_DATA (input).
1735 
1736  void (*appFreeFunc)(void *) - a handle to an application
1737     callback. When "copyEnum" is RM_DONT_COPY_DATA, the application
1738     must provide a callback used to release memory when the
1739     RMprimitive is delete (input).
1740 
1741  int textureUnit - an integer value specifying with which multitexturing
1742     unit the texture coordinates will be used. Valid values are in the
1743     range zero through RM_MAX_MULTITEXTURES-1.
1744  @aend
1745 
1746  @dstart
1747 
1748  rmPrimitiveSetMultiTexcoord2D is nearly identical in function and
1749  return values to rmPrimitiveSetTexcoord2D. The difference is the ability
1750  to assign texture coordinates to a specific texturing unit in a
1751  multitexturing environment.
1752 
1753  Note that while valid values for the input textureUnit parameter are
1754  in the range zero through RM_MAX_MULTITEXTURES-1, this routine performs
1755  no error checking to verify that the textureUnit input value is valid
1756  for a particular OpenGL implementation. The constant RM_MAX_MULTITEXTURES
1757  is independent of the actual number of texture units supported by an
1758  OpenGL implementation. When multitexturing is supported (use the routine
1759  rmPipeGetNumMultitextureUnits to check for the availability on a given
1760  OpenGL implementation), the minimum number of texture units to be supported
1761  is two; our Quadro4 cards have four texture units; Mesa provides eight
1762  texture units.
1763 
1764  @dend
1765  * ----------------------------------------------------
1766  */
1767 RMenum
rmPrimitiveSetMultiTexcoord2D(RMprimitive * p,int n,RMvertex2D * r,RMenum copy_flag,void (* freefunc)(void *),int textureUnit)1768 rmPrimitiveSetMultiTexcoord2D (RMprimitive *p,
1769 			       int n,
1770 			       RMvertex2D *r,
1771 			       RMenum copy_flag,
1772 			       void (*freefunc)(void *),
1773 			       int textureUnit)
1774 {
1775     RMenum stat;
1776 
1777     if ((private_rmPrimSetAssert(p, n, (void *)r, copy_flag, freefunc, "rmPrimitiveSetMultiTexcoord2D")) == RM_WHACKED)
1778 	return(RM_WHACKED);
1779 
1780     stat = private_rmPrimitiveSetMultiTexcoordBlob(p, RM_PRIMITIVE_MULTI_2DTCOORDS, n, sizeof(RMvertex2D), (void *)r, copy_flag, freefunc, textureUnit);
1781 
1782     return stat;
1783     /*    return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_MULTI_2DTCOORDS, n, sizeof(RMvertex2D), (void *)r, copy_flag, freefunc, textureUnit)); */
1784 }
1785 
1786 
1787 /*
1788  * ----------------------------------------------------
1789  * @Name rmPrimitiveSetMultiTexcoord3D
1790  @pstart
1791  RMenum rmPrimitiveSetMultiTexcoord3D (RMprimitive *toModify,
1792 		                       int nTexCoords,
1793 				       RMvertex3D *texCoordData,
1794 				       RMenum copyEnum,
1795 				       void (*appFreeFunc)(void *),
1796 				       int textureUnit)
1797  @pend
1798 
1799  @astart
1800  RMprimitive *toModify - a handle to an RMprimitive (modified).
1801 
1802  int nTexCoords - an integer value, specifies the number of 2D texture
1803     coordinates that will be assigned to the RMprimitive (input).
1804 
1805  RMvertex3D *texCoordData - a handle to a flat array of RMvertex3D's. (input)
1806 
1807  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
1808     RM_DONT_COPY_DATA (input).
1809 
1810  void (*appFreeFunc)(void *) - a handle to an application
1811     callback. When "copyEnum" is RM_DONT_COPY_DATA, the application
1812     must provide a callback used to release memory when the
1813     RMprimitive is delete (input).
1814 
1815  int textureUnit - an integer value specifying with which multitexturing
1816     unit the texture coordinates will be used. Valid values are in the
1817     range zero through RM_MAX_MULTITEXTURES-1.
1818  @aend
1819 
1820  @dstart
1821 
1822  rmPrimitiveSetMultiTexcoord3D is nearly identical in function and
1823  return values to rmPrimitiveSetTexcoord3D. The difference is the ability
1824  to assign texture coordinates to a specific texturing unit in a
1825  multitexturing environment.
1826 
1827  Note that while valid values for the input textureUnit parameter are
1828  in the range zero through RM_MAX_MULTITEXTURES-1, this routine performs
1829  no error checking to verify that the textureUnit input value is valid
1830  for a particular OpenGL implementation. The constant RM_MAX_MULTITEXTURES
1831  is independent of the actual number of texture units supported by an
1832  OpenGL implementation. When multitexturing is supported (use the routine
1833  rmPipeGetNumMultitextureUnits to check for the availability on a given
1834  OpenGL implementation), the minimum number of texture units to be supported
1835  is two; our Quadro4 cards have four texture units; Mesa provides eight
1836  texture units.
1837 
1838  @dend
1839  * ----------------------------------------------------
1840  */
1841 RMenum
rmPrimitiveSetMultiTexcoord3D(RMprimitive * p,int n,RMvertex3D * r,RMenum copy_flag,void (* freefunc)(void *),int textureUnit)1842 rmPrimitiveSetMultiTexcoord3D (RMprimitive *p,
1843 			       int n,
1844 			       RMvertex3D *r,
1845 			       RMenum copy_flag,
1846 			       void (*freefunc)(void *),
1847 			       int textureUnit)
1848 {
1849     RMenum stat;
1850     if ((private_rmPrimSetAssert(p, n, (void *)r, copy_flag, freefunc, "rmPrimitiveSetMultiTexcoord3D")) == RM_WHACKED)
1851 	return(RM_WHACKED);
1852 
1853     stat = private_rmPrimitiveSetMultiTexcoordBlob(p, RM_PRIMITIVE_MULTI_3DTCOORDS, n, sizeof(RMvertex2D), (void *)r, copy_flag, freefunc, textureUnit);
1854 
1855     return stat;
1856     /*    return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_MULTI_2DTCOORDS, n, sizeof(RMvertex2D), (void *)r, copy_flag, freefunc, textureUnit)); */
1857 }
1858 
1859 
1860 /*
1861  * ----------------------------------------------------
1862  * @Name rmPrimitiveSetIndices
1863  @pstart
1864  RMenum rmPrimitiveSetIndices (RMprimitive *toModify,
1865 		               int numIndices,
1866 			       int *indicesArray,
1867 			       RMenum copyEnum,
1868 			       void (*appFreeFunc)(void *))
1869  @pend
1870 
1871  @astart
1872  RMprimitive *toModify - a handle to an RMprimitive (modified).
1873 
1874  int numIndices - an integer value specifying the length of the
1875     indicesArray[] array (input).
1876 
1877  int *indicesArray - a flat array of integer indices (input).
1878 
1879  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
1880     RM_DONT_COPY_DATA (input).
1881 
1882  void (*appFreeFunc)(void *) - a handle to an application callback,
1883     required when copyEnum is RM_DONT_COPY_DATA (input).
1884  @aend
1885 
1886  @dstart
1887 
1888  Use this routine to set "index values" in an RMprimitive. Returns
1889  RM_CHILL upon success, or RM_WHACKED upon failure.
1890 
1891  Some RMprimitive objects allow the use of "indexed" vertices. At this
1892  time (Feb 2004), these include RM_INDEXED_TFAN, RM_INDEXED_TEXT, and
1893  RM_INDEXED_BITMAP, RM_INDEXED_QUADS, RM_INDEXED_TRIANGLES,
1894  and RM_INDEXED_TRIANGLE_STRIP. (Plans
1895  are underway to grow the number of indexed primitives).
1896 
1897  In non-indexed primitives, the number of objects drawn on screen is a
1898  function of the number of vertices in the RMprimitive and the
1899  primitive type itself. For example, in RM_TRIANGLES primitives
1900  (disjoint triangles), the number of triangles that are drawn is the
1901  number of vertices divided by 3. For RM_INDEXED_TRIANGLES, the number
1902  of triangles that will be drawn is instead the number of indices
1903  divided by 3. For RM_INDEXED_QUADS, the number of quads drawn is the
1904  number of indices divided by 4. For RM_INDEXED_TRIANGLE_STRIP, the
1905  number of triangles draw is the number of indices-2 (e.g, four
1906  indices produces 2 triangles).
1907 
1908  Each entry in the index array is an index into another array.
1909 
1910  Index values in the RM_INDEXED_TEXT are offsets into an array of text
1911  strings. Index values in RM_INDEXED_BITMAP primitives are offsets
1912  into an array of RMbitmap objects. Index values in RM_INDEXED_TFAN
1913  are offsets into a vertex array.
1914 
1915  When "copyEnum" is set to RM_COPY_DATA, RM will make a copy of the
1916  raw index data provided in "indexArray." When "copyEnum" is set to
1917  RM_DONT_COPY_DATA, RM will not make a copy of the index data, but
1918  instead will simply copy the handle "indexArray" into the
1919  RMprimitive, and refer to the caller-supplied memory directly in
1920  later operations.
1921 
1922  When RM_DONT_COPY_DATA is specified, applications must supply a
1923  callback function that will be invoked when the index data in an
1924  RMprimitive is deleted. Such deletion occurs when the RMprimitive
1925  itself is deleted, the RMnode containing the RMprimitive is deleted
1926  (if the RMprimitive was assigned to an RMnode with rmNodeAddChild()),
1927  or if new index is assigned. The application callback takes a single
1928  parameter: a handle to the underlying data array that is managed by
1929  the application.
1930 
1931  @dend
1932  * ----------------------------------------------------
1933  */
1934 RMenum
rmPrimitiveSetIndices(RMprimitive * t,int npts,int * indices,RMenum copy_enum,void (* freefunc)(void *))1935 rmPrimitiveSetIndices (RMprimitive *t,
1936 		       int npts,
1937 		       int *indices,
1938 		       RMenum copy_enum,
1939 		       void (*freefunc)(void *))
1940 {
1941     if (private_rmPrimSetAssert(t, npts, (void *)indices, copy_enum, freefunc, "rmPrimitiveSetIndices") == RM_WHACKED)
1942 	return(RM_WHACKED);
1943 
1944     return(private_rmPrimitiveSetItem((RMprimitive *)t, RM_PRIMITIVE_INDICES, npts, sizeof(int), (void *)indices, copy_enum, freefunc));
1945 }
1946 
1947 
1948 /*
1949  * ----------------------------------------------------
1950  * @Name rmPrimitiveSetSprites
1951  @pstart
1952  RMenum rmPrimitiveSetSprites (RMprimitive *toModify,
1953 		               int nSprites,
1954 			       RMimage **spriteArray)
1955  @pend
1956 
1957  @astart
1958  RMprimitive *toModify - a handle to an RMprimitive (modified).
1959 
1960  int nSprites - an integer value specifying the number of sprites that
1961     will be assigned to an RM_SPRITE primitive (input).
1962 
1963  RMimage **spriteArray - an array of RMimage handles (input).
1964  @aend
1965 
1966  @dstart
1967 
1968  RM_SPRITE primitives are image-based primitives consisting of vertex
1969  and image data. rmPrimitiveSetSprites is used to assign the image
1970  data to the RM_SPRITE primitive.
1971 
1972  Shared data management of the raw pixel data is specified as an
1973  interface to the RMimage object, hence specification of
1974  RM_COPY_DATA/RM_DONT_COPY_DATA is not necessary at the RMprimitive
1975  level for RM_SPRITES. Inside this routine, all the images in the
1976  spriteArray are duplicated with rmImageDup(). Please refer to
1977  rmImageDup() for more details about shared data management of pixel
1978  data in RMimage objects.
1979 
1980  @dend
1981  * ----------------------------------------------------
1982  */
1983 RMenum
rmPrimitiveSetSprites(RMprimitive * p,int nsprites,RMimage ** sprite_array)1984 rmPrimitiveSetSprites (RMprimitive *p,
1985 		       int nsprites,
1986 		       RMimage **sprite_array)
1987 {
1988     if ((private_rmPrimSetAssert(p, nsprites, (void *)sprite_array, RM_COPY_DATA,NULL, "rmPrimitiveSetSprites")) == RM_WHACKED)
1989         return(RM_WHACKED);
1990 
1991     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_SPRITES, nsprites, sizeof(RMimage *), sprite_array, RM_COPY_DATA, NULL));
1992 }
1993 
1994 
1995 /*
1996  * ----------------------------------------------------
1997  * @Name rmPrimitiveSetBitmaps
1998  @pstart
1999  RMenum rmPrimitiveSetBitmaps (RMprimitive *toModify,
2000 		               int nBitmaps,
2001 			       RMbitmap **bmapArray)
2002  @pend
2003 
2004  @astart
2005  RMprimitive *toModify - a handle to an RMprimitive (modified).
2006 
2007  int nBitmaps - an integer value specifying the number of RMbitmap
2008     objects to assign to an RMprimitive (input).
2009 
2010  RMbitmap **bmapArray - an array of RMbitmap handles (input).
2011  @aend
2012 
2013  @dstart
2014 
2015  Primitives of the type RM_BITMAP or RM_INDEXED_BITMAP consist of
2016  vertex data and RMbitmap objects (the indexed form also takes
2017  indices). Use this routine to assign RMbitmap data to the
2018  RMprimitive. It returns RM_CHILL upon success, or RM_WHACKED upon
2019  failure.
2020 
2021  There is no shared data management of RMbitmap data since these
2022  objects are small.
2023 
2024  @dend
2025  * ----------------------------------------------------
2026  */
2027 RMenum
rmPrimitiveSetBitmaps(RMprimitive * p,int nbitmaps,RMbitmap ** bmaplist)2028 rmPrimitiveSetBitmaps (RMprimitive *p,
2029 		       int nbitmaps,
2030 		       RMbitmap **bmaplist)
2031 {
2032     if ((private_rmPrimSetAssert(p, nbitmaps, (void *)bmaplist, RM_COPY_DATA, NULL, "rmPrimitiveSetBitmaps")) == RM_WHACKED)
2033         return(RM_WHACKED);
2034 
2035     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_BITMAPS, nbitmaps, sizeof(RMbitmap), (void *)bmaplist, RM_COPY_DATA, NULL));
2036 }
2037 
2038 
2039 /*
2040  * ----------------------------------------------------
2041  * @Name rmPrimitiveSetQmeshDims
2042  @pstart
2043  RMenum rmPrimitiveSetQmeshDims (RMprimitive *toModify,
2044 			         int uSize,
2045 				 int vSize)
2046  @pend
2047 
2048  @astart
2049  RMprimitive *toModify - a handle to an RMprimitive (modified).
2050 
2051  int uSize, vSize - integer values specifying the dimensions of a
2052     lattice defining a quadmesh (input).
2053  @aend
2054 
2055  @dstart
2056 
2057  A quadmesh primitive may be considered as a two-dimensional lattice
2058  of points. The points themselves may be specified with two or three
2059  dimensional coordinate values. This routine is used to specify the
2060  number of points in each of the two dimensions of the lattice, and
2061  returns RM_CHILL upon success or RM_WHACKED upon failure.
2062 
2063  Quadmesh primitives require, in addition to a grid size set with
2064  rmPrimitiveSetQmeshDims, vertex data set with rmPrimitiveSetVertex3D
2065  or rmPrimitiveSetVertex2D. Colors, normals and texture coordinates
2066  are all optional.
2067 
2068  The routines rmPrimitiveSetQmeshDims and rmPrimitiveSetVertex3D/2D
2069  may be called in any order, but both must be called before a quadmesh
2070  primitive is rendered.
2071 
2072  @dend
2073  * ----------------------------------------------------
2074  */
2075 RMenum
rmPrimitiveSetQmeshDims(RMprimitive * p,int usize,int vsize)2076 rmPrimitiveSetQmeshDims (RMprimitive *p,
2077 			 int usize,
2078 			 int vsize)
2079 {
2080     int dims[2];
2081 
2082     if (RM_ASSERT(p, "rmPrimitiveSetQmeshDims() error: the input RMprimitive is NULL. ") == RM_WHACKED)
2083 	return(RM_WHACKED);
2084 
2085     dims[0] = usize;
2086     dims[1] = vsize;
2087 
2088     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_QMESHDIMS, 2, sizeof(int), (void *)dims, RM_COPY_DATA, NULL));
2089 }
2090 
2091 
2092 /*
2093  * ----------------------------------------------------
2094  * @Name rmPrimitiveSetOmeshDims
2095  @pstart
2096  RMenum rmPrimitiveSetOmeshDims (RMprimitive *toModify,
2097 			         int isize,
2098 				 int jsize,
2099 				 int ksize)
2100  @pend
2101 
2102  @astart
2103  RMprimitive *toModify - a handle to an RMprimitive (modified).
2104 
2105  int isize, jsize, ksize - integer values specifying the number of
2106     points in a three dimensional hexahedral lattice (input).
2107  @aend
2108 
2109  @dstart
2110 
2111  The OpenRM Octmesh primitive is logically a three-dimensional,
2112  hexahedral lattice. Use this routine to set the dimensions of the
2113  lattice. In most cases, "isize" will correspond to the x-axis,
2114  "jsize" to the y-axis and "ksize" to the z-axis.
2115 
2116  In OpenRM, direct volume rendering is achieved with a combination of
2117  an octmesh primitive and a 3D texture. The 3D texture provides color
2118  and opacity information, while the octmesh primitive specifies the
2119  geometric placement and resolution of the underlying 3D lattice.
2120 
2121  The octmesh primitive is procedural in that texture coordinates are
2122  automatically generated at render time. Use rmPrimitiveSetModelFlag
2123  to coarsen or refine render-time sampling of the underlying Octmesh
2124  grid.
2125 
2126  (Jan 2000) - use rmPrimitiveSetOmeshMinMaxGrid() to specify the
2127  corners of the 3D lattice. Use of rmPrimitiveSetVertex3D on octmesh
2128  primitives is not yet implemented.
2129 
2130  Note: the dimensions of the Octmesh lattice must be specified prior
2131  (using this routine, rmPrimitiveSetOmeshDims) prior to the
2132  specification of the corners of the lattice (using
2133  rmPrimitiveSetOmeshMinMaxGrid).
2134 
2135  @dend
2136  * ----------------------------------------------------
2137  */
2138 RMenum
rmPrimitiveSetOmeshDims(RMprimitive * p,int isize,int jsize,int ksize)2139 rmPrimitiveSetOmeshDims (RMprimitive *p,
2140 			 int isize,
2141 			 int jsize,
2142 			 int ksize)
2143 {
2144     int dims[3];
2145 
2146     if (RM_ASSERT(p, "rmPrimitiveSetOmeshDims() error: the input RMprimitive is NULL. ") == RM_WHACKED)
2147 	return(RM_WHACKED);
2148 
2149     dims[0] = isize;
2150     dims[1] = jsize;
2151     dims[2] = ksize;
2152 
2153     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_OMESHDIMS, 3, sizeof(int), (void *)dims, RM_COPY_DATA, NULL));
2154 }
2155 
2156 
2157 /*
2158  * ----------------------------------------------------
2159  * @Name rmPrimitiveSetOmeshMinMaxGrid
2160  @pstart
2161  RMenum rmPrimitiveSetOmeshMinMaxGrid (RMprimitive *toModify,
2162 			               const RMvertex3D *gridMin,
2163 				       const RMvertex3D *gridMax)
2164  @pend
2165 
2166  @astart
2167  RMprimitive *p - a handle to an RMprimitive (modified).
2168 
2169  const RMvertex3D *gridMin, *gridMax - handles to RMvertex3D objects
2170     (input).
2171  @aend
2172 
2173  @dstart
2174 
2175  Use this routine to set the minimum and maximum coordinates for the
2176  3D lattice that defines an octmesh primitive. The spatial extents of
2177  the lattice are specified with this routine, whereas the resolution
2178  of the lattice is specified with rmPrimitiveSetOmeshDims().
2179 
2180  Returns RM_CHILL upon success, or RM_WHACKED upon failure.
2181 
2182  Note: the dimensions of the Octmesh lattice must be specified prior
2183  (using rmPrimitiveSetOmeshDims) prior to the specification of the
2184  corners of the lattice (using rmPrimitiveSetOmeshMinMaxGrid).
2185 
2186  @dend
2187  * ----------------------------------------------------
2188  */
2189 RMenum
rmPrimitiveSetOmeshMinMaxGrid(RMprimitive * p,const RMvertex3D * gridMin,const RMvertex3D * gridMax)2190 rmPrimitiveSetOmeshMinMaxGrid (RMprimitive *p,
2191 			       const RMvertex3D *gridMin,
2192 			       const RMvertex3D *gridMax)
2193 {
2194     RMvertex3D v[2];
2195 
2196     if ((RM_ASSERT(p, "rmPrimitiveSetOmeshMinMaxGrid() error: the input RMprimitive is NULL") == RM_WHACKED ) ||
2197 	(RM_ASSERT(gridMin, "rmPrimitiveSetOmeshMinMaxGrid() error: the input gridMin pointer is NULL") == RM_WHACKED) ||
2198 	(RM_ASSERT(gridMax, "rmPrimitiveSetOmeshMinMaxGrid() error: the input gridMax pointer is NULL") == RM_WHACKED))
2199 	return(RM_WHACKED);
2200 
2201     v[0] = *gridMin;
2202     v[1] = *gridMax;
2203 
2204     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_OMESH_MINMAX_GRID, 2, sizeof(RMvertex3D), (void *)v, RM_COPY_DATA, NULL));
2205 }
2206 
2207 
2208 /*
2209  * ----------------------------------------------------
2210  * @Name rmPrimitiveSetMarkerScale
2211  @pstart
2212  RMenum rmPrimitiveSetMarkerScale (RMprimitive *toModify,
2213 			           int npts,
2214 				   float *scales,
2215 				   RMenum copyEnum,
2216 				   void (*appFreeFunc)(void *))
2217  @pend
2218 
2219  @astart
2220  RMprimitive *toModify - a handle to an RMprimitive (modified).
2221 
2222  int npts - an integer value specifying the length of the "scales"
2223     array (input).
2224 
2225  float *scales - a flat array of floats, expected to be "npts" in
2226     length (input).
2227 
2228  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
2229     RM_DONT_COPY_DATA (input).
2230 
2231  void (*appFreeFunc)(void *) - a handle to an application callback,
2232     required when copyEnum is RM_DONT_COPY_DATA (input).
2233  @aend
2234 
2235  @dstart
2236 
2237  Use this routine to set the scale values applied to RM "marker
2238  primitives."  Returns RM_CHILL upon success, or RM_WHACKED upon
2239  failure.
2240 
2241  The "marker primitive" in RM is a procedural primitive built from a
2242  number of predefined shapes, such as a triangles, squares, and so
2243  forth (see rmv.h). A fully populated marker primitive will consist of
2244  some number of vertices (each vertex defines the center point for the
2245  procedural marker), optional scale values used to isometrically
2246  shrink or expand the underlying marker geometric model, and optional
2247  color values. The number of vertices defined by
2248  rmPrimitiveSetVertex2D/3D defines the number of marker primitives
2249  that will be drawn.
2250 
2251  The number of marker shapes that are drawn by a given RMprimitive
2252  object is either 1 (drawn at many places in the scene, defined by
2253  rmPrimitiveSetVertex2D/3D), or the same as the number of vertices
2254  defined by rmPrimitiveSetVertex2D/3D. The marker primitives
2255  themselves are created by rmInternalMarker2DNew() and assigned to the
2256  RMprimitive with rmPrimitiveSetMarkerPrims().
2257 
2258  The number of scale values may be either 1, or the same as the number
2259  of vertices specified with rmPrimitiveSetVertex2D/3D.
2260 
2261  @dend
2262  * ----------------------------------------------------
2263  */
2264 RMenum
rmPrimitiveSetMarkerScale(RMprimitive * p,int npts,float * s,RMenum copy_enum,void (* appfreefunc)(void *))2265 rmPrimitiveSetMarkerScale (RMprimitive *p,
2266 			   int npts,
2267 			   float *s,
2268 			   RMenum copy_enum,
2269 			   void (*appfreefunc)(void *))
2270 {
2271     if ((private_rmPrimSetAssert(p, npts, (void *)s, copy_enum, appfreefunc, "rmPrimitiveSetMarkerScale")) == RM_WHACKED)
2272         return(RM_WHACKED);
2273 
2274     return(private_rmPrimitiveSetItem((RMprimitive *)p, RM_PRIMITIVE_MARKERS2D_SCALE, npts, sizeof(float), (void *)s, copy_enum, appfreefunc));
2275 }
2276 
2277 
2278 /*
2279  * ----------------------------------------------------
2280  * @Name rmPrimitiveSetMarkerPrims
2281  @pstart
2282  RMenum rmPrimitiveSetMarkerPrims (RMprimitive *toModify,
2283 			           int nMarkerPrims,
2284 				   RMinternalMarker2D **mArray)
2285  @pend
2286 
2287  @astart
2288  RMprimitive *toModify - a handle to an RMprimitive (modified).
2289 
2290  int nMarkerPrims - an integer value specifying the number of input
2291     "marker primitives" in the mArray parameter (input).
2292 
2293  RMinternalMarker2D **mArray - a handle to a flat array of
2294     RMinternalMarker2D handles (input).
2295  @aend
2296 
2297  @dstart
2298 
2299  Use this routine to assign some number of procedural marker
2300  primitives (RMinternalMarker2D) to an RMprimitive. Returns RM_CHILL
2301  upon success, or RM_WHACKED upon failure.  Use
2302  rmInternalMarker2DNew() to create the marker primitives.
2303 
2304  The "marker primitive" in RM is a procedural primitive built from a
2305  number of predefined shapes, such as a triangles, squares, and so
2306  forth (see rmv.h). A fully populated marker primitive will consist of
2307  some number of vertices (each vertex defines the center point for the
2308  procedural marker), optional scale values used to isometrically
2309  shrink or expand the underlying marker geometric model, and optional
2310  color values. The number of vertices defined by
2311  rmPrimitiveSetVertex2D/3D defines the number of marker primitives
2312  that will be drawn.
2313 
2314  The number of marker shapes that are drawn by a given RMprimitive
2315  object is either 1 (drawn at many places in the scene, defined by
2316  rmPrimitiveSetVertex2D/3D), or the same as the number of vertices
2317  defined by rmPrimitiveSetVertex2D/3D. The marker primitives
2318  themselves are created by rmInternalMarker2DNew() and assigned to the
2319  RMprimitive with rmPrimitiveSetMarkerPrims().
2320 
2321  The number of scale values may be either 1, or the same as the number
2322  of vertices specified with rmPrimitiveSetVertex2D/3D.
2323 
2324  @dend
2325  * ----------------------------------------------------
2326  */
2327 RMenum
rmPrimitiveSetMarkerPrims(RMprimitive * p,int nmarkerprims,RMinternalMarker2D ** marray)2328 rmPrimitiveSetMarkerPrims (RMprimitive *p,
2329 			   int nmarkerprims,
2330 			   RMinternalMarker2D **marray)
2331 {
2332     if (RM_ASSERT(p, "rmPrimitiveSetMarkerPrims() error: primitive is NULL") == RM_WHACKED)
2333 	return(RM_WHACKED);
2334 
2335     if (!((nmarkerprims != 0) && (marray != NULL)))
2336     {
2337 	rmError("rmPrimitiveSetMarkerPrims() error: null markerprims array pointer and non-zero count");
2338 	return(RM_WHACKED);
2339     }
2340 
2341     return(private_rmPrimitiveSetItem((RMprimitive *)p, RM_PRIMITIVE_MARKERS2D_PRIM, nmarkerprims, sizeof(RMinternalMarker2D), (void *)marray, RM_COPY_DATA, NULL));
2342 }
2343 
2344 
2345 /*
2346  * ----------------------------------------------------
2347  * @Name  rmPrimitiveSetEllipse2DRotate
2348  @pstart
2349  RMenum rmPrimitiveSetEllipse2DRotate (RMprimitive *toModify,
2350 			               int nVals,
2351 				       float *rotationValues,
2352 				       RMenum copyEnum,
2353 				       void (*appFreeFunc)(void *))
2354  @pend
2355 
2356  @astart
2357  RMprimitive *toModify - a handle to an RMprimitive (modified).
2358 
2359  int nVals - an integer value specifying the length of the
2360     rotationValues[] array (input).
2361 
2362  float *rotationValues - an array of floats, must be nVals in length
2363     (input).
2364 
2365  RMenum copyEnum - an RMenum value, may be either RM_COPY_DATA or
2366     RM_DONT_COPY_DATA (input).
2367 
2368  void (*appFreeFunc)(void *) - a handle to an application callback,
2369     required when copyEnum is RM_DONT_COPY_DATA (input).
2370  @aend
2371 
2372  @dstart
2373 
2374  Use this routine to set the rotation angles for some number of
2375  ellipses in an RM_ELLIPSE2D primitive. Returns RM_CHILL upon success,
2376  or RM_WHACKED upon failure.
2377 
2378  RM ellipse primitives consist of vertices that define the center of
2379  each ellipse (rmPrimitiveSetVertex2D), optional per-ellipse color
2380  data, optional per-ellipse scale values (2 radius values per ellipse)
2381  and an optional per-ellipse rotation value.
2382 
2383  At render time, for each input vertex, or ellipse center, an
2384  idealized ellipse is first scaled, rotated, then translated to the
2385  desired location.
2386 
2387  The per-ellipse rotation value defines a counterclockwise rotation
2388  about the Z-axis, where it is assumed that the ellipse is defined in
2389  the x/y plane. The rotation values are specified in degrees (not
2390  radians).  A input rotation value of 90 will cause the ellipse to be
2391  rotated 90 degrees counterclockwise.
2392 
2393  When copyEnum is set to RM_COPY_DATA, the rotation values provided by
2394  the caller will be copied. When copyEnum is set to RM_DONT_COPY_DATA,
2395  the handle "rotationValues" will be used directly by the RMprimitive.
2396  The caller must provide a callback in conjunction with
2397  RM_DONT_COPY_DATA that will be invoked when the RMprimitive is
2398  deleted.
2399 
2400  @dend
2401  * ----------------------------------------------------
2402  */
2403 RMenum
rmPrimitiveSetEllipse2DRotate(RMprimitive * p,int nvals,float * rots,RMenum copy_enum,void (* appfreefunc)(void *))2404 rmPrimitiveSetEllipse2DRotate (RMprimitive *p,
2405 			       int nvals,
2406 			       float *rots,
2407 			       RMenum copy_enum,
2408 			       void (*appfreefunc)(void *))
2409 {
2410     if ((private_rmPrimSetAssert(p, nvals, (void *)rots, copy_enum, appfreefunc, "rmPrimitiveSetEllipse2DRotate")) == RM_WHACKED)
2411 	return(RM_WHACKED);
2412 
2413     return(private_rmPrimitiveSetItem(p, RM_PRIMITIVE_INDICES, nvals, sizeof(float), (void *)rots, copy_enum, appfreefunc));
2414 }
2415 
2416 
2417 /*
2418  * ----------------------------------------------------
2419  * @Name rmPrimitiveSetText
2420  @pstart
2421  RMenum rmPrimitiveSetText (RMprimitive *toModify,
2422 		            int nStrings,
2423 			    char *strings[])
2424  @pend
2425 
2426  @astart
2427  RMprimitive *toModify - a handle to an RMprimitive (modified).
2428 
2429  int nStrings - an integer value specifying the number of text strings
2430     in the strings[] array (input).
2431 
2432  char *strings[] - an array of character strings (input).
2433  @aend
2434 
2435  @dstart
2436 
2437  Use this routine to assign some number of text strings to an
2438  RMprimitive of type RM_TEXT or RM_INDEXED_TEXT. The input text
2439  strings are duplicated in the RMprimitive; there is no shared data
2440  management. Returns RM_CHILL upon success, or RM_WHACKED upon
2441  failure.
2442 
2443  Text rendering in RM is achieved by creating an RMprimitive of type
2444  RM_TEXT or RM_INDEXED_TEXT, supplying text strings and vertex
2445  locations to the RMprimitive (colors are optional, but indices are
2446  required for the RM_INDEXED_TEXT primitive). This RMprimitive data
2447  specifies the location of the text string, along with the text to be
2448  rendered.
2449 
2450  The appearance of the text string, such as typeface, size,
2451  italicization and so forth are manipulated through the RMnode scene
2452  parameter RMtextProps (see rmTextPropsSetAttribs).
2453 
2454  @dend
2455  * ----------------------------------------------------
2456  */
2457 RMenum
rmPrimitiveSetText(RMprimitive * t,int nstrings,char * strings[])2458 rmPrimitiveSetText (RMprimitive *t,
2459 		    int nstrings,
2460 		    char *strings[])
2461 {
2462     int          i;
2463     RMtextPrim *p;
2464 
2465     if ((private_rmPrimSetAssert(t, nstrings, (void *)strings, RM_COPY_DATA, NULL, "rmPrimitiveSetText")) == RM_WHACKED)
2466         return(RM_WHACKED);
2467 
2468     /* first, remove any stuff */
2469     if (t->p1)
2470     {
2471 	int i;
2472 	p = t->p1;
2473 	/* free each old string */
2474 	for (i=0; i<(int)(t->flags1); i++)
2475 	    free((void *)p[i].string);
2476 
2477 	free((void *)t->p1);
2478     }
2479 
2480     p = (RMtextPrim *)malloc(sizeof(RMtextPrim)*nstrings);
2481 
2482     for (i = 0; i < nstrings; i++)
2483     {
2484 	p[i].string = strdup(strings[i]);
2485 	p[i].bh = p[i].bw = -1; /* need to have these set */
2486 	p[i].ptag = -1;		/* mark as uninitialized */
2487     }
2488 
2489     t->p1 = (void *)p;
2490     t->flags1 = nstrings;
2491 
2492     return(RM_CHILL);
2493 }
2494 
2495 
2496 /*
2497  * ----------------------------------------------------
2498  * @Name rmPrimitiveSetDisplayListEnable
2499  @pstart
2500  RMenum rmPrimitiveSetDisplayListEnable (RMprimitive *toModify,
2501 				         RMenum newMode)
2502  @pend
2503 
2504  @astart
2505  RMprimitive *toModify - a handle to an RMprimitive (modified).
2506 
2507  RMenum newMode - an RMenum value, may be either RM_TRUE or RM_FALSE
2508     (input).
2509  @aend
2510 
2511  @dstart
2512 
2513  In RM, OpenGL display lists are automatically built and cached on a
2514  per-primitive basis. In some cases, the application may wish to
2515  override this behavior, and inhibit the automatic construction of
2516  display lists. Primitive which are dynamic, such as those that have
2517  geometry, colors, etc. that change often (like every frame) should
2518  not be display-listed. The cost of building and storing the display
2519  list will not be recouped by the shortened rendering time unless the
2520  display list is used in many frames.
2521 
2522  Specify RM_TRUE for newMode to enable display lists for the
2523  RMprimitive toModify, otherwise, specify RM_FALSE to disable display
2524  list building for the RMprimitive.
2525 
2526  Applications can control use of display lists in two ways: at the RMpipe
2527  level, and at the RMprimitive level. At the RMpipe level, you can
2528  enable or disable use of display lists for all RMprimitives drawn on RMpipe
2529  using the routine rmPipeSetDisplayListEnable. At the RMprimitive level,
2530  you can enable or disable the use of display lists for a single primitive
2531  using rmPrimitiveSetDisplayListEnable().
2532 
2533  The RMprimitive display list  policy does not override the display list
2534  policy set at the RMpipe level. In other words, if the policy at the RMpipe
2535  level is set to RM_FALSE, then no display lists will be used, even if the
2536  policy at the RMprimitive level is set to RM_TRUE. On the other hand, if
2537  the policy at the RMpipe level is set to RM_TRUE, a policy at the RMprimitive
2538  level of RM_FALSE will result on no display lists being used for the
2539  one RMprimitive. In order for display lists to be used at any given
2540  RMprimitive, the logical AND of RMpipe and RMprimitive display list
2541  policies must be RM_TRUE.
2542 
2543  Returns RM_CHILL upon success, or RM_WHACKED upon failure.
2544 
2545  (Jan 2000) At this time, there is no corresponding "get display list
2546  enable" routine.
2547 
2548  See also rmPipeSetDisplayListEnable().
2549 
2550  @dend
2551  * ----------------------------------------------------
2552  */
2553 RMenum
rmPrimitiveSetDisplayListEnable(RMprimitive * p,RMenum newMode)2554 rmPrimitiveSetDisplayListEnable (RMprimitive *p,
2555 				 RMenum newMode)
2556 {
2557     if (RM_ASSERT(p, "rmPrimitiveSetDisplayListEnable() error: the input RMprimitive pointer is NULL. ") == RM_WHACKED)
2558 	return(RM_WHACKED);
2559 
2560     if ((newMode != RM_TRUE) && (newMode != RM_FALSE))
2561     {
2562 	rmError("rmPrimitiveDisplayListEnable() error: the input newMode enumerator is neither RM_TRUE nor RM_FALSE.");
2563 	return(RM_WHACKED);
2564     }
2565 
2566     /*
2567      * bookkeeping chores:
2568      * if the new mode is RM_FALSE, delete any existing display list,
2569      * and set the "compiled render function" pointer to NULL.
2570      */
2571     private_rmPrimitiveSetDisplayListEnable(p, newMode);
2572 
2573     return(RM_CHILL);
2574 }
2575 
2576 
2577 /*
2578  * ----------------------------------------------------
2579  * @Name rmNodeAddPrimitive
2580  @pstart
2581  RMenum rmNodeAddPrimitive (RMnode *addTo,
2582 		            RMprimitive *src)
2583  @pend
2584 
2585  @astart
2586  RMnode *addTo - a handle to an RMnode (modified).
2587 
2588  RMprimitive *src - a handle to an RMprimitive (input).
2589  @aend
2590 
2591  @dstart
2592 
2593  This routine adds an RMprimitive to an RMnode. Returns RM_CHILL upon
2594  success, or RM_WHACKED upon failure.
2595 
2596  Each RMnode may contain an arbitrary number of RMprimitive objects.
2597  Each of the RMprimitive objects is added to the RMnode using
2598  rmNodeAddPrimitive. The list of RMprimitives in an RMnode is a flat
2599  array, and this array grows to accomodate new RMprimitives as they
2600  are added.
2601 
2602  January 2000 - at this time, there is no corresponding "delete
2603  primitive from an RMnode" operation. The closest equivalent is
2604  rmNodeDelete().  Applications that anticipate the need to delete
2605  RMprimitives should carefully consider the subject of scene graph
2606  design, and use RMnodes that contain just a single primitive; the
2607  delete operations should be performed at the RMnode level, not the
2608  RMprimitive level.
2609 
2610  February 2001 - this routine is thread safe: multiple application threads
2611  may simultaneously call this routine to add primitives to the same node.
2612  Thread safety is provided by mutex locks in the component manager.
2613 
2614  NOTE: Applications SHOULD NOT use an RMprimitive in multiple RMnodes
2615  in order to accomplish instancing. Instancing is properly achieved in
2616  RM by instancing at the RMnode level, not the RMprimitive level.
2617 
2618 
2619  @dend
2620  * ----------------------------------------------------
2621  */
2622 RMenum
rmNodeAddPrimitive(RMnode * n,RMprimitive * prim)2623 rmNodeAddPrimitive (RMnode *n,
2624 		    RMprimitive *prim)
2625 {
2626     extern RMcompMgrHdr *global_RMnodePool;
2627 
2628     if (RM_ASSERT(n, "rmNodeAddPrimitive() error: input node is NULL\n") == RM_WHACKED)
2629 	return(RM_WHACKED);
2630 
2631     if (rmMutexLock(global_RMnodePool->guard) == RM_WHACKED)
2632     {
2633 	rmError("rmNodeAddPrimitive() error: problem locking guard mutex in component manager. ");
2634 	return(RM_WHACKED);
2635     }
2636 
2637     if ((n->prims = (void **)realloc(n->prims, sizeof(void *) * (n->nprims + 1))) == NULL)
2638     {
2639 	rmError("rmNodeAddPrimitive() error: realloc failure. the primitive list at this node is now in an undetermined state, and may contain garbage. ");
2640 
2641 	if (rmMutexUnlock(global_RMnodePool->guard) == RM_WHACKED)
2642 	{
2643 	    rmError("rmNodeAddPrimitive() error: problem unlocking guard mutex in component manager. ");
2644 	    return(RM_WHACKED);
2645 	}
2646 	return(RM_WHACKED);
2647     }
2648     n->prims[n->nprims] = prim;
2649     n->nprims++;
2650 
2651     if (rmMutexUnlock(global_RMnodePool->guard) == RM_WHACKED)
2652     {
2653 	rmError("rmNodeAddPrimitive() error: problem unlocking guard mutex in component manager. ");
2654 	return(RM_WHACKED);
2655     }
2656 
2657     return(RM_CHILL);
2658 }
2659 
2660 
2661 /*
2662  * ----------------------------------------------------
2663  * @Name rmNodeGetPrimitive
2664  @pstart
2665  RMprimitive * rmNodeGetPrimitive (const RMnode *toQuery,
2666 		                   int indx)
2667  @pend
2668 
2669  @astart
2670  const RMnode *toQuery - a handle to an RMnode (input).
2671 
2672  int indx - an integer value interpreted as an index (input).
2673  @aend
2674 
2675  @dstart
2676 
2677  Returns to the caller the RMprimitive handle of the i'th primitive in
2678  an RMnode.
2679 
2680  @dend
2681  * ----------------------------------------------------
2682  */
2683 RMprimitive *
rmNodeGetPrimitive(const RMnode * m,int j)2684 rmNodeGetPrimitive (const RMnode *m,
2685 		    int j)
2686 {
2687     if (RM_ASSERT(m, "rmNodeGetPrimitive() error: input node is NULL. \n") == RM_WHACKED)
2688 	return(NULL);
2689 
2690     if (m->prims == NULL)
2691 	return(NULL);
2692 
2693     if ((j < 0) || (j >= m->nprims)) /* error? warning? */
2694 	return(NULL);
2695 
2696     return(m->prims[j]);
2697 }
2698 
2699 
2700 /*
2701  * ----------------------------------------------------
2702  * @Name rmNodeSetClientData
2703  @pstart
2704  RMenum rmNodeSetClientData (RMnode *toModify,
2705 		             void *clientData,
2706 			     void (*cdFreeFunc)(RMnode *,void *))
2707  @pend
2708 
2709  @astart
2710  RMnode *toModify - a handle to an RMnode (modified).
2711 
2712  void *clientData - a handle (input).
2713 
2714  void (*cdFreeFunc)(RMnode *,void *) - a handle to an application
2715    callback (input).
2716  @aend
2717 
2718  @dstart
2719 
2720  Applications may store a handle to arbitrary memory in RMnodes or
2721  RMprimitives. This routine is used to place a handle to arbitrary
2722  memory in an RMnode, and returns RM_CHILL upon success or RM_WHACKED
2723  upon failure.
2724 
2725  Client data may be stored in both RMprimitives and RMnodes
2726  (rmNodeSetClientData).
2727 
2728  The "client data" handle may be later accessed using
2729  rmNodeGetClientData.
2730 
2731  The callback function will be invoked when the RMnode is deleted.
2732  The callback takes two parameters, a handle to the RMnode containing
2733  the client data handle, and the client data handle itself. The
2734  callback is provided so that applications may delete the data
2735  referenced by the client data handle stored in the RMnode.
2736 
2737  When the input client data handle is NULL, the old handle value is
2738  effectively overwritten. Any memory pointed to by the old client data
2739  handle will be lost (a potential memory leak).
2740 
2741  @dend
2742  * ----------------------------------------------------
2743  */
2744 RMenum
rmNodeSetClientData(RMnode * n,void * cd,void (* cd_free_func)(RMnode *,void *))2745 rmNodeSetClientData (RMnode *n,
2746 		     void *cd,
2747 		     void (*cd_free_func)(RMnode *,void *))
2748 {
2749     if (RM_ASSERT(n, "rmNodeeSetClientData() error: the input RMnode is NULL") == RM_WHACKED)
2750 	return(RM_WHACKED);
2751 
2752     n->clientData = cd;
2753     n->clientDataFreeFunc = cd_free_func;
2754 
2755     return(RM_CHILL);
2756 }
2757 
2758 
2759 /*
2760  * ----------------------------------------------------
2761  * @Name rmNodeGetClientData
2762  @pstart
2763  void * rmNodeGetClientData (const RMnode *toQuery)
2764  @pend
2765 
2766  @astart
2767  const RMnode *toQuery - a handle to an RMnode (input).
2768  @aend
2769 
2770  @dstart
2771 
2772  Use this routine to obtain the client data handle stored in an
2773  RMnode.
2774 
2775  @dend
2776  * ----------------------------------------------------
2777  */
2778 void *
rmNodeGetClientData(const RMnode * n)2779 rmNodeGetClientData (const RMnode *n)
2780 {
2781     if (RM_ASSERT(n, "rmNodeGetClientData() error: the input RMnode is NULL") == RM_WHACKED)
2782 	return((void *)NULL);
2783 
2784     return(n->clientData);
2785 }
2786 
2787 
2788 /*
2789  * ----------------------------------------------------
2790  * @Name rmPrimitiveSetAppDisplayList
2791  @pstart
2792  RMenum rmPrimitiveSetAppDisplayList (RMprimitive *toModify, GLuint appDisplayList)
2793  @pend
2794 
2795  @astart
2796  RMprimitive *toModify - a handle to an RMprimitive object (input).
2797  GLuint appDisplayList - a GLuint value (input).
2798  @aend
2799 
2800  @dstart
2801  Use this routine to assign a GL display list ID to an RMprimitive of
2802  type RM_APP_DISPLAYLIST. This type of RMprimitive is intended to be used
2803  by applications that need to create an OpenGL display list, perhaps using
2804  third-party modeling tools, and then have the display list contents rendered
2805  within an RM Scene Graph. Upon success, RM_CHILL is returned, while RM_WHACKED
2806  is returned upon failure.
2807 
2808  Restrictions apply when using application-defined display lists:
2809  (1) Applications are completely responsible for ensuring that the GLuint
2810  assigned as a display list ID is indeed valid.
2811  (2) After invoking the application-supplied display list, the the OpenGL
2812  state must be in exactly the same condition as it was before the
2813  display list was invoked. Failure to adhere to this rule will likely cause
2814  rendering errors that result from RM's inability to know about state changes
2815  made by the application display list.
2816 
2817  @dend
2818  * ----------------------------------------------------
2819  */
2820 RMenum
rmPrimitiveSetAppDisplayList(RMprimitive * toModify,GLuint displayListID)2821 rmPrimitiveSetAppDisplayList(RMprimitive *toModify,
2822 			     GLuint displayListID)
2823 {
2824     if (RM_ASSERT(toModify, "rmPrimitiveSetAppDisplayList() error: the input RMprimitive is NULL") == RM_WHACKED)
2825 	return RM_WHACKED;
2826 
2827     if (private_rmPrimitiveGetType(toModify) != RM_APP_DISPLAYLIST)
2828     {
2829 	rmError("rmPrimitiveSetAppDisplayList() error - the input primitive is not of type RM_APP_DISPLAYLIST");
2830 	return RM_WHACKED;
2831     }
2832 
2833     toModify->flags1 = displayListID;
2834 
2835     return RM_CHILL;
2836 }
2837 
2838 RMenum
private_rmPrimitiveSetMultiTexcoordBlob(RMprimitive * p,int tcTag,int num,int stride,void * stuff,RMenum copyFlag,void (* freefunc)(void *),int textureUnit)2839 private_rmPrimitiveSetMultiTexcoordBlob(RMprimitive *p,
2840 					int tcTag,
2841 					int num,
2842 					int stride,
2843 					void *stuff,
2844 					RMenum copyFlag,
2845 					void (*freefunc)(void *),
2846 					int textureUnit)
2847 /*
2848  * 2/2005.
2849  * Unlike private_rmPrimitiveSetItem, which is intended to be a reasonably
2850  * general interface to map the most common primitive elements into a
2851  * finite number of data blobs, this routine instead accesses blob array
2852  * specifically set aside for multitexture TCs. We still use the blob
2853  * interface for setting/getting stuff in the data blobs, but the
2854  * more general approach doesn't work so well for multitexture TCs.
2855  */
2856 {
2857     /*
2858      * input validity checking -
2859      * 1. textureUnit. We can only check for 0 <= textureUnit <= RM_MAX_MULTITEXTURES.
2860      *    we can't compare against the number of multitexture units supported
2861      *    by the OpenGL implementation here - that's a render-time check.
2862      */
2863     RMprimitiveDataBlob *b;
2864     int newMask;
2865     int numMTCs, i, junk;
2866 
2867     if ((textureUnit < 0) || (textureUnit >= RM_MAX_MULTITEXTURES))
2868     {
2869 	rmWarning("private_rmPrimitiveSetMultiTexcoordBlob error() - the input textureUnit is either less than zero or greater than or equal to RM_MAX_MULTITEXTURES. Failing to assign multitexture coords as requested. ");
2870 	return RM_WHACKED;
2871     }
2872 
2873     private_rmPrimitiveSetCacheKey(p);
2874 
2875     /*
2876      * RMprimitives don't start out with prealloced blobs for multitexture TCs.
2877      * create a pile of blobs if none exist.
2878      */
2879     if (p->multiTextureCoordBlobs == NULL)
2880     {
2881 	p->multiTextureCoordBlobs = (RMprimitiveDataBlob *)malloc(sizeof(RMprimitiveDataBlob) * RM_MAX_MULTITEXTURES);
2882 	memset(p->multiTextureCoordBlobs, 0, sizeof(RMprimitiveDataBlob) * RM_MAX_MULTITEXTURES);
2883     }
2884 
2885     /* we directly access the MTC blobs based upon textureUnit */
2886     b = &(p->multiTextureCoordBlobs[textureUnit]);
2887 
2888     if ((copyFlag == RM_DONT_COPY_DATA) && (freefunc != NULL))
2889 	private_rmBlobSetFreefunc(b, freefunc);
2890     else if ((copyFlag == RM_DONT_COPY_DATA) && (freefunc == NULL))
2891     {
2892 	rmError("private_rmPrimitiveSetMultiTexcoordBlob: a freefunc is required when you use RM_DONT_COPY_DATA.");
2893 	return RM_WHACKED;
2894     }
2895 
2896     /* use normal interface to set data in the blob */
2897     private_rmBlobSetNthings(b ,num);
2898     private_rmBlobSetStride(b, stride);
2899     private_rmBlobSetData(b, num, stride, stuff, copyFlag);
2900 
2901     switch (tcTag)
2902     {
2903     case RM_PRIMITIVE_MULTI_1DTCOORDS:
2904 	private_rmBlobSetVeclen(b, 1);
2905 	break;
2906 
2907     case RM_PRIMITIVE_MULTI_2DTCOORDS:
2908 	private_rmBlobSetVeclen(b, 2);
2909 	break;
2910 
2911     case RM_PRIMITIVE_MULTI_3DTCOORDS:
2912 	private_rmBlobSetVeclen(b, 3);
2913 	break;
2914     }
2915 
2916     /* update the mask to reflect the addition of new MTC's */
2917     newMask = 1 << textureUnit;
2918 
2919     /* we might be writing over the MTCs for a texture unit
2920        set during a previous invocation (app data update) */
2921     junk = p->multiTextureCoordBlobsMask |= newMask;
2922 
2923     /* count up the number of MTC blobs */
2924     for (i=0, numMTCs=0; (i<RM_MAX_MULTITEXTURES) && (junk != 0); i++)
2925     {
2926 	if (junk & 0x1)
2927 	    numMTCs++;
2928 	junk = junk >> 1;
2929     }
2930 
2931     /* and set the field indicating the number of MTC blobs */
2932     p->numMultiTextureCoordBlobs = numMTCs;
2933 
2934     return RM_CHILL;
2935 }
2936 
2937 /* PRIVATE
2938  *
2939  * the following is a private, interal routine used to interface between
2940  * application level API and the guts of the RMprimitive "blob model"
2941  * of data management.
2942  */
2943 RMenum
private_rmPrimitiveSetItem(RMprimitive * p,int tag,int num,int stride,void * stuff,RMenum copy_flag,void (* freefunc)(void *))2944 private_rmPrimitiveSetItem (RMprimitive *p, 		/* primitive to add to */
2945 			    int tag,			/* definition */
2946 			    int num,			/* how many */
2947 			    int stride,			/* size of individual thing in bytes -stride*/
2948 			    void *stuff, 		/* pointer to the stuff */
2949 			    RMenum copy_flag, 		/* RM_COPY_DATA/RM_DONT_COPY_DATA */
2950 			    void (*freefunc)(void *))  /* free function for prim */
2951 {
2952     /*
2953      * Tue Sep 30 20:36:53 PDT 1997 - added clutch code that sits
2954      * between RMvertex3D and true float[]'s - to avoid padding magic
2955      * that happens on some compilers.
2956      */
2957     /*
2958      * Fri Oct  2 08:42:46 PDT 1998 - copy flag and client data free
2959      * func added. some compilers on 64bit OS's pad structures to 8-byte
2960      * boundaries. therefore, an  RMvertex3D structure that consists of
2961      * 3 floats is padded out to the next 8-byte boundary. OpenGL
2962      * vertex arrays allow for this kind of thing with a stride
2963      * parameter.
2964      *
2965      * Sat Oct 28 10:53:57 PDT 2000 - all prims get their cache key
2966      * updated whenever anything in the prim is set.
2967      */
2968     int                  blob_index;
2969     RMenum               rstat = RM_CHILL;
2970     RMprimitiveDataBlob *b;
2971 
2972     private_rmPrimitiveSetCacheKey(p);
2973 
2974     switch (tag)
2975 	{
2976 	case RM_PRIMITIVE_3DVERTICES:
2977 	case RM_PRIMITIVE_2DVERTICES:
2978 	    {
2979 		blob_index = private_rmBlobIndexFromPrimAtom(tag);
2980 		b = private_rmBlobFromIndex(p, blob_index);
2981 
2982 		private_rmBlobSetNthings(b, num);
2983 		private_rmBlobSetStride(b, stride);
2984 		private_rmBlobSetVeclen(b, (tag == RM_PRIMITIVE_3DVERTICES) ? 3 : 2);
2985 		private_rmBlobSetData(b, num, stride, stuff, copy_flag);
2986 		private_rmBlobSetType(b, blob_index);
2987 
2988 
2989 		if ((copy_flag == RM_DONT_COPY_DATA) && (freefunc != NULL))
2990 		    private_rmBlobSetFreefunc(b, freefunc);
2991 		else if ((copy_flag == RM_DONT_COPY_DATA) && (freefunc == NULL))
2992 		{
2993 		    rmError("rmPrimitiveSetItem: a freefunc is required when you use RM_DONT_COPY_DATA.");
2994 		    rstat = RM_WHACKED;
2995 		}
2996 	    }
2997         break;
2998 
2999 	case RM_PRIMITIVE_4COLORS:
3000 	case RM_PRIMITIVE_3COLORS:
3001 	    {
3002 		blob_index = private_rmBlobIndexFromPrimAtom(tag);
3003 		b = private_rmBlobFromIndex(p, blob_index);
3004 
3005 		private_rmBlobSetNthings(b ,num);
3006 		private_rmBlobSetStride(b, stride);
3007 		private_rmBlobSetData(b, num, stride, stuff, copy_flag);
3008 		private_rmBlobSetVeclen(b, (tag == RM_PRIMITIVE_4COLORS) ? 4 : 3);
3009 		private_rmBlobSetType(b, blob_index);
3010 
3011 
3012 		if ((copy_flag == RM_DONT_COPY_DATA) && (freefunc != NULL))
3013 		    private_rmBlobSetFreefunc(b, freefunc);
3014 		else if ((copy_flag == RM_DONT_COPY_DATA) && (freefunc == NULL))
3015 		{
3016 		    rmError("rmPrimitiveSetItem: a freefunc is required when you use RM_DONT_COPY_DATA.");
3017 		    rstat = RM_WHACKED;
3018 		}
3019 		break;
3020 	    }
3021 
3022 	case RM_PRIMITIVE_1DTCOORDS:
3023 	case RM_PRIMITIVE_2DTCOORDS:
3024 	case RM_PRIMITIVE_3DTCOORDS:
3025 	case RM_PRIMITIVE_NORMALS:
3026 	    {
3027 		int veclen = 0; /* init satisfies gcc warning */
3028 
3029 		blob_index = private_rmBlobIndexFromPrimAtom(tag);
3030 		b = private_rmBlobFromIndex(p, blob_index);
3031 
3032 		private_rmBlobSetNthings(b, num);
3033 		private_rmBlobSetStride(b, stride);
3034 		private_rmBlobSetData(b, num, stride, stuff, copy_flag);
3035 
3036 		/* set veclen */
3037 		if ((tag == RM_PRIMITIVE_NORMALS) || (tag == RM_PRIMITIVE_3DTCOORDS))
3038 		    veclen = 3;
3039 		else if (tag == RM_PRIMITIVE_2DTCOORDS)
3040 		    veclen = 2;
3041 		else if (tag == RM_PRIMITIVE_1DTCOORDS)
3042 		    veclen = 1;
3043 
3044 		private_rmBlobSetVeclen(b, veclen);
3045 
3046 		if ((copy_flag == RM_DONT_COPY_DATA) && (freefunc != NULL))
3047 		    private_rmBlobSetFreefunc(b, freefunc);
3048 		else if ((copy_flag == RM_DONT_COPY_DATA) && (freefunc == NULL))
3049 		{
3050 		    rmError("rmPrimitiveSetItem: a freefunc is required when you use RM_DONT_COPY_DATA.");
3051 		    rstat = RM_WHACKED;
3052 		}
3053 		break;
3054 	    }
3055 
3056 	case RM_PRIMITIVE_OMESHDIMS:
3057 	case RM_PRIMITIVE_QMESHDIMS:
3058 	    {
3059 		blob_index = private_rmBlobIndexFromPrimAtom(tag);
3060 		b = private_rmBlobFromIndex(p, blob_index);
3061 
3062 		private_rmBlobSetNthings(b, num);
3063 		private_rmBlobSetStride(b, stride );
3064 		private_rmBlobSetData(b, num, stride, stuff, copy_flag);
3065 
3066 		if ((copy_flag == RM_DONT_COPY_DATA) && (freefunc != NULL))
3067 		    private_rmBlobSetFreefunc(b, freefunc);
3068 		else if ((copy_flag == RM_DONT_COPY_DATA) && (freefunc == NULL))
3069 		{
3070 		    rmError("rmPrimitiveSetItem: a freefunc is required when you use RM_DONT_COPY_DATA.");
3071 		    rstat = RM_WHACKED;
3072 		}
3073 		break;
3074 	    }
3075 
3076 	case RM_PRIMITIVE_MARKERS2D_SCALE:
3077 	case RM_PRIMITIVE_CYLINDER_RADII:
3078 	case RM_PRIMITIVE_CONE_RADII:
3079 	case RM_PRIMITIVE_RADII:
3080 	case RM_PRIMITIVE_INDICES:
3081 	    {
3082 		blob_index = private_rmBlobIndexFromPrimAtom(tag);
3083 		b = private_rmBlobFromIndex(p, blob_index);
3084 
3085 		private_rmBlobSetNthings(b, num);
3086 		private_rmBlobSetStride(b, stride);
3087 		private_rmBlobSetData(b, num, stride, stuff, copy_flag);
3088 
3089 		/* set veclength */
3090 
3091 		if ((copy_flag == RM_DONT_COPY_DATA) && (freefunc != NULL))
3092 		    private_rmBlobSetFreefunc(b, freefunc);
3093 		else if ((copy_flag == RM_DONT_COPY_DATA) && (freefunc == NULL))
3094 		{
3095 		    rmError("rmPrimitiveSetItem: a freefunc is required when you use RM_DONT_COPY_DATA.");
3096 		    rstat = RM_WHACKED;
3097 		}
3098 
3099 		break;
3100 	    }
3101 
3102 	case RM_PRIMITIVE_OMESH_MINMAX_GRID:
3103 	    {
3104 		/*
3105 		 * the omesh min-max grid is expanded to a rectilinear
3106 		 * grid here. we go from two RMvertex's to an array of
3107 		 * floats, the length of which is usize+vsize+wsize;
3108 		 *
3109 		 * the dimensions of the octmesh MUST be defined before
3110 		 * the grid is defined, otherwise this hunk of code fails.
3111 		 *
3112 		 * we ignore the copy flag passed in to this routine, and
3113 		 * create our own "copy" of the grid via the expansion from
3114 		 * corner points to 3 rectilinear arrays.
3115 		 */
3116 
3117 		int                  i, *dims;
3118 		float                t, dt, *f, *xspacing, *yspacing, *zspacing;
3119 		RMvertex3D          *gmin,*gmax;
3120 		RMprimitiveDataBlob *s;
3121 
3122 		/* check to see if usize, vsize and wsize are set */
3123 		i = private_rmBlobIndexFromPrimAtom(RM_PRIMITIVE_OMESHDIMS);
3124 		s = private_rmBlobFromIndex(p, i);
3125 
3126 		{
3127 		    int npts = private_rmBlobGetNthings(s);
3128 
3129 		    dims = (int *)private_rmBlobGetData(s);
3130 		    if ((dims == NULL) || (npts != 3))
3131 			{
3132 			    rmError(" the size of the Octmesh must be defined prior to setting the grid. Skipping the assignment of the grid. \n");
3133 			    return(RM_WHACKED);
3134 			}
3135 		}
3136 
3137 		/* malloc the hunk of memory used to hold the expanded grid */
3138 		f = (float *)malloc(sizeof(float) * (dims[0] + dims[1] + dims[2]));
3139 		xspacing = f;
3140 		yspacing = xspacing + dims[0];
3141 		zspacing = yspacing + dims[1];
3142 
3143 		gmin = (RMvertex3D *)stuff;
3144 		gmax = gmin + 1;	/* ?? */
3145 
3146 		/* do the x axis */
3147 		t = gmin->x;
3148 		dt = (gmax->x - gmin->x) / (dims[0] - 1);
3149 
3150 		for (i = 0; i < dims[0]; i++, t += dt)
3151 		    xspacing[i] = t;
3152 
3153 		/* do the y axis */
3154 		t = gmin->y;
3155 		dt = (gmax->y - gmin->y) / (dims[1]- 1);
3156 
3157 		for (i = 0; i < dims[1]; i++, t += dt)
3158 		    yspacing[i] = t;
3159 
3160 		/* do the z-axis */
3161 		t = gmin->z;
3162 		dt = (gmax->z - gmin->z) / (dims[2] - 1);
3163 
3164 		for (i = 0; i < dims[2]; i++, t += dt)
3165 		    zspacing[i] = t;
3166 
3167 		i = private_rmBlobIndexFromPrimAtom(tag);
3168 		b = private_rmBlobFromIndex(p, i);
3169 		private_rmBlobSetType(b, i);
3170 
3171 		private_rmBlobSetNthings(b, (dims[0] + dims[1] + dims[2]));
3172 		private_rmBlobSetStride(b, sizeof(float));
3173 		private_rmBlobSetData(b, (dims[0] + dims[1] + dims[2]), sizeof(float), f, RM_COPY_DATA);
3174 
3175 		free(f);
3176 		break;
3177 	    }
3178 
3179 	case RM_PRIMITIVE_MARKERS2D_PRIM:
3180 	    {
3181 		RMinternalMarker2D **m;
3182 
3183 		if (p->p1)
3184 		    free(p->p1);
3185 
3186 		/* hack - we assume that there is only one of these things that is being passed in. */
3187 		m = (RMinternalMarker2D **)stuff;
3188 
3189 		p->p1 = (void *)rmInternalMarker2DNew(m[0]->npts, m[0]->gl_begin_flag, m[0]->vlist);
3190 		p->flags1 = num;
3191 
3192 		rstat = RM_CHILL;
3193 		break;
3194 	    }
3195 
3196 	case RM_PRIMITIVE_SPRITES:
3197 	    {
3198 		int       i;
3199 		RMimage **img, **src;
3200 
3201 		/*
3202 		 * in sprite primitives, we use p1 to point to a list of
3203 		 * RMimages's.  the flags1 field is set in this chunk of
3204 		 * code to reflect the actual number of cached sprites.
3205 		 * we use this internal field so that we can properly
3206 		 * free up old sprite's.
3207 		 */
3208 
3209 		if (rmPrimitiveGetType(p) != RM_SPRITE)
3210 		{
3211 		    rmError("error trying to add sprites to a non-sprite primitive type.");
3212 		    return(RM_WHACKED);
3213 		}
3214 		if (p->p1)
3215 		{
3216 		    /* free up old one's */
3217 		    img = (RMimage **) (p->p1);
3218 		    for (i = 0; i < (int)(p->flags1); i++)
3219 			rmImageDelete(img[i]);
3220 
3221 		    free((void *)(img));
3222 		    p->flags1 = 0;
3223 		}
3224 
3225 		/* now build a new list, duplicating the input images */
3226 		src = (RMimage **)stuff;
3227 		img = (RMimage **)malloc(sizeof(RMimage *)*num);
3228 		for (i = 0; i < num; i++)
3229 		    img[i] = rmImageDup(src[i]);
3230 
3231 		p->p1 = (void *)img;
3232 		p->flags1 = num;
3233 
3234 		break;
3235 	    }
3236 
3237 	case RM_PRIMITIVE_BITMAPS:
3238 	    {
3239 		/*
3240 		 * the "p1" field is used as a pointer to a list of bitmaps.
3241 		 * the "flags1" field is used to hold the count of bitmaps
3242 		 *    in the p1 field.
3243 		 */
3244 		int        i;
3245 		RMbitmap **src, **bmp;
3246 
3247 		i = rmPrimitiveGetType(p);
3248 
3249 		if ((i != RM_BITMAP) && (i != RM_INDEXED_BITMAP) && (i != RM_TEXT) && (i != RM_INDEXED_TEXT))
3250 		{
3251 		    rmError("attempting to add bitmaps to a primitive which is not of type RM_BITMAP or RM_BITMAP_INDICES. \n");
3252 		    return(RM_WHACKED);
3253 		}
3254 
3255 		if (p->p1)
3256 		{
3257 		    /* free the old ones. */
3258 		    bmp = (RMbitmap **) (p->p1);
3259 		    for (i = 0; i < (int)(p->flags1); i++)
3260 			rmBitmapDelete(bmp[i]);
3261 
3262 		    free((void *)(bmp));
3263 		    p->flags1 = 0;
3264 		}
3265 
3266 		/* now build a new list, duplicating the input images */
3267 		src = (RMbitmap **)stuff;
3268 
3269 		bmp = (RMbitmap **)malloc(sizeof(RMbitmap *)*num);
3270 		for (i = 0; i < num; i++)
3271 		    bmp[i] = rmBitmapDup(src[i]);
3272 
3273 		p->p1 = (void *)bmp;
3274 		p->flags1 = num;
3275 
3276 		break;
3277 	    }
3278 
3279 	default:
3280 	    rmWarning(" undefined primitive type used in private_rmPrimitiveSetItem() ");
3281 	    rstat = RM_WHACKED;
3282 	    break;
3283 	}
3284     return(rstat);
3285 }
3286 
3287 
3288 /* PRIVATE
3289  *
3290  * this private routine is used by some of the draw functions to
3291  * get at specific parts of the RMprimitive data. vertices, colors,
3292  * indices, etc are all handled by the blob data model, and attempting
3293  * to access those items with this routine will produce an error message.
3294  */
3295 RMenum
private_rmPrimitiveGetItem(RMprimitive * p,int tag,int * num,void ** stuff)3296 private_rmPrimitiveGetItem (RMprimitive *p,
3297 			    int tag,
3298 			    int *num,
3299 			    void **stuff)
3300 {
3301     RMenum rstat = RM_WHACKED;
3302 
3303     switch (tag)
3304     {
3305     case RM_PRIMITIVE_3DVERTICES:
3306     case RM_PRIMITIVE_2DVERTICES:
3307     case RM_PRIMITIVE_2DTCOORDS:
3308     case RM_PRIMITIVE_4COLORS:
3309     case RM_PRIMITIVE_3COLORS:
3310     case RM_PRIMITIVE_NORMALS:
3311     case RM_PRIMITIVE_MARKERS2D_SCALE:
3312     case RM_PRIMITIVE_CYLINDER_RADII:
3313     case RM_PRIMITIVE_CONE_RADII:
3314     case RM_PRIMITIVE_RADII:
3315     case RM_PRIMITIVE_QMESHDIMS:
3316     case RM_PRIMITIVE_OMESHDIMS:
3317     case RM_PRIMITIVE_BITMAP_INDICES:
3318 	{
3319 	    fprintf(stderr," improper use of RMprimitiveGetItem! \n");
3320 	    break;
3321 	}
3322 
3323     case RM_PRIMITIVE_RENDERFUNC:
3324 	{
3325 	    if (p->renderfunc)
3326 	    {
3327 		*stuff = (void *)(p->renderfunc);
3328 		rstat = RM_CHILL;
3329 	    }
3330 	    else
3331 		rstat = RM_WHACKED;
3332 	}
3333 	break;
3334 
3335 
3336     case RM_PRIMITIVE_MARKERS2D_PRIM:
3337     case RM_PRIMITIVE_SPRITES:
3338     case RM_PRIMITIVE_BITMAPS:
3339     case RM_PRIMITIVE_TEXTPRIM:
3340 	{
3341 	    if (p->p1)
3342 	    {
3343 		*num = p->flags1;
3344 		*stuff = p->p1;
3345 		rstat = RM_CHILL;
3346 	    }
3347 	    else
3348 		*num = 0;
3349 	}
3350 	break;
3351     }
3352     return(rstat);
3353 }
3354 
3355 
3356 /* PRIVATE */
3357 RMenum
private_rmPrimitiveGetText(RMprimitive * t,int * nstringsReturn,RMtextPrim ** primsReturn)3358 private_rmPrimitiveGetText (RMprimitive *t,
3359 			    int *nstringsReturn,
3360 			    RMtextPrim **primsReturn)
3361 {
3362     /* this routine needs some work */
3363     if ((t->flags1 != 0) && (t->p1 != NULL))
3364     {
3365 	*nstringsReturn = t->flags1;
3366 	*primsReturn = (RMtextPrim *)(t->p1);
3367 	return(RM_CHILL);
3368     }
3369     else
3370 	return(RM_WHACKED);
3371 }
3372 
3373 /* PRIVATE */
3374 void
private_rmBlobSetType(RMprimitiveDataBlob * b,int newtype)3375 private_rmBlobSetType (RMprimitiveDataBlob *b,
3376 		       int newtype)
3377 {
3378     /*
3379      * the intent is to store in "blobtype" the RM_PRIMITIVE_* tag
3380      * assigned by the user. we need this info because, to some extent,
3381      * the user data is homogonized in the cast-to-blob process. some
3382      * primitive rendering & mem. mgt handling code in RM needs this
3383      * info.
3384      */
3385     b->blobtype = newtype;
3386 }
3387 
3388 
3389 /* PRIVATE */
3390 int
private_rmBlobGetType(RMprimitiveDataBlob * b)3391 private_rmBlobGetType (RMprimitiveDataBlob *b)
3392 {
3393     return(b->blobtype);
3394 }
3395 
3396 
3397 /* PRIVATE */
3398 void
private_rmBlobSetNthings(RMprimitiveDataBlob * b,int num)3399 private_rmBlobSetNthings (RMprimitiveDataBlob *b,
3400 			  int num)
3401 {
3402     b->nthings = num;
3403 }
3404 
3405 
3406 /* PRIVATE */
3407 int
private_rmBlobGetNthings(RMprimitiveDataBlob * b)3408 private_rmBlobGetNthings (RMprimitiveDataBlob *b)
3409 {
3410     return(b->nthings);
3411 }
3412 
3413 
3414 /* PRIVATE */
3415 void
private_rmBlobSetStride(RMprimitiveDataBlob * b,int stride)3416 private_rmBlobSetStride (RMprimitiveDataBlob *b,
3417 			 int stride)
3418 {
3419     b->stride = stride;
3420 }
3421 
3422 /* PRIVATE */
3423 void
private_rmBlobSetVeclen(RMprimitiveDataBlob * b,int veclen)3424 private_rmBlobSetVeclen (RMprimitiveDataBlob *b,
3425 			 int veclen)
3426 {
3427     b->veclen = veclen;
3428 }
3429 
3430 
3431 /* PRIVATE */
3432 int
private_rmBlobGetVeclen(RMprimitiveDataBlob * b)3433 private_rmBlobGetVeclen (RMprimitiveDataBlob *b)
3434 {
3435     return(b->veclen);
3436 }
3437 
3438 
3439 /* PRIVATE */
3440 void
private_rmBlobSetData(RMprimitiveDataBlob * b,int num,int stride,void * stuff,RMenum copy_flag)3441 private_rmBlobSetData (RMprimitiveDataBlob *b,
3442 		       int num,
3443 		       int stride,
3444 		       void *stuff,
3445 		       RMenum copy_flag)
3446 {
3447     /*
3448      * first, free up old stuff. if RM is responsible for the data, do
3449      * a free(). if the app is repsonsible, invoke the appfreefunc().
3450      */
3451     if ((b->copyflag == RM_COPY_DATA) && (b->ptr != NULL))
3452 	free(b->ptr);
3453     else if ((b->copyflag == RM_DONT_COPY_DATA) && (b->appfreefunc != NULL))
3454 	(*(b->appfreefunc))(b->ptr);
3455 
3456     if (copy_flag == RM_COPY_DATA)
3457     {
3458 	int nbytes;
3459 	nbytes = stride*num;
3460 	b->ptr = (void *)malloc(nbytes);
3461 	b->copyflag = copy_flag;
3462 	memcpy(b->ptr, stuff, nbytes);
3463     }
3464     else
3465     {
3466 	b->ptr = stuff;
3467 	b->copyflag = copy_flag;
3468     }
3469 }
3470 
3471 
3472 /* PRIVATE */
3473 void
private_rmBlobSetFreefunc(RMprimitiveDataBlob * b,void (* freefunc)(void *))3474 private_rmBlobSetFreefunc (RMprimitiveDataBlob *b,
3475 			   void (*freefunc)(void *))
3476 {
3477     b->appfreefunc = freefunc;
3478 }
3479 
3480 
3481 /* PRIVATE */
3482 int
private_rmBlobGetStride(RMprimitiveDataBlob * b)3483 private_rmBlobGetStride (RMprimitiveDataBlob *b)
3484 {
3485     return(b->stride);
3486 }
3487 
3488 
3489 /* PRIVATE */
3490 void *
private_rmBlobGetData(RMprimitiveDataBlob * b)3491 private_rmBlobGetData (RMprimitiveDataBlob *b)
3492 {
3493     return(b->ptr);
3494 }
3495 
3496 
3497 /* PRIVATE */
3498 int
private_rmBlobIndexFromPrimAtom(int tag)3499 private_rmBlobIndexFromPrimAtom (int tag)
3500 {
3501     int rstat;
3502     /*
3503      * this code translates from an RM_PRIMITIVE_* tag to a blob tag.
3504      * this is used by rm routines that need to stuff app's prim data
3505      * into blobs
3506      */
3507     switch(tag)
3508     {
3509     case RM_PRIMITIVE_3DVERTICES:
3510     case RM_PRIMITIVE_2DVERTICES:
3511 	rstat = BLOB_VERTEX_INDEX;
3512 	break;
3513 
3514     case RM_PRIMITIVE_OMESH_MINMAX_GRID:
3515 	rstat = BLOB_OMESH_RECTGRID_INDEX;
3516 	break;
3517 
3518     case RM_PRIMITIVE_4COLORS:
3519     case RM_PRIMITIVE_3COLORS:
3520 	rstat = BLOB_COLOR_INDEX;
3521 	break;
3522 
3523     case RM_PRIMITIVE_NORMALS:
3524 	rstat = BLOB_NORMAL_INDEX;
3525 	break;
3526 
3527     case RM_PRIMITIVE_1DTCOORDS:
3528     case RM_PRIMITIVE_2DTCOORDS:
3529     case RM_PRIMITIVE_3DTCOORDS:
3530 	rstat = BLOB_TC_INDEX;
3531 	break;
3532 
3533     case RM_PRIMITIVE_MARKERS2D_SCALE:
3534     case RM_PRIMITIVE_CYLINDER_RADII:
3535     case RM_PRIMITIVE_CONE_RADII:
3536     case RM_PRIMITIVE_RADII:
3537 	rstat = BLOB_SCALE_INDEX;
3538 	break;
3539 
3540     case RM_PRIMITIVE_QMESHDIMS:
3541 	rstat = BLOB_QMESHDIMS_INDEX;
3542 	break;
3543 
3544     case RM_PRIMITIVE_OMESHDIMS:
3545 	rstat = BLOB_OMESHDIMS_INDEX;
3546 	break;
3547 
3548     case RM_PRIMITIVE_INDICES:
3549 	rstat = BLOB_INDEX_INDEX;
3550 	break;
3551 
3552     default:
3553         rstat = RM_WHACKED;
3554         break;
3555 
3556 	/* no texture coords yet */
3557     }
3558     return(rstat);
3559 }
3560 
3561 
3562 /* PRIVATE */
3563 RMprimitiveDataBlob *
private_rmBlobFromIndex(RMprimitive * p,int tag)3564 private_rmBlobFromIndex (RMprimitive *p,
3565 			 int tag)
3566 {
3567     /* used by rm routines that need to get at the data in blobs */
3568     RMprimitiveDataBlob *b;
3569 
3570     switch (tag)
3571     {
3572     case BLOB_VERTEX_INDEX:
3573     case BLOB_OMESH_RECTGRID_INDEX:
3574 	b = &(p->blobs[0]);
3575 	break;
3576 
3577     case BLOB_COLOR_INDEX:
3578 	b = &(p->blobs[1]);
3579 	break;
3580 
3581     case BLOB_TC_INDEX:
3582 	b = &(p->blobs[3]);
3583 	break;
3584 
3585     case BLOB_NORMAL_INDEX:
3586 	b = &(p->blobs[2]);
3587 	break;
3588 
3589     case BLOB_QMESHDIMS_INDEX:
3590     case BLOB_OMESHDIMS_INDEX:
3591     case BLOB_INDEX_INDEX:
3592 	b = &(p->blobs[4]);
3593 	break;
3594 
3595     case BLOB_SCALE_INDEX:
3596 	b = &(p->blobs[5]);
3597 	break;
3598 
3599     default:
3600 	b = NULL;
3601 	fprintf(stderr, "private_rmBlobFromIndex() code not finished or unrecognized blob type \n");
3602 	break;
3603     }
3604     return(b);
3605 }
3606 
3607 
3608 /* PRIVATE
3609  *
3610  * the following is a convenience routine used by most of the methods
3611  * that assign data to RMprimitives. it is a way to do sanity checking
3612  * of input parameters, and avoids a lot of duplicated code. it's a
3613  * compact, reusable routine for performing input validation.
3614  */
3615 RMenum
private_rmPrimSetAssert(RMprimitive * t,int n,void * dataptr,RMenum copyEnum,void (* freefunc)(),const char * rname)3616 private_rmPrimSetAssert (RMprimitive *t,
3617 			 int n,
3618 			 void *dataptr,
3619 			 RMenum copyEnum,
3620 			 void (*freefunc)(),
3621 			 const char *rname)
3622 {
3623     char buf[256];
3624 
3625     sprintf(buf, "%s error: the input primitive is NULL", rname);
3626     if (RM_ASSERT(t, buf) == RM_WHACKED)
3627 	return(RM_WHACKED);
3628 
3629     sprintf(buf, "%s error: non-zero data count but have NULL data pointer.", rname);
3630     if (((n != 0) && (dataptr == NULL)) == 1)
3631     {
3632 	rmError(buf);
3633 	return(RM_WHACKED);
3634     }
3635 
3636     sprintf(buf, "%s error: when the copy enum is set to RM_DONT_COPY_DATA, the application MUST provide a free function ", rname);
3637     if ((freefunc == NULL) && (copyEnum == RM_DONT_COPY_DATA))
3638     {
3639 	rmError(buf);
3640 	return(RM_WHACKED);
3641     }
3642     return(RM_CHILL);
3643 }
3644 
3645 /* private */
3646 RMenum
private_rmPrimitiveComputeGenericBoundingBox(RMprimitive * p)3647 private_rmPrimitiveComputeGenericBoundingBox(RMprimitive *p)
3648 {
3649     int                  nverts, stride;
3650     float               *v;
3651     RMprimitiveDataBlob *b;
3652     RMvertex3D           tmin, tmax;
3653 
3654     b = private_rmBlobFromIndex(p, BLOB_VERTEX_INDEX);
3655     v = (float *)private_rmBlobGetData(b);
3656 
3657     nverts = private_rmBlobGetNthings(b);
3658     stride = private_rmBlobGetStride(b);
3659     rmPointMinMax(v, nverts, private_rmBlobGetVeclen(b), stride, &tmin, &tmax);
3660 
3661     rmPrimitiveSetBoundingBox(p, &tmin, &tmax);
3662     return(RM_CHILL);
3663 }
3664 
3665 /* private */
3666 RMenum
private_rmPrimitiveComputeSpheresBoundingBox(RMprimitive * p)3667 private_rmPrimitiveComputeSpheresBoundingBox(RMprimitive *p)
3668 {
3669     int         j, rstride, nradii, rveclen, vstride, nvertices, vveclen;
3670     float      *radii, *vertices;
3671     RMvertex3D  smin, smax;
3672     RMvertex3D boxMin, boxMax;
3673 
3674 
3675     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nvertices, (void **)&vertices, &vveclen);
3676     private_rmGetBlobData(BLOB_SCALE_INDEX, p, &rstride, &nradii, (void **)&radii, &rveclen);
3677 
3678     /* compute bounding boxes for all spheres */
3679     for (j = 0; j < nvertices; j++, vertices += vstride, radii += rstride)
3680     {
3681 	/* extents = center +/- radius */
3682 	memcpy((void *)&smin, vertices, sizeof(RMvertex3D));
3683 	smax = smin;
3684 
3685 	smin.x -= *radii; smin.y -= *radii; smin.z -= *radii;
3686 	smax.x += *radii; smax.y += *radii; smax.z += *radii;
3687 
3688 	/* tally sphere bounding boxes */
3689 	if (j == 0)
3690 	{
3691 	    boxMin = smin;
3692 	    boxMax = smax;
3693 	}
3694 	else
3695 	    rmUnionBoundingBoxes(&boxMin, &boxMax, &smin, &smax, &boxMin, &boxMax);
3696     }
3697     /* just scan through all the vertices to find min/max */
3698 
3699     rmPrimitiveSetBoundingBox(p, &boxMin, &boxMax);
3700 
3701     return RM_CHILL;
3702 }
3703 
3704 /* private */
3705 RMenum
private_rmPrimitiveComputeCylindersBoundingBox(RMprimitive * p)3706 private_rmPrimitiveComputeCylindersBoundingBox(RMprimitive *p)
3707 {
3708     /*
3709      * we assume that the bbox for a cylinder is "almost the same as"
3710      * the union of the bbox formed by two spheres of radius R at
3711      * each end of the cylinder.
3712      */
3713     int         j, rstride, nradii, rveclen, vstride, nvertices, vveclen;
3714     float      *radii, *vertices;
3715     RMvertex3D  s1min, s1max, s2min, s2max;
3716     RMvertex3D  boxMin, boxMax;
3717 
3718     /* get vertex and radius blob info */
3719     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nvertices, (void **)&vertices, &vveclen);
3720     private_rmGetBlobData(BLOB_SCALE_INDEX, p, &rstride, &nradii, (void **)&radii, &rveclen);
3721 
3722     /* compute bounding boxes for all cylinders */
3723     for (j = 0; j < nvertices/2; j++, vertices += vstride, radii += rstride)
3724     {
3725 	/* extents = center +/- radius */
3726 	memcpy((void *)&s1min, vertices, sizeof(RMvertex3D));
3727 	vertices += vstride;
3728 	s1max = s1min;
3729 	memcpy((void *)&s2min, vertices, sizeof(RMvertex3D));
3730 	s2max = s2min;
3731 
3732 	s1min.x -= *radii; s1min.y -= *radii; s1min.z -= *radii;
3733 	s1max.x += *radii; s1max.y += *radii; s1max.z += *radii;
3734 
3735 	s2min.x -= *radii; s2min.y -= *radii; s2min.z -= *radii;
3736 	s2max.x += *radii; s2max.y += *radii; s2max.z += *radii;
3737 
3738 	/* tally sphere bounding boxes */
3739 	if (j == 0)
3740 	{
3741 	    rmUnionBoundingBoxes(&s1min, &s1max, &s2min, &s2max, &boxMin, &boxMax);
3742 	}
3743 	else
3744 	{
3745 	    rmUnionBoundingBoxes(&boxMin, &boxMax, &s1min, &s1max, &boxMin, &boxMax);
3746 	    rmUnionBoundingBoxes(&boxMin, &boxMax, &s2min, &s2max, &boxMin, &boxMax);
3747 	}
3748     }
3749 
3750     rmPrimitiveSetBoundingBox(p, &boxMin, &boxMax);
3751     return(RM_CHILL);
3752 }
3753 
3754 /* private */
3755 RMenum
private_rmPrimitiveComputeConesBoundingBox(RMprimitive * p)3756 private_rmPrimitiveComputeConesBoundingBox(RMprimitive *p)
3757 {
3758     /*
3759      * we assume that the bbox for a cone can be estimated as the
3760      * combination of a sphere centered at the base of the cone, and the
3761      * line segment formed by the two cone endpoints.
3762      */
3763     int         j, rstride, nradii, rveclen, vstride, nvertices, vveclen;
3764     float      *radii, *vertices;
3765     RMvertex3D  s1min, s1max, s2min, s2max;
3766     RMvertex3D  boxMin, boxMax;
3767 
3768     /* get vertex and radius blob info */
3769     private_rmGetBlobData(BLOB_VERTEX_INDEX, p, &vstride, &nvertices, (void **)&vertices, &vveclen);
3770     private_rmGetBlobData(BLOB_SCALE_INDEX, p, &rstride, &nradii, (void **)&radii, &rveclen);
3771 
3772     /* compute bounding boxes for all cones */
3773     for (j = 0; j < nvertices/2; j++, vertices += vstride, radii += rstride)
3774     {
3775 	/* extents = center +/- radius */
3776 	memcpy((void *)&s1min, vertices, sizeof(RMvertex3D));
3777 	vertices += vstride;
3778 	s1max = s1min;
3779 	memcpy((void *)&s2min, vertices, sizeof(RMvertex3D));
3780 	s2max = s2min;
3781 
3782 	s1min.x -= *radii; s1min.y -= *radii; s1min.z -= *radii;
3783 	s1max.x += *radii; s1max.y += *radii; s1max.z += *radii;
3784 
3785 	/* tally sphere bounding boxes */
3786 	if (j == 0)
3787 	{
3788 	    rmUnionBoundingBoxes(&s1min, &s1max, &s2min, &s2max, &boxMin, &boxMax);
3789 	}
3790 	else
3791 	{
3792 	    rmUnionBoundingBoxes(&boxMin, &boxMax, &s1min, &s1max, &boxMin, &boxMax);
3793 	    rmUnionBoundingBoxes(&boxMin, &boxMax, &s2min, &s2max, &boxMin, &boxMax);
3794 	}
3795     }
3796 
3797     rmPrimitiveSetBoundingBox(p, &boxMin, &boxMax);
3798     return(RM_CHILL);
3799 }
3800 
3801 /* private */
3802 RMenum
private_rmPrimitiveComputeOctmeshBoundingBox(RMprimitive * p)3803 private_rmPrimitiveComputeOctmeshBoundingBox(RMprimitive *p)
3804 {
3805     float               *v;
3806     RMprimitiveDataBlob *b;
3807     RMvertex3D           tmin, tmax;
3808     RMenum               haveValidOctmeshBox=RM_FALSE;
3809 
3810     /* this doesn't work for the weird octmesh grid types */
3811     b = private_rmBlobFromIndex(p, BLOB_VERTEX_INDEX);
3812     v = (float *)private_rmBlobGetData(b);
3813 
3814     switch(private_rmBlobGetType(b))
3815     {
3816 
3817 	/* 2/1/03 - the only support grid type for octmeshes is the
3818 	   minmax grid. that grid is converted into a rectilinear
3819 	   form when the app sets the grid corners. */
3820        case BLOB_OMESH_RECTGRID_INDEX:
3821        {
3822 	   int                 *dims, i;
3823 	   RMprimitiveDataBlob *s;
3824 	   int npts;
3825 
3826 	   i = private_rmBlobIndexFromPrimAtom(RM_PRIMITIVE_OMESHDIMS);
3827 	   s = private_rmBlobFromIndex(p, i);
3828 
3829 	   npts = private_rmBlobGetNthings(s);
3830 	   dims = (int *)private_rmBlobGetData(s);
3831 	   if (dims == NULL) 	/* no size info, can't compute size so leave it unchanged*/
3832 	       return(RM_WHACKED);
3833 
3834 	   haveValidOctmeshBox = RM_TRUE;
3835 
3836 	   tmin.x = tmax.x = v[0];
3837 	   for (i = 1; i < dims[0]; i++)
3838 	       {
3839 		   if (v[i] < tmin.x)
3840 		       tmin.x = v[i];
3841 		   if (v[i] > tmax.x)
3842 		       tmax.x = v[i];
3843 	       }
3844 
3845 	   v += dims[0];
3846 	   tmin.y = tmax.y = v[0];
3847 	   for (i = 1; i < dims[1]; i++)
3848 	       {
3849 		   if (v[i] < tmin.y)
3850 		       tmin.y = v[i];
3851 		   if (v[i] > tmax.y)
3852 		       tmax.y = v[i];
3853 	       }
3854 
3855 	   v += dims[1];
3856 	   tmin.z = tmax.z = v[0];
3857 	   for (i = 1; i < dims[2]; i++)
3858 	       {
3859 		   if (v[i] < tmin.z)
3860 		       tmin.z = v[i];
3861 		   if (v[i] > tmax.z)
3862 		       tmax.z = v[i];
3863 	       }
3864 	   break;
3865        }
3866 
3867     default: /* bogus blob type */
3868 	break;
3869     } /* end blobtype switch */
3870 
3871     if (haveValidOctmeshBox == RM_TRUE)
3872     {
3873 	rmPrimitiveSetBoundingBox(p, &tmin, &tmax);
3874 	return RM_CHILL;
3875     }
3876     else
3877     {
3878 	rmWarning("private_rmPrimitiveComputeOctmeshBoundingBox() - unable to obtain valid octmesh grid data. ");
3879 	return RM_WHACKED;
3880     }
3881 }
3882 
3883 /* private */
3884 RMenum
private_rmPrimitiveCompute2DCircleBoundingBox(RMprimitive * p)3885 private_rmPrimitiveCompute2DCircleBoundingBox(RMprimitive *p)
3886 {
3887     /* just scan through all the vertices to find min/max */
3888     rmNotice("private_rmPrimitiveCompute2DCircleBoundingBox(RMprimitive *p) - no code yet.");
3889     p = NULL; 			/* foil compiler warning */
3890     return RM_WHACKED;
3891 }
3892 
3893 /* private */
3894 RMenum
private_rmPrimitiveCompute2DEllipseBoundingBox(RMprimitive * p)3895 private_rmPrimitiveCompute2DEllipseBoundingBox(RMprimitive *p)
3896 {
3897     /* just scan through all the vertices to find min/max */
3898     rmNotice("private_rmPrimitiveCompute2DEllipseBoundingBox(RMprimitive *p) - no code yet. ");
3899     p = NULL; 			/* foil compiler warning */
3900     return RM_WHACKED;
3901 }
3902 
3903 /* private */
3904 RMenum
private_rmPrimitiveNullBoxFunc(RMprimitive * p)3905 private_rmPrimitiveNullBoxFunc(RMprimitive *p)
3906 {
3907     /* */
3908     p = NULL; 			/* foil compiler warning */
3909     return RM_WHACKED;
3910 }
3911 /* EOF */
3912