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