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: rmscene.c,v 1.15 2005/06/26 18:58:42 wes Exp $
27 * Version: $Name: OpenRM-1-6-0-2-RC2 $
28 * $Revision: 1.15 $
29 * $Log: rmscene.c,v $
30 * Revision 1.15 2005/06/26 18:58:42 wes
31 * Updated rmNodeSceneGetFog to return RM_WHACKED when no RMfog is present.
32 *
33 * Revision 1.14 2005/06/12 21:18:23 wes
34 * Minor language changes to in-code documentation.
35 *
36 * Revision 1.13 2005/06/06 02:04:29 wes
37 * Lots of small additions to clean up compiler warnings.
38 *
39 * Revision 1.12 2005/05/16 01:02:16 wes
40 * Updated code documentation.
41 *
42 * Revision 1.11 2005/02/24 16:17:25 wes
43 * Added support for fbClears to be set at the RMpipe level. Apps can
44 * still set them at the RMnode level if desired for fine-grained control.
45 *
46 * Revision 1.10 2005/02/19 16:22:50 wes
47 * Distro sync and consolidation.
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/06/22 05:01:58 wes
56 * Minor tweaks to support consistent state tracking. These changes
57 * were made as a result to changes in the main RMSG tree during a
58 * big PS bug fixing expedition.
59 *
60 * Revision 1.7 2004/04/09 14:48:18 wes
61 * Fix compile warnings about unused variables.
62 *
63 * Revision 1.6 2004/01/16 16:48:35 wes
64 * Updated copyright line for 2004.
65 *
66 * Revision 1.5 2003/11/22 00:53:41 wes
67 * Changes to support RMtextures being shared when assigned as scene parameters
68 * to properly implement instancing.
69 *
70 * Revision 1.4 2003/10/03 19:20:16 wes
71 * Repaired bogus error message on rmNodeSetSceneLight().
72 *
73 * Revision 1.3 2003/02/14 00:20:51 wes
74 * No significant changes.
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.15 2003/01/20 05:39:49 wes
83 * Rewrote texture state handling code.
84 *
85 * Revision 1.14 2003/01/16 22:21:17 wes
86 * Updated all source files to reflect new organization of header files:
87 * all header files formerly located in include/rmaux, include/rmi, include/rmv
88 * are now located in include/rm.
89 *
90 * Revision 1.13 2002/04/30 19:33:26 wes
91 * Updated copyright dates.
92 *
93 * Revision 1.12 2001/10/15 00:12:25 wes
94 * Different treatment of rmTextProps scene params. The rmTextProps is
95 * owned by the component manager, so we can't directly memcpy stuff from
96 * one to another without causing problems.
97 *
98 * Revision 1.11 2001/07/15 17:15:29 wes
99 * Cleanup of code that manages RMtextProps objects.
100 *
101 * Revision 1.10 2001/05/26 14:38:19 wes
102 * Doc additions.
103 *
104 * Revision 1.9 2001/03/31 17:12:39 wes
105 * v1.4.0-alpha-2 checkin.
106 *
107 * Revision 1.8 2000/12/05 03:02:52 wes
108 * Updated rmNodeSetSceneTexture to use rmImageDup() when copying
109 * images from caller-supplied Rmtexture. Code-resident docs also updated.
110 *
111 * Revision 1.7 2000/12/03 22:35:38 wes
112 * Mods for thread safety.
113 *
114 * Revision 1.6 2000/08/30 02:08:55 wes
115 * In rmNodeSetSceneClipPlane, moved creation of scene parms struct
116 * to earlier in the routine. Its previous placement was an error.
117 *
118 * Revision 1.5 2000/05/17 14:20:18 wes
119 * Added lots of documentation.
120 *
121 * Revision 1.4 2000/05/14 15:24:53 wes
122 * Added lots of documentation.
123 *
124 * Revision 1.3 2000/04/20 16:29:47 wes
125 * Documentation additions/enhancements, some code rearragement.
126 *
127 * Revision 1.2 2000/02/29 23:43:53 wes
128 * Compile warning cleanups.
129 *
130 * Revision 1.1.1.1 2000/02/28 21:29:40 wes
131 * OpenRM 1.2 Checkin
132 *
133 * Revision 1.1.1.1 2000/02/28 17:18:48 wes
134 * Initial entry - pre-RM120 release, source base for OpenRM 1.2.
135 *
136 */
137
138 /* documentation of public routines is incomplete in this file. */
139
140 #include <rm/rm.h>
141 #include "rmprivat.h"
142
143 /* PRIVATE declarations */
144 internals_RMsceneParms *private_rmNodeSceneParmsNew (void);
145
146 RMenum private_rmNodeSetSceneTexture(RMnode *n, RMtexture *t, int textureUnit);
147
148 /*
149 * ----------------------------------------------------
150 * @Name rmNodeSetSceneBackgroundColor
151 @pstart
152 RMenum rmNodeSetSceneBackgroundColor (RMnode *toModify,
153 const RMcolor4D *newColor)
154 @pend
155
156 @astart
157 RMnode *toModify - a handle to an RMnode (input).
158
159 const RMcolor4D *newColor - a handle to the desired background color
160 (input).
161 @aend
162
163 @dstart
164
165 Use this routine to set the background color scene parameter.
166 Calling this routine with a color argument of NULL disables the
167 background color scene parameter. During rendering, the color planes
168 of the framebuffer are cleared to this background color (with a depth
169 value of 1.0, see NOTE below).
170
171 Upon success, RM_CHILL is returned and the specified background color
172 scene parameter is set. Otherwise, RM_WHACKED is returned, and the
173 background color scene parameter remains unmodified.
174
175 Passing in a value of NULL for the RMcolor4D object will effectively
176 remove any existing background image color parameter from the RMnode toModify.
177
178 NOTE: internal to this routine, a call to rmNodeSetSceneDepthValue is
179 performed, effectively coupling framebuffer and depthbuffer clears.
180
181 Because this routine makes a copy of the input scene parameter (an
182 RMcolor4D object), callers do not need to manage the input object after a
183 successful return from this routine. This has important ramificiations:
184
185 1. Since a copy is made, any changes made to the caller's object will have
186 no effect upon the scene graph, unless this routine is called again to
187 update the scene parameter inside the scene graph;
188
189 2. Callers may safely delete their copy of the input object after a
190 successful return from this routine.
191
192 Related routines: rmNodeSetSceneBackgroundImageTile, rnNodeSetSceneDepthValue.
193
194 @dend
195 * ----------------------------------------------------
196 */
197 RMenum
rmNodeSetSceneBackgroundColor(RMnode * r,const RMcolor4D * new_color)198 rmNodeSetSceneBackgroundColor (RMnode *r,
199 const RMcolor4D *new_color)
200 {
201 if (RM_ASSERT(r, "rmNodeSetSceneBackgroundColor() error: the input RMnode pointer is NULL.") == RM_WHACKED)
202 return(RM_WHACKED);
203
204 if (r->fbClear == NULL)
205 r->fbClear = private_rmFBClearNew();
206
207 if (r->fbClear->bgColor != NULL)
208 rmColor4DDelete(r->fbClear->bgColor);
209
210 if (new_color != NULL)
211 {
212 float junk;
213
214 r->fbClear->bgColor = rmColor4DNew(1);
215 C4COPY(r->fbClear->bgColor, new_color);
216
217 if (rmNodeGetSceneDepthValue(r, &junk) == RM_WHACKED)
218 {
219 extern float RM_DEFAULT_DEPTH_VALUE;
220
221 junk = RM_DEFAULT_DEPTH_VALUE;
222 rmNodeSetSceneDepthValue(r, &junk);
223 }
224 }
225 else
226 r->fbClear->bgColor = NULL;
227
228 return(RM_CHILL);
229 }
230
231
232 /*
233 * ----------------------------------------------------
234 * @Name rmNodeGetSceneBackgroundColor
235 @pstart
236 RMenum rmNodeGetSceneBackgroundColor (const RMnode *toQuery,
237 RMcolor4D *returnColor)
238 @pend
239
240 @astart
241 const RMnode *toQuery - a handle to an RMnode (input).
242
243 RMcolor4D *returnColor - a handle to a caller-supplied RMcolor4D
244 object (return).
245 @aend
246
247 @dstart
248
249 Use this routine to obtain the background color scene parameter of an
250 RMnode, if such a scene parameter exists.
251
252 Upon success, RM_CHILL is returned and the scene background color is
253 copied into the caller-supplied RMcolor4D (effectively returning a copy
254 of the background color scene parameter to the caller). If no such scene
255 parameter exists, or if there is some error condition detected, RM_WHACKED
256 is returned, and the caller-supplied colorReturn object remains unmodified.
257
258 @dend
259 * ----------------------------------------------------
260 */
261 RMenum
rmNodeGetSceneBackgroundColor(const RMnode * r,RMcolor4D * color_return)262 rmNodeGetSceneBackgroundColor (const RMnode *r,
263 RMcolor4D *color_return)
264 {
265 if ((RM_ASSERT(r, "rmNodeGetSceneBackgroundColor() error: the input RMnode pointer is NULL.") == RM_WHACKED) ||
266 (RM_ASSERT(color_return, "rmNodeGetSceneBackgroundColor() error: the return RMcolor4D pointer is NULL.") == RM_WHACKED))
267 return(RM_WHACKED);
268
269 if ((r->fbClear == NULL) || (r->fbClear->bgColor == NULL))
270 return(RM_WHACKED);
271
272 /* we are returning the contents of the scene parameter, an RMcolor4D
273 object, to the caller, not the handle to the RMcolor4D object stored
274 in the scene graph itself. */
275
276 *color_return = *(r->fbClear->bgColor);
277
278 return(RM_CHILL);
279 }
280
281
282 /*
283 * ----------------------------------------------------
284 * @Name rmNodeSetSceneBackgroundImage
285 @pstart
286 RMenum rmNodeSetSceneBackgroundImage (RMnode *toModify,
287 const RMimage *newImageTile)
288 @pend
289
290 @astart
291 RMnode *toModify - a handle to an RMnode (modified).
292
293 const RMimage *newImageTile - a handle to an RMimage (input).
294 @aend
295
296 @dstart
297
298 Sets the background image scene parameter for the RMnode. When
299 rendered, this image is tiled into the viewport at the scene depth
300 value (or a default of 1.0) with an orthogonal projection, creating a
301 background image. If the image does not fit the display, it will be
302 tiled from top to bottom and left to right, so ragged edges fall on
303 the bottom and right edges of the viewport.
304
305 Passing in a value of NULL for the newImageTile parameter will
306 effectively remove the background image tile scene parameter, if it
307 exists.
308
309 Upon success, RM_CHILL is returned and the background image scene
310 parameter has been modified. Otherwise, RM_WHACKED is returned.
311
312 Because this routine makes a copy of the input scene parameter (an
313 RMimage object), callers do not need to manage the input object after a
314 successful return from this routine. This has important ramificiations:
315
316 1. Since a copy is made, any changes made to the caller's object will have
317 no effect upon the scene graph, unless this routine is called again to
318 update the scene parameter inside the scene graph;
319
320 2. Callers may safely delete their copy of the input object after a
321 successful return from this routine.
322
323 NOTE: internal to this routine, a call to rmNodeSetSceneDepthValue() is
324 performed, effectively coupling framebuffer clears (by image tiling) with
325 depth buffer clears.
326
327 @dend
328 * ----------------------------------------------------
329 */
330 RMenum
rmNodeSetSceneBackgroundImage(RMnode * n,const RMimage * tile)331 rmNodeSetSceneBackgroundImage (RMnode *n,
332 const RMimage *tile)
333 {
334 if (RM_ASSERT(n, "rmNodeSetSceneBackgroundImage() error: input RMnode is NULL. \n") == RM_WHACKED)
335 return(RM_WHACKED);
336
337 if (n->fbClear == NULL)
338 n->fbClear = private_rmFBClearNew();
339
340 /* if there's an existing background image tile parameter, remove it. */
341 if (n->fbClear->bgImageTile != NULL)
342 rmImageDelete(n->fbClear->bgImageTile);
343
344 /* if the input isn't null, make a copy and assign it as a scene
345 parameter. */
346 if (tile != NULL)
347 {
348 float junk;
349
350 n->fbClear->bgImageTile = rmImageDup(tile);
351
352 /* if there's no background depth value, create one. this
353 policy may change in the future. */
354 if (rmNodeGetSceneDepthValue(n, &junk) == RM_WHACKED)
355 {
356 extern float RM_DEFAULT_DEPTH_VALUE;
357
358 junk = RM_DEFAULT_DEPTH_VALUE;
359 rmNodeSetSceneDepthValue(n, &junk);
360 }
361 }
362 else
363 n->fbClear->bgImageTile = NULL;
364
365 return(RM_CHILL);
366 }
367
368
369 /*
370 * ----------------------------------------------------
371 * @Name rmNodeGetSceneBackgroundImage
372 @pstart
373 RMenum rmNodeGetSceneBackgroundImage (const RMnode *toQuery,
374 RMimage **returnImageTile)
375 @pend
376
377 @astart
378 const RMnode *toQuery - a handle to an RMnode (input).
379
380 RMimage **returnImageTile - a handle to an RMimage handle (return).
381 @aend
382
383 @dstart
384
385 Use this routine to obtain the background image scene parameter of an
386 RMnode. Note that a handle to the RMimage is returned, not a
387 copy of the actual pixel data.
388
389 Upon success, RM_CHILL is returned and a handle to the scene
390 background image is copied into the caller-supplied RMimage handle.
391 Otherwise, RM_WHACKED is returned.
392
393 Unlike most other rmNodeGetScene*() routines, this routine returns a
394 handle to the actual object contained within the scene graph, rather
395 than returning a copy. Applications should exercise appropriate
396 discretion when using this object.
397
398 @dend
399 * ----------------------------------------------------
400 */
401 RMenum
rmNodeGetSceneBackgroundImage(const RMnode * r,RMimage ** tile_return)402 rmNodeGetSceneBackgroundImage (const RMnode *r,
403 RMimage **tile_return)
404 {
405 if ((RM_ASSERT(r, "rmNodeGetSceneBackgroundImage() error: input RMnode is NULL. \n") == RM_WHACKED) ||
406 (RM_ASSERT(r, "rmNodeGetSceneBackgroundImage() error: input pointer to RMimage pointer is NULL. ") == RM_WHACKED))
407 return(RM_WHACKED);
408
409 /* detect the absence of any scene parms, or the absence of the
410 background image tile scene parm. */
411
412 if ((r->fbClear == NULL) || (r->fbClear->bgImageTile == NULL))
413 return(RM_WHACKED);
414
415 *tile_return = r->fbClear->bgImageTile;
416
417 return(RM_CHILL);
418 }
419
420
421 /*
422 * ----------------------------------------------------
423 * @Name rmNodeSetSceneCamera2D
424 @pstart
425 RMenum rmNodeSetSceneCamera2D (RMnode *toModify,
426 const RMcamera2D *newCamera)
427 @pend
428
429 @astart
430 RMnode *toModify - a handle to an RMnode (modified).
431
432 const RMcamera2D *newCamera - a handle to an RMcamera2D object (input).
433 @aend
434
435 @dstart
436
437 Assign a 2D camera as a scene parameter to an RMnode. The 2D camera scene
438 parameter defines a rectangular viewing region, and results in the
439 render-time modification of the OpenGL view and projection matrices.
440
441 Upon success, RM_CHILL is returned; otherwise, RM_WHACKED is
442 returned and the RMnode's scene parameters remain unmodified.
443
444 Passing in a value of NULL for the RMcamera2D object will effectively
445 remove any existing 2D camera scene parameter from the RMnode toModify.
446
447 Because this routine makes a copy of the input scene parameter (an
448 RMcamera2D object), callers do not need to manage the input object after a
449 successful return from this routine. This has important ramificiations:
450
451 1. Since a copy is made, any changes made to the caller's object will have
452 no effect upon the scene graph, unless this routine is called again to
453 update the scene parameter inside the scene graph;
454
455 2. Callers may safely delete their copy of the input object after a
456 successful return from this routine.
457
458 @dend
459 * ----------------------------------------------------
460 */
461 RMenum
rmNodeSetSceneCamera2D(RMnode * n,const RMcamera2D * c)462 rmNodeSetSceneCamera2D (RMnode *n,
463 const RMcamera2D *c)
464 {
465 if (RM_ASSERT(n, "rmNodeSetSceneCamera2D() error: the input RMnode pointer is NULL") == RM_WHACKED)
466 return(RM_WHACKED);
467
468 if (n->scene_parms == NULL)
469 n->scene_parms = private_rmNodeSceneParmsNew();
470
471 if (n->scene_parms->camera2d != NULL)
472 {
473 rmCamera2DDelete(n->scene_parms->camera2d);
474 n->scene_parms->camera2d = NULL;
475 }
476
477 if (c != NULL)
478 {
479 n->scene_parms->camera2d = rmCamera2DNew();
480 *(n->scene_parms->camera2d) = *c;
481 }
482 return(RM_CHILL);
483 }
484
485
486 /*
487 * ----------------------------------------------------
488 * @Name rmNodeGetSceneCamera2D
489 @pstart
490 RMenum rmNodeGetSceneCamera2D (const RMnode *toQuery,
491 RMcamera2D **returnCamera)
492 @pend
493
494 @astart
495 const RMnode *toQuery - a handle to an RMnode (input).
496
497 RMcamera2D **returnCamera - a handle to anRMcamera2D object (return).
498 @aend
499
500 @dstart
501
502 If a 2D camera is defined for the RMnode, then a copy of the 2D
503 camera is returned in the caller-supplied handle, and RM_CHILL is
504 returned. Otherwise, RM_WHACKED is returned, and the caller supplied
505 RMcamera2D object handle remains unmodified.
506
507 Because this routine returns a COPY of the RMnode's scene parameter (an
508 RMcamera2D object), two important ramifications should be noted:
509
510 1. Since a copy is returned, any changes made to the caller's object will have
511 no effect upon the scene graph, unless the appropriate routine is called
512 again to update the scene parameter inside the scene graph;
513
514 2. Callers are responsible for managing the returned object
515 (rmCamera2DDelete the object when it is no longer needed).
516
517
518 @dend
519 * ----------------------------------------------------
520 */
521 RMenum
rmNodeGetSceneCamera2D(const RMnode * n,RMcamera2D ** c)522 rmNodeGetSceneCamera2D (const RMnode *n,
523 RMcamera2D **c)
524 {
525 if ((RM_ASSERT(n, "rmNodeGetSceneCamera2D() error: the input RMnode pointer is NULL") == RM_WHACKED) ||
526 (RM_ASSERT(c, "rmNodeGetSceneCamera2D() error: the input pointer to an RMcamera2D pointer is NULL.") == RM_WHACKED))
527 return(RM_WHACKED);
528
529 if ((n->scene_parms == NULL) || (n->scene_parms->camera2d == NULL))
530 return(RM_WHACKED);
531
532 *c = rmCamera2DNew();
533 *(*c) = *(n->scene_parms->camera2d);
534
535 return(RM_CHILL);
536 }
537
538
539 /*
540 * ----------------------------------------------------
541 * @Name rmNodeSetSceneCamera3D
542 @pstart
543 RMenum rmNodeSetSceneCamera3D (RMnode *toModify,
544 const RMcamera3D *newCamera)
545 @pend
546
547 @astart
548 RMnode *toModify - a handle to an RMnode (modified).
549
550 const RMcamera3D *newCamera - a handle to an RMcamera3D (input).
551 @aend
552
553 @dstart
554
555 Assign a 3D camera as a scene parameter to an RMnode. The 3D camera
556 defines a viewing volume in world coordinats. Objects that lie within
557 this view volume will be visible when rendered. The 3D camera scene
558 parameter will produce a render-time modification of the OpenGL
559 modelview and projection matrices. The effect of these matrix stack
560 modifications have scope only over the subtree rooted at the RMnode
561 toModify.
562
563 Passing in a value of NULL for the input RMcamera3D object will effectively
564 remove any existing RMcamera3D scene parameter from the RMnode.
565
566 Upon success, a copy of the input RMcamera3D object is made (if not NULL),
567 and assigned as a scene parameter to the input RMnode; Otherwise, RM_WHACKED
568 is returned.
569
570 Because this routine makes a copy of the input scene parameter (an
571 RMcamera3D object), callers do not need to manage the input object after a
572 successful return from this routine. This has important ramificiations:
573
574 1. Since a copy is made, any changes made to the caller's object will have
575 no effect upon the scene graph, unless this routine is called again to
576 update the scene parameter inside the scene graph;
577
578 2. Callers may safely delete their copy of the input object after a
579 successful return from this routine.
580
581 @dend
582 * ----------------------------------------------------
583 */
584 RMenum
rmNodeSetSceneCamera3D(RMnode * n,const RMcamera3D * c)585 rmNodeSetSceneCamera3D (RMnode *n,
586 const RMcamera3D *c)
587 {
588 if (RM_ASSERT(n, "rmNodeSetSceneCamera3D() error: the input RMnode pointer is NULL") == RM_WHACKED)
589 return(RM_WHACKED);
590
591 if (n->scene_parms == NULL)
592 n->scene_parms = private_rmNodeSceneParmsNew();
593
594 if (n->scene_parms->camera3d != NULL)
595 {
596 rmCamera3DDelete(n->scene_parms->camera3d);
597 n->scene_parms->camera3d = NULL;
598 }
599
600 if (c != NULL)
601 {
602 n->scene_parms->camera3d = rmCamera3DNew();
603 *(n->scene_parms->camera3d) = *c;
604 }
605 return(RM_CHILL);
606 }
607
608
609 /*
610 * ----------------------------------------------------
611 * @Name rmNodeGetSceneCamera3D
612 @pstart
613 RMenum rmNodeGetSceneCamera3D (const RMnode *toQuery,
614 RMcamera3D **returnCamera)
615 @pend
616
617 @astart
618 const RMnode *toQuery - a handle to an RMnode (input).
619
620 RMcamera3D **returnCamera - a handle to a caller-supplied RMcamera3D object
621 (modified).
622 @aend
623
624 @dstart
625
626 If a 3D camera is defined for the RMnode, then a copy of the 3D
627 camera is created, then returned in the caller-supplied handle, and
628 RM_CHILL is returned. Otherwise, RM_WHACKED is returned and the
629 caller-supplied RMcamera3D handle remains unmodified.
630
631 Because this routine returns a COPY of the RMnode's scene parameter (an
632 RMcamera3D object), two important ramifications should be noted:
633
634 1. Since a copy is returned, any changes made to the caller's object will have
635 no effect upon the scene graph, unless the appropriate routine is called
636 again to update the scene parameter inside the scene graph;
637
638 2. Callers are responsible for managing the returned object
639 (rmCamera3DDelete the object when it is no longer needed).
640
641 @dend
642 * ----------------------------------------------------
643 */
644 RMenum
rmNodeGetSceneCamera3D(const RMnode * n,RMcamera3D ** c)645 rmNodeGetSceneCamera3D (const RMnode *n,
646 RMcamera3D **c)
647 {
648 if ((RM_ASSERT(n, "rmNodeGetSceneCamera3D() error: the input RMnode pointer is NULL") == RM_WHACKED) ||
649 (RM_ASSERT(c, "rmNodeGetSceneCamera3D() error: the input pointer to an RMcamera3D pointer is NULL.") == RM_WHACKED))
650 return(RM_WHACKED);
651
652 if ((n->scene_parms == NULL) || (n->scene_parms->camera3d == NULL))
653 return(RM_WHACKED);
654
655 *c = rmCamera3DNew();
656 *(*c) = *(n->scene_parms->camera3d);
657
658 return(RM_CHILL);
659 }
660
661
662 /*
663 * ----------------------------------------------------
664 * @Name rmNodeSetSceneClipPlane
665 @pstart
666 RMenum rmNodeSetSceneClipPlane (RMnode *toModify,
667 RMenum clipPlaneEnum,
668 const RMclipPlane *newClipPlane)
669 @pend
670
671 @astart
672 RMnode *toModify - a handle to an RMnode (input).
673
674 RMenum clipPlaneEnum - an RMenum specifying which clipping plane
675 to modify. Must be one of [RM_SCENE_CLIP_PLANE0..5] (input).
676
677 const RMclipPlane *newClipPlane - a handle to an RMclipPlane handle (input).
678 @aend
679
680 @dstart
681
682 Assigns a clip plane as a scene parameter to an RMnode. This routine will
683 make a copy of the input RMclipPlane object, and assign the copy as a
684 scene parameter to the input RMnode. See rmClipPlaneNew() for more
685 details about how clip planes are specified.
686
687 Passing in a value of NULL for the newClipPlane parameter will
688 effectively remove the clip plane scene parameter specified by
689 clipPlaneEnum, if it exists.
690
691 Upon success, RM_CHILL is returned; otherwise, RM_WHACKED is
692 returned.
693
694 Because this routine makes a copy of the input scene parameter (an
695 RMclipPlane), callers do not need to manage the input object after a
696 successful return from this routine. This has important ramificiations:
697
698 1. Since a copy is made, any changes made to the caller's object will have
699 no effect upon the scene graph, unless this routine is called again to
700 update the scene parameter inside the scene graph;
701
702 2. Callers may safely delete their copy of the input object after a
703 successful return from this routine.
704
705 @dend
706 * ----------------------------------------------------
707 */
708 RMenum
rmNodeSetSceneClipPlane(RMnode * n,RMenum which_clip_plane,const RMclipPlane * ncp)709 rmNodeSetSceneClipPlane (RMnode *n,
710 RMenum which_clip_plane,
711 const RMclipPlane *ncp)
712 {
713 RMclipPlane **target = NULL, *t;
714
715 if (RM_ASSERT(n, "rmNodeSetSceneClipPlane() error: the input RMnode pointer is NULL") == RM_WHACKED)
716 return(RM_WHACKED);
717
718 if (n->scene_parms == NULL)
719 n->scene_parms = private_rmNodeSceneParmsNew();
720
721 switch (which_clip_plane)
722 {
723 case RM_SCENE_CLIP_PLANE0:
724 target = &(n->scene_parms->cp0);
725 break;
726
727 case RM_SCENE_CLIP_PLANE1:
728 target = &(n->scene_parms->cp1);
729 break;
730
731 case RM_SCENE_CLIP_PLANE2:
732 target = &(n->scene_parms->cp2);
733 break;
734
735 case RM_SCENE_CLIP_PLANE3:
736 target = &(n->scene_parms->cp3);
737 break;
738
739 case RM_SCENE_CLIP_PLANE4:
740 target = &(n->scene_parms->cp4);
741 break;
742
743 case RM_SCENE_CLIP_PLANE5:
744 target = &(n->scene_parms->cp5);
745 break;
746
747 default:
748 rmWarning("rmNodeSetSceneClipPlane error: bad clip plane enumerator specified by calling routine. ");
749 return(RM_WHACKED);
750 }
751
752 /* this conditional should never evaluate to TRUE. */
753 if (RM_ASSERT(target,"rmNodeSetSceneClipPlane() error: input enumerator specifying a clip plane is invalid.") == RM_WHACKED)
754 return(RM_WHACKED);
755
756 t = *target;
757
758 if (t != NULL)
759 {
760 rmClipPlaneDelete(t);
761 *target = NULL;
762 }
763
764 if (ncp != NULL)
765 {
766 t = *target = rmClipPlaneNew();
767 memcpy((void *)t, (void *)ncp, sizeof(RMclipPlane));
768 }
769
770 private_rmNodeAttribMask(n,private_rmNodeComputeAttribMask(n),RM_SET);
771
772 return(RM_CHILL);
773 }
774
775
776 /*
777 * ----------------------------------------------------
778 * @Name rmNodeGetSceneClipPlane
779 @pstart
780 RMenum rmNodeGetSceneClipPlane (const RMnode *toQuery,
781 RMenum clipPlaneEnum,
782 RMclipPlane **returnClipPlane)
783 @pend
784
785 @astart
786 const RMnode *toQuery - a handle to an RMnode (input).
787
788 RMenum clipPlaneEnum - an RMenum indicating which clip plane is
789 being modified. Must be one of RM_SCENE_CLIP_PLANE[0-5] (input).
790
791 RMclipPlane **returnClipPlane - a caller-supplied handle to an RMclipPlane
792 handle (return).
793 @aend
794
795 @dstart
796
797 Use this routine to obtain one of six possible clip planes from an
798 RMnode's scene parameters.
799
800 Upon success, a copy of the requested clip plane is created and returned to
801 the caller via the returnClipPlane handle, and RM_CHILL is returned.
802 Otherwise, RM_WHACKED is returned, and the caller supplied RMclipPlane
803 handle remains unmodified.
804
805 Because this routine returns a COPY of the RMnode's scene parameter (an
806 RMclipPlane object), two important ramifications should be noted:
807
808 1. Since a copy is returned, any changes made to the caller's object will have
809 no effect upon the scene graph, unless the appropriate routine is called
810 again to update the scene parameter inside the scene graph;
811
812 2. Callers are responsible for managing the returned object
813 (rmClipPlaneDelete the object when it is no longer needed).
814
815 @dend
816 * ----------------------------------------------------
817 */
818 RMenum
rmNodeGetSceneClipPlane(const RMnode * n,RMenum which_clip_plane,RMclipPlane ** rcp)819 rmNodeGetSceneClipPlane (const RMnode *n,
820 RMenum which_clip_plane,
821 RMclipPlane **rcp)
822 {
823 RMclipPlane **target=NULL, *t;
824
825 if ((RM_ASSERT(n, "rmNodeGetSceneClipPlane() error: the input RMnode pointer is NULL") == RM_WHACKED) ||
826 (RM_ASSERT(rcp, "rmNodeGetSceneClipPlane() error: the input pointer to an RMclipPlane pointer is NULL. ") == RM_WHACKED))
827 return(RM_WHACKED);
828
829 if (n->scene_parms == NULL)
830 return(RM_WHACKED);
831
832 switch (which_clip_plane)
833 {
834 case RM_SCENE_CLIP_PLANE0:
835 target = &(n->scene_parms->cp0);
836 break;
837
838 case RM_SCENE_CLIP_PLANE1:
839 target = &(n->scene_parms->cp1);
840 break;
841
842 case RM_SCENE_CLIP_PLANE2:
843 target = &(n->scene_parms->cp2);
844 break;
845
846 case RM_SCENE_CLIP_PLANE3:
847 target = &(n->scene_parms->cp3);
848 break;
849
850 case RM_SCENE_CLIP_PLANE4:
851 target = &(n->scene_parms->cp4);
852 break;
853
854 case RM_SCENE_CLIP_PLANE5:
855 target = &(n->scene_parms->cp5);
856 break;
857
858 default: /* bogus clip plane enum */
859 rmWarning("rmNodeGetSceneClipPlane() error: bad clip plane enumerator specified by calling routine.");
860 return(RM_WHACKED);
861 }
862
863 /* this conditional should NEVER evaluate to true. */
864 if (RM_ASSERT(target,"rmNodeGetSceneClipPlane() error: input enumerator specifying a clipping plane is invalid.") == RM_WHACKED)
865 return(RM_WHACKED);
866
867 t = rmClipPlaneNew();
868 memcpy((void *)t, (void *)(*target), sizeof(RMclipPlane));
869 *rcp = t; /* the app is now responsible for this memory */
870
871 return(RM_CHILL);
872 }
873
874
875 /*
876 * ----------------------------------------------------
877 * @Name rmNodeSetSceneDepthImage
878 @pstart
879 RMenum rmNodeSetSceneDepthImage (RMnode *toModify,
880 const RMimage *newDepthImage)
881 @pend
882
883 @astart
884 RMnode *toModify - a handle to an RMnode (modified).
885
886 const RMimage *newDepthImage - a handle to a depth image (input)
887 @aend
888
889 @dstart
890
891 Assigns a depth image as a scene parameter for the RMnode. The
892 depth image is similar to the background image tile, but is applied to the
893 depth buffer, rather than the color planes of the framebuffer. Like the
894 background image tile, the depth image scene parameter is tiled to fill
895 the framebuffer, starting from the upper left-hand corner of the viewport.
896 If the size of the depth buffer image and viewport do not match exactly,
897 the "ragged edges" or on the right and the bottom of the viewport.
898
899 Passing in a value of NULL for the RMimage object will have the effect
900 of removing the background depth image scene parameter, if one exists,
901 from the RMnode.
902
903 Upon success, a copy of the caller's RMimage object is made, and the
904 copy is assigned as a scene parameter (or, if the input RMimage object is
905 NULL, the NULL is assigned as a depth image scene parameter, effectively
906 turning off that scene parameter), and RM_CHILL is returned;
907 otherwise, RM_WHACKED is returned.
908
909 Because this routine makes a copy of the input scene parameter (an
910 RMimage), callers do not need to manage the input object after a
911 successful return from this routine. This has important ramificiations:
912
913 1. Since a copy is made, any changes made to the caller's object will have
914 no effect upon the scene graph, unless this routine is called again to
915 update the scene parameter inside the scene graph;
916
917 2. Callers may safely delete their copy of the input object after a
918 successful return from this routine.
919
920 Note: as a practical matter, it is suggested that the pixel format
921 of input RMimage objects should be of type RM_FLOAT, and in the
922 range 0..1. By default, depth buffer Pixels in OpenGL range from
923 0..1 (or perhaps 0..0.9999, depending upon your interpretation), but
924 this range may be manipulated with glPixelTransferf(). As of the time
925 of this writing (May 2000), we have tested background depth images
926 only with RMimage's consisting of RM_FLOAT pixels in the range 0..1
927 (and they work - refer to the demonstration program "pdb" included with
928 the openrm-demo distribution).
929
930 @dend
931 * ----------------------------------------------------
932 */
933 RMenum
934
rmNodeSetSceneDepthImage(RMnode * n,const RMimage * new_depth_image)935 rmNodeSetSceneDepthImage (RMnode *n,
936 const RMimage *new_depth_image)
937 {
938 if (RM_ASSERT(n, "rmNodeSetSceneDepthImage() error: the input RMnode pointer is NULL.") == RM_WHACKED)
939 return(RM_WHACKED);
940
941 if (n->fbClear == NULL)
942 n->fbClear = private_rmFBClearNew();
943
944 if (n->fbClear->depthImage != NULL)
945 {
946 rmImageDelete(n->fbClear->depthImage);
947 n->fbClear->depthImage = NULL;
948 }
949
950 if (new_depth_image != NULL)
951 n->fbClear->depthImage = rmImageDup(new_depth_image);
952
953 return(RM_CHILL);
954 }
955
956
957 /*
958 * ----------------------------------------------------
959 * @Name rmNodeGetSceneDepthImage
960 @pstart
961 RMenum rmNodeGetSceneDepthImage (const RMnode *toQuery,
962 RMimage **returnDepthImage)
963 @pend
964
965 @astart
966 const RMnode *toQuery - a handle to an RMnode (input).
967
968 RMimage **returnDepthImage - a handle to a depth image handle
969 (return).
970 @aend
971
972 @dstart
973
974 Use this routine to obtain the RMnode's depth image scene parameter. If
975 such a scene parameter exists, the handle of the RMimage (depth image)
976 scene parameter is copied into caller-supplied memory, and RM_CHILL is
977 returned. Otherwise, in the event of an error or the absence of the
978 depth image scene parameter, RM_WHACKED is returned and caller supplied
979 memory remains unmodified.
980
981 Unlike most other rmNodeGetScene*() routines, this routine returns a
982 handle to the actual RMimage object contained within the scene graph, rather
983 than returning a copy. Applications should exercise appropriate
984 discretion when using this object.
985
986 @dend
987 * ----------------------------------------------------
988 */
989 RMenum
rmNodeGetSceneDepthImage(const RMnode * n,RMimage ** depth_image_return)990 rmNodeGetSceneDepthImage (const RMnode *n,
991 RMimage **depth_image_return)
992 {
993 if ((RM_ASSERT(n, "rmNodeGetSceneDepthImage() error: input RMnode is NULL. \n") == RM_WHACKED) ||
994 (RM_ASSERT(depth_image_return, "rmNodeGetSceneDepthImage() error: input pointer to RMimage pointer is NULL. ") == RM_WHACKED))
995 return(RM_WHACKED);
996
997 if ((n->fbClear == NULL) || (n->fbClear->depthImage == NULL))
998 return(RM_WHACKED);
999
1000 *depth_image_return = n->fbClear->depthImage;
1001
1002 return(RM_CHILL);
1003 }
1004
1005
1006 /*
1007 * ----------------------------------------------------
1008 * @Name rmNodeSetSceneDepthValue
1009 @pstart
1010 RMenum rmNodeSetSceneDepthValue (RMnode *toModify,
1011 const float *newDepthValue)
1012 @pend
1013
1014 @astart
1015 RMnode *toModify - a handle to an RMnode (modified).
1016
1017 const float *newDepthValue - a handle to the new depth value for the
1018 node (input).
1019 @aend
1020
1021 @dstart
1022
1023 Use this routine to set the scene depth value parameter for an
1024 RMnode. The presence of the scene depth value has the effect of
1025 clearing the depth buffer to the value of newDepthValue.
1026
1027 Passing in a value of NULL for newDepthValue has the effect of disabling
1028 depth buffer clears.
1029
1030 The input newDepthValue should have the magnitude specified by
1031 glPixelTransferf(GL_DEPTH_SCALE,X) and range specified by
1032 glPixelTransferf(GL_DEPTH_BIAS,X). In OpenGL, the default depth
1033 bias is 0.0 and range/scale is 1.0.
1034
1035 Upon success, RM_CHILL is returned and the node's depth value is set.
1036 Otherwise, RM_WHACKED is returned.
1037
1038 @dend
1039 * ----------------------------------------------------
1040 */
1041 RMenum
rmNodeSetSceneDepthValue(RMnode * n,const float * newDepthValue)1042 rmNodeSetSceneDepthValue (RMnode *n,
1043 const float *newDepthValue)
1044 {
1045 if (RM_ASSERT(n, "rmNodeSetSceneDepthValue() error: the input RMnode pointer is NULL") == RM_WHACKED)
1046 return(RM_WHACKED);
1047
1048 if (n->fbClear == NULL)
1049 n->fbClear = private_rmFBClearNew();
1050
1051 if (n->fbClear->depthValue != NULL)
1052 {
1053 free((void *)(n->fbClear->depthValue));
1054 n->fbClear->depthValue = NULL;
1055 }
1056 if (newDepthValue != NULL)
1057 {
1058 n->fbClear->depthValue = rmFloatNew(1);
1059 *(n->fbClear->depthValue) = *newDepthValue;
1060 }
1061
1062 private_rmNodeAttribMask(n,private_rmNodeComputeAttribMask(n),RM_SET);
1063 return(RM_CHILL);
1064 }
1065
1066
1067 /*
1068 * ----------------------------------------------------
1069 * @Name rmNodeGetSceneDepthValue
1070 @pstart
1071 RMenum rmNodeGetSceneDepthValue (const RMnode *toQuery,
1072 float *returnDepthValue)
1073 @pend
1074
1075 @astart
1076 const RMnode *toQuery - a handle to an RMnode (input).
1077
1078 float *returnDepthValue - a handle to a caller-supplied float for the
1079 queried depth value (return).
1080 @aend
1081
1082 @dstart
1083
1084 Use this routine to query the scene depth value for a given RMnode.
1085
1086 Upon success, RM_CHILL is returned and the node's depth value is
1087 copied into the caller-supplied float. If the specified pointers are
1088 NULL, or no valid scene depth parameter exists, RM_WHACKED is
1089 returned.
1090
1091 @dend
1092 * ----------------------------------------------------
1093 */
1094 RMenum
rmNodeGetSceneDepthValue(const RMnode * n,float * dr)1095 rmNodeGetSceneDepthValue (const RMnode *n,
1096 float *dr)
1097 {
1098 if ((RM_ASSERT(n, "rmNodeGetSceneDepthValue() error: the input RMnode pointer is NULL") == RM_WHACKED) ||
1099 (RM_ASSERT(dr, "rmNodeGetSceneDepthValue() error: the return float pointer is NULL.") == RM_WHACKED))
1100 return(RM_WHACKED);
1101
1102 if ((n->fbClear == NULL) || (n->fbClear->depthValue == NULL))
1103 return(RM_WHACKED);
1104
1105 *dr = *(n->fbClear->depthValue);
1106
1107 return(RM_CHILL);
1108 }
1109
1110
1111 /*
1112 * ----------------------------------------------------
1113 * @Name rmNodeSetSceneFog
1114 @pstart
1115 RMenum rmNodeSetSceneFog (RMnode *toModify,
1116 const RMfog *newFog)
1117 @pend
1118
1119 @astart
1120 RMnode *toModify - a handle to an RMnode (modified).
1121
1122 const RMfog *newFog - a handle to the new fog scene parameters
1123 (input).
1124 @aend
1125
1126 @dstart
1127
1128 Use this routine to set the fog scene parameters for an RMnode. If
1129 no scene parameters have been defined, then the RMfog object is
1130 duplicated into the RMnode. Existing fog parameters are first deleted,
1131 thenn replaced with the new fog parameters. Calling this routine with a
1132 an argument of NULL for the RMfog object disables the fog scene parameters.
1133
1134 When a non-NULL RMfog object is added as a scene parameter to an
1135 RMnode, fogging will become enabled. The fogging will have scope only
1136 over the subtree rooted at the RMnode toModify. When the RMfog object
1137 is NULL, fogging is disabled (unless fogging is enabled at an
1138 anscestor node in the scene graph).
1139
1140 Upon success, RM_CHILL is returned and the node's fog parameters are
1141 set. Otherwise, RM_WHACKED is returned.
1142
1143 Because this routine makes a copy of the input scene parameter (an
1144 RMfog object), callers do not need to manage the input object after a
1145 successful return from this routine. This has important ramificiations:
1146
1147 1. Since a copy is made, any changes made to the caller's object will have
1148 no effect upon the scene graph, unless this routine is called again to
1149 update the scene parameter inside the scene graph;
1150
1151 2. Callers may safely delete their copy of the input object after a
1152 successful return from this routine.
1153
1154 @dend
1155 * ----------------------------------------------------
1156 */
1157 RMenum
rmNodeSetSceneFog(RMnode * n,const RMfog * newFog)1158 rmNodeSetSceneFog (RMnode *n,
1159 const RMfog *newFog)
1160 {
1161 if (RM_ASSERT(n, "rmNodeSetSceneFog() error: the input RMnode pointer is NULL.") == RM_WHACKED)
1162 return(RM_WHACKED);
1163
1164 if (n->scene_parms == NULL)
1165 n->scene_parms = private_rmNodeSceneParmsNew();
1166
1167 if (n->scene_parms->fog != NULL)
1168 {
1169 rmFogDelete(n->scene_parms->fog);
1170 n->scene_parms->fog = NULL;
1171 }
1172
1173 if (newFog != NULL)
1174 n->scene_parms->fog = rmFogDup(newFog);
1175
1176 private_rmNodeAttribMask(n,private_rmNodeComputeAttribMask(n),RM_SET);
1177 return(RM_CHILL);
1178 }
1179
1180 /*
1181 * ----------------------------------------------------
1182 * @Name rmNodeGetSceneFog
1183 @pstart
1184 RMenum rmNodeGetSceneFog (const RMnode *toQuery,
1185 RMfog **returnFog)
1186 @pend
1187
1188 @astart
1189 const RMnode *toQuery - a handle to an RMnode (input).
1190
1191 RMfog **returnFog - a pointer to an RMfog handle (return).
1192 @aend
1193
1194 @dstart
1195
1196 Use this routine to query the fog scene parameters for an RMnode. If
1197 no fog scene parameters exists for the RMnode, then RM_WHACKED
1198 is returned and no changes will be made to the input returnFog
1199 parameter.
1200
1201 Upon success, RM_CHILL is returned and a handle to the node's fog
1202 scene parameters are copied into the caller-supplied handle.
1203
1204 Unlike most other rmNodeGetScene*() routines, this routine returns a
1205 handle to the actual RMfog object contained within the scene graph, rather
1206 than returning a copy. Applications should exercise appropriate
1207 discretion when using this object.
1208 @dend
1209 * ----------------------------------------------------
1210 */
1211 RMenum
rmNodeGetSceneFog(const RMnode * n,RMfog ** returnFog)1212 rmNodeGetSceneFog (const RMnode *n,
1213 RMfog **returnFog)
1214 {
1215 if ((RM_ASSERT(n, "rmNodeGetSceneFog() error: the input RMnode pointer is NULL") == RM_WHACKED) ||
1216 (RM_ASSERT(returnFog, "rmNodeGetSceneFog() error: the returnFog pointer is NULL.") == RM_WHACKED))
1217 return(RM_WHACKED);
1218
1219 if (n->scene_parms == NULL || n->scene_parms->fog == NULL)
1220 return RM_WHACKED;
1221
1222 *returnFog = n->scene_parms->fog;
1223
1224 return(RM_CHILL);
1225 }
1226
1227
1228 /*
1229 * ----------------------------------------------------
1230 * @Name rmNodeSetSceneLight
1231 @pstart
1232 RMenum rmNodeSetSceneLight (RMnode *toModify,
1233 RMenum whichLightEnum,
1234 const RMlight *newLight)
1235 @pend
1236
1237 @astart
1238 RMnode *toModify - a handle to an RMnode (modified).
1239
1240 RMenum whichLightEnum - an RMenum specifying which light tp modify.
1241 Must be one of [RM_LIGHT0..7] (input).
1242
1243 const RMlight *newLight - a handle to an RMlight handle (input).
1244 @aend
1245
1246 @dstart
1247
1248 Use this routine to assign a light source as a scene parameter to
1249 an RMnode. The light source is specified with an RMlight object
1250 (see rmLightNew for more information). Up to eight light sources
1251 may be simultaneously active, or specified at an RMnode by the
1252 RMenum values RM_LIGHT0, RM_LIGHT1, ... , RM_LIGHT7.
1253
1254 When a non-NULL light source is assigned as a scene parameter, that
1255 light source becomes active, and has scope over the subtree rooted
1256 at the RMnode toModify within the scene graph. Assinging a NULL
1257 light source to one of the eight potential light source scene
1258 parameters will deactivate that particular light source.
1259
1260 Upon success, RM_CHILL is returned; otherwise, RM_WHACKED is
1261 returned.
1262
1263 Because this routine makes a copy of the input scene parameter (an
1264 RMlight object), callers do not need to manage the input object after a
1265 successful return from this routine. This has important ramificiations:
1266
1267 1. Since a copy is made, any changes made to the caller's object will have
1268 no effect upon the scene graph, unless this routine is called again to
1269 update the scene parameter inside the scene graph;
1270
1271 2. Callers may safely delete their copy of the input object after a
1272 successful return from this routine.
1273
1274 @dend
1275 * ----------------------------------------------------
1276 */
1277 RMenum
rmNodeSetSceneLight(RMnode * n,RMenum which_light,const RMlight * l)1278 rmNodeSetSceneLight (RMnode *n,
1279 RMenum which_light,
1280 const RMlight *l)
1281 {
1282 RMlight **target=NULL, *t;
1283
1284 if (RM_ASSERT(n, "rmNodeSetSceneLight() error: the input RMnode pointer is NULL") == RM_WHACKED)
1285 return(RM_WHACKED);
1286
1287 if (n->scene_parms == NULL)
1288 n->scene_parms = private_rmNodeSceneParmsNew();
1289
1290 switch (which_light)
1291 {
1292 case RM_LIGHT0:
1293 target = &(n->scene_parms->lightSources[0]);
1294 break;
1295
1296 case RM_LIGHT1:
1297 target = &(n->scene_parms->lightSources[1]);
1298 break;
1299
1300 case RM_LIGHT2:
1301 target = &(n->scene_parms->lightSources[2]);
1302 break;
1303
1304 case RM_LIGHT3:
1305 target = &(n->scene_parms->lightSources[3]);
1306 break;
1307
1308 case RM_LIGHT4:
1309 target = &(n->scene_parms->lightSources[4]);
1310 break;
1311
1312 case RM_LIGHT5:
1313 target = &(n->scene_parms->lightSources[5]);
1314 break;
1315
1316 case RM_LIGHT6:
1317 target = &(n->scene_parms->lightSources[6]);
1318 break;
1319
1320 case RM_LIGHT7:
1321 target = &(n->scene_parms->lightSources[7]);
1322 break;
1323
1324 default: /* bogus light enum */
1325 rmWarning("rmNodeSetSceneLight() error: bad light enumerator specified by calling routine.");
1326 return(RM_WHACKED);
1327 }
1328
1329 if (RM_ASSERT(target, "rmNodeSetSceneLight() error: input enumerator specifying a light is invalid.") == RM_WHACKED)
1330 return(RM_WHACKED);
1331
1332 t = *target;
1333
1334 if (t != NULL)
1335 {
1336 rmLightDelete(t);
1337 *target = NULL;
1338 }
1339
1340 if (l != NULL)
1341 {
1342 t = *target = rmLightNew();
1343 memcpy((void *)t, (void *)l, sizeof(RMlight));
1344 }
1345
1346 private_rmNodeAttribMask(n,private_rmNodeComputeAttribMask(n),RM_SET);
1347 return(RM_CHILL);
1348 }
1349
1350 /*
1351 * ----------------------------------------------------
1352 * @Name rmNodeGetSceneLight
1353 @pstart
1354 RMenum rmNodeGetSceneLight (const RMnode *toQuery,
1355 RMenum whichLightEnum,
1356 RMlight **returnLightCopy)
1357 @pend
1358
1359 @astart
1360 const RMnode *toQuery - a handle to an RMnode (input).
1361
1362 RMenum whichLightEnum - an RMenum indicating which RMlight to query.
1363 Must be one of RM_LIGHT0, RM_LIGHT1, ... , RM_LIGHT7 (input).
1364
1365 RMlight **returnLightCopy - a caller-supplied handle to an RMlight handle
1366 (return).
1367 @aend
1368
1369 @dstart
1370
1371 Use this routine to obtain one of eight possible lights defined as
1372 scene parameters for an RMnode. If no such scene parameter is
1373 defined, RM_WHACKED is returned, and the caller-supplied pointer to
1374 an RMlight pointer remains unmodified.
1375
1376 Upon success, RM_CHILL is returned, and a copy of the specified
1377 RMlight object is created, and the handle to the new copy is
1378 returned via the caller-supplied handle. Applications
1379
1380 Because this routine returns a COPY of the RMnode's scene parameter (an
1381 RMlight object), two important ramifications should be noted:
1382
1383 1. Since a copy is returned, any changes made to the caller's object will have
1384 no effect upon the scene graph, unless the appropriate routine is called
1385 again to update the scene parameter inside the scene graph;
1386
1387 2. Callers are responsible for managing the returned object
1388 (rmLightDelete the object when it is no longer needed).
1389
1390 @dend
1391 * ----------------------------------------------------
1392 */
1393 RMenum
rmNodeGetSceneLight(const RMnode * n,RMenum which_light,RMlight ** l)1394 rmNodeGetSceneLight (const RMnode *n,
1395 RMenum which_light,
1396 RMlight **l)
1397 {
1398 RMlight **target=NULL,*t;
1399
1400 if ((RM_ASSERT(n, "rmNodeGetSceneLight() error: the input RMnode pointer is NULL") == RM_WHACKED) ||
1401 (RM_ASSERT(l, "rmNodeGetSceneLight() error: the input pointer to an RMlight pointer is NULL. ") == RM_WHACKED))
1402 return(RM_WHACKED);
1403
1404 if (n->scene_parms == NULL)
1405 return(RM_WHACKED);
1406
1407 switch (which_light)
1408 {
1409 case RM_LIGHT0:
1410 target = &(n->scene_parms->lightSources[0]);
1411 break;
1412
1413 case RM_LIGHT1:
1414 target = &(n->scene_parms->lightSources[1]);
1415 break;
1416
1417 case RM_LIGHT2:
1418 target = &(n->scene_parms->lightSources[2]);
1419 break;
1420
1421 case RM_LIGHT3:
1422 target = &(n->scene_parms->lightSources[3]);
1423 break;
1424
1425 case RM_LIGHT4:
1426 target = &(n->scene_parms->lightSources[4]);
1427 break;
1428
1429 case RM_LIGHT5:
1430 target = &(n->scene_parms->lightSources[5]);
1431 break;
1432
1433 case RM_LIGHT6:
1434 target = &(n->scene_parms->lightSources[6]);
1435 break;
1436
1437 case RM_LIGHT7:
1438 target = &(n->scene_parms->lightSources[7]);
1439 break;
1440
1441 default: /* bogus light enum */
1442 rmWarning("rmNodeGetSceneLight() error: bad light enumerator specified by calling routine.");
1443 return(RM_WHACKED);
1444 }
1445
1446 if (RM_ASSERT(*target, "rmNodeGetSceneLight() error: the input node has no light source associated with the input RM_LIGHT* enumerator.") == RM_WHACKED)
1447 return(RM_WHACKED);
1448
1449 t = rmLightNew();
1450 memcpy((void *)t, (void *)(*target), sizeof(RMlight));
1451 *l = t; /* the app will now be responsible for this memory */
1452
1453 return(RM_CHILL);
1454 }
1455
1456
1457 /*
1458 * ----------------------------------------------------
1459 * @Name rmNodeSetSceneLightModel
1460 @pstart
1461 RMenum rmNodeSetSceneLightModel (RMnode *toModify,
1462 const RMlightModel *newLightModel)
1463 @pend
1464
1465 @astart
1466 RMnode *toModify - a handle to an RMnode (modified).
1467
1468 const RMlightModel *newLightModel - a handle to an RMlightModel (input).
1469 @aend
1470
1471 @dstart
1472
1473 Set the light model used by an RMnode. The RMlightmodel controls the
1474 ambient light color, whether two-sided lighting is enabled, and
1475 whether the local viewer is enabled for specular calculations. If no
1476 light model has been defined, then the RMlightModel object is
1477 duplicated into the RMnode. An existing light model is deleted and
1478 overwritten with the new light model.
1479
1480 Calling this routine with an RMlightModel argument of NULL has the
1481 effect of removing any existing light model specification from the
1482 input RMnode. A light model that is specified at an ancestor
1483 node in the scene graph, if any, will be used to control light
1484 model parameters.
1485
1486 See rmLightModelNew for details of the RMlightModel parameters.
1487
1488 Upon success, RM_CHILL is returned and the RMnode contains the new
1489 light model. Otherwise, RM_WHACKED is returned.
1490
1491 Because this routine makes a copy of the input scene parameter (an
1492 RMlightModel object), callers do not need to manage the input object after a
1493 successful return from this routine. This has important ramificiations:
1494
1495 1. Since a copy is made, any changes made to the caller's object will have
1496 no effect upon the scene graph, unless this routine is called again to
1497 update the scene parameter inside the scene graph;
1498
1499 2. Callers may safely delete their copy of the input object after a
1500 successful return from this routine.
1501
1502 @dend
1503 * ----------------------------------------------------
1504 */
1505 RMenum
rmNodeSetSceneLightModel(RMnode * n,const RMlightModel * lm)1506 rmNodeSetSceneLightModel (RMnode *n,
1507 const RMlightModel *lm)
1508 {
1509 if (RM_ASSERT(n, "rmNodeSetSceneLightModel() error: the input RMnode pointer is NULL") == RM_WHACKED)
1510 return(RM_WHACKED);
1511
1512 if (n->scene_parms == NULL)
1513 n->scene_parms = private_rmNodeSceneParmsNew();
1514
1515 if (n->scene_parms->lmodel != NULL)
1516 {
1517 rmLightModelDelete(n->scene_parms->lmodel);
1518 n->scene_parms->lmodel = NULL;
1519 }
1520
1521 if (lm != NULL)
1522 {
1523 n->scene_parms->lmodel = rmLightModelNew();
1524 memcpy((void *)(n->scene_parms->lmodel), (void *)lm, sizeof(RMlightModel));
1525 }
1526
1527 private_rmNodeAttribMask(n,private_rmNodeComputeAttribMask(n),RM_SET);
1528 return(RM_CHILL);
1529 }
1530
1531
1532 /*
1533 * ----------------------------------------------------
1534 * @Name rmNodeGetSceneLightModel
1535 @pstart
1536 RMenum rmNodeGetSceneLightModel (const RMnode *toQuery,
1537 RMlightModel **lightModelReturn)
1538 @pend
1539
1540 @astart
1541 const RMnode *toQuery - a handle to an RMnode (input).
1542
1543 RMlightModel **returnLightModel - a caller-supplied handle to an RMlightModel
1544 handle (return).
1545 @aend
1546
1547 @dstart
1548
1549 Obtains a copy of the light model scene parameter for an RMnode. If no
1550 such scene parameter exists, RM_WHACKED is returned, and the pointer to the
1551 caller-supplied RMlightModel pointer remains unmodified.
1552
1553 Otherwise, a copy of the RMnode's RMlightModel parameter is created,
1554 the pointer to this new object is copied into caller-supplied memory,
1555 and RM_CHILL is returned.
1556
1557 Because this routine returns a COPY of the RMnode's scene parameter (an
1558 RMlightModel object), two important ramifications should be noted:
1559
1560 1. Since a copy is returned, any changes made to the caller's object will have
1561 no effect upon the scene graph, unless the appropriate routine is called
1562 again to update the scene parameter inside the scene graph;
1563
1564 2. Callers are responsible for managing the returned object
1565 (rmLightModelDelete the object when it is no longer needed).
1566
1567 @dend
1568 * ----------------------------------------------------
1569 */
1570 RMenum
rmNodeGetSceneLightModel(const RMnode * n,RMlightModel ** lm)1571 rmNodeGetSceneLightModel (const RMnode *n,
1572 RMlightModel **lm)
1573 {
1574 if ((RM_ASSERT(n, "rmNodeGetSceneLightModel() error: the input RMnode pointer is NULL") == RM_WHACKED) ||
1575 (RM_ASSERT(lm, "rmNodeGetSceneLightModel() error: the input pointer to an RMlightModel pointer is NULL.") == RM_WHACKED))
1576 return(RM_WHACKED);
1577
1578 if ((n->scene_parms == NULL) ||
1579 (n->scene_parms->lmodel == NULL))
1580 return(RM_WHACKED);
1581
1582 *lm = rmLightModelNew();
1583 memcpy((void *)(*lm), (void *)(n->scene_parms->lmodel), sizeof(RMlightModel));
1584
1585 return(RM_CHILL);
1586 }
1587
1588
1589 /*
1590 * ----------------------------------------------------
1591 * @Name rmTextPropsNew
1592 @pstart
1593 RMtextProps * rmTextPropsNew (void)
1594 @pend
1595
1596 @astart
1597 No arguments.
1598 @aend
1599
1600 @dstart
1601
1602 Creates a new RMtextProps object and returns a handle to the caller.
1603
1604 Upon success, the returned handle points to a new RMtextProps object.
1605 If resources cannot be allocated, then a NULL handle is returned.
1606
1607 The RMtextProps object may be assigned as a scene parameter to RMnodes,
1608 where it will control text rendering properties, such as font family,
1609 size, italizication, etc. These text properties may be thought of in
1610 the same way as other drawing parameters, such as material properties,
1611 current color, and so forth.
1612
1613 The defaults text rendering properties set by rmTextPropsNew() are
1614 controlled by definitions in rmglobals.c, and are:
1615
1616 <pre>
1617 RMenum RM_DEFAULT_HJUSTIFY = RM_LEFT;
1618 RMenum RM_DEFAULT_VJUSTIFY = RM_BOTTOM;
1619 RMenum RM_DEFAULT_FONT_FAMILY = RM_FONT_SANS;
1620 RMenum RM_DEFAULT_FONT_SIZE = RM_FONT_M;
1621 RMenum RM_DEFAULT_FONT_BOLD = RM_FALSE;
1622 RMenum RM_DEFAULT_FONT_ITALIC = RM_FALSE;
1623 </pre>
1624
1625 Use rmTextPropsSetAttribs() to set the attributes of an RMtextProps
1626 object, or rmTextPropsGetAttribs() to query attributes.
1627
1628 @dend
1629 * ----------------------------------------------------
1630 */
1631 RMtextProps *
rmTextPropsNew(void)1632 rmTextPropsNew (void)
1633 {
1634 /* these are set in rmglobals.c */
1635 extern int RM_DEFAULT_FONT_FAMILY, RM_DEFAULT_FONT_SIZE;
1636 extern RMenum RM_DEFAULT_FONT_BOLD, RM_DEFAULT_FONT_ITALIC,
1637 RM_DEFAULT_HJUSTIFY, RM_DEFAULT_VJUSTIFY;
1638
1639 RMtextProps *t;
1640
1641 t = private_rmTextPropsNew();
1642
1643 if (RM_ASSERT(t, "rmTextPropsNew() error: malloc failure. ") == RM_WHACKED)
1644 return(NULL);
1645
1646 rmTextPropsSetAttribs(t,
1647 RM_DEFAULT_FONT_FAMILY,
1648 RM_DEFAULT_FONT_SIZE,
1649 RM_DEFAULT_FONT_BOLD,
1650 RM_DEFAULT_FONT_ITALIC,
1651 RM_DEFAULT_HJUSTIFY,
1652 RM_DEFAULT_VJUSTIFY);
1653 return(t);
1654 }
1655
1656 /*
1657 * ----------------------------------------------------
1658 * @Name rmTextPropsDelete
1659 @pstart
1660 RMenum rmTextPropsDelete (RMtextProps *toDelet)
1661 @pend
1662
1663 @astart
1664 RMtextProps *toDelete - a handle to an RMtextProps object (deleted).
1665 @aend
1666
1667 @dstart
1668
1669 Deletes the resources associated with an RMtextProps object.
1670
1671 Upon success, RM_CHILL is returned; otherwise, RM_WHACKED is
1672 returned.
1673
1674 @dend
1675 * ----------------------------------------------------
1676 */
1677 RMenum
rmTextPropsDelete(RMtextProps * t)1678 rmTextPropsDelete (RMtextProps *t)
1679 {
1680 if (RM_ASSERT(t, "rmTextPropsDelete() error: the input RMtextProps object is NULL") == RM_WHACKED)
1681 return(RM_WHACKED);
1682
1683 return(private_rmTextPropsDelete(t));
1684 }
1685
1686
1687 /*
1688 * ----------------------------------------------------
1689 * @Name rmNodeSetSceneTextProps
1690 @pstart
1691 RMenum rmNodeSetSceneTextProps (RMnode *toModify,
1692 const RMtextProps *newTextProps)
1693 @pend
1694
1695 @astart
1696 RMnode *toModify - a handle to an RMnode (modified).
1697
1698 const RMtextProps *newTextProps - a handle to an RMtextProps object (input).
1699 @aend
1700
1701 @dstart
1702
1703 Assigns an RMtextProps object as a scene parameter for an RMnode. These
1704 text properties will control how strings are rendered within the
1705 subtree rooted at the RMnode toModify, unless subsequently overridden
1706 at a descendent RMnode. The text properties specify a font family,
1707 point size, horizontal and vertical justification control, and
1708 emboldening and italicization parameters.
1709
1710 If the input RMtextProps object is NULL, any existing RMtextProps
1711 scene parameter is deleted.
1712
1713 Upon success, RM_CHILL is returned; otherwise, RM_WHACKED is
1714 returned.
1715
1716 Because this routine makes a copy of the input scene parameter (an
1717 RMtextProps object), callers do not need to manage the input object after a
1718 successful return from this routine. This has important ramificiations:
1719
1720 1. Since a copy is made, any changes made to the caller's object will have
1721 no effect upon the scene graph, unless this routine is called again to
1722 update the scene parameter inside the scene graph;
1723
1724 2. Callers may safely delete their copy of the input object after a
1725 successful return from this routine.
1726 @dend
1727 * ----------------------------------------------------
1728 */
1729 RMenum
rmNodeSetSceneTextProps(RMnode * n,const RMtextProps * t)1730 rmNodeSetSceneTextProps (RMnode *n,
1731 const RMtextProps *t)
1732 {
1733 if (RM_ASSERT(n, "rmNodeSetSceneTextProps() error: the input RMnode is NULL. \n") == RM_WHACKED)
1734 return(RM_WHACKED);
1735
1736 if (n->scene_parms == NULL)
1737 n->scene_parms = private_rmNodeSceneParmsNew();
1738
1739 if ((n->scene_parms->textProps == NULL) && (t != NULL))
1740 n->scene_parms->textProps = rmTextPropsNew();
1741
1742 if (t != NULL)
1743 private_rmTextPropsCopy(t, n->scene_parms->textProps);
1744 else
1745 {
1746 if (n->scene_parms->textProps != NULL)
1747 rmTextPropsDelete(n->scene_parms->textProps);
1748 t = NULL;
1749 }
1750
1751 #if 0
1752 /* this code would actually generate OpenGL display lists for
1753 the string using the requested font and style. we're going to
1754 delay doing this until render time. */
1755 /* register the font, size, embolden, italic with RM's font registry */
1756 if (t != NULL)
1757 private_rmPrepareBitmapFont(n->scene_parms->textProps);
1758 #endif
1759
1760 return(RM_CHILL);
1761 }
1762
1763
1764 /*
1765 * ----------------------------------------------------
1766 * @Name rmNodeGetSceneTextProps
1767 @pstart
1768 RMenum rmNodeGetSceneTextProps (const RMnode *toQuery,
1769 RMtextProps **returnTextProps)
1770 @pend
1771
1772 @astart
1773 const RMnode *toQuery - a handle to an RMnode (input).
1774
1775 RMtextProps **returnTextProps - a caller-supplied handle to an
1776 RMtextProps handle (return).
1777 @aend
1778
1779 @dstart
1780
1781 Obtains a copy of the RMtextProps object scene parameter for the
1782 RMnode, and returns a handle to the copy in the parameter returnTextProps,
1783 and RM_CHILL is returned on the stack.
1784
1785 If no such scene parameter exists, or if there is some other error
1786 condition encountered, RM_WHACKED is returned on the stack, and
1787 the caller-supplied parameter returnTextProps remains unmodified.
1788
1789 Because this routine returns a COPY of the RMnode's scene parameter (an
1790 RMtextProps object), two important ramifications should be noted:
1791
1792 1. Since a copy is returned, any changes made to the caller's object will have
1793 no effect upon the scene graph, unless the appropriate routine is called
1794 again to update the scene parameter inside the scene graph;
1795
1796 2. Callers are responsible for managing the returned object
1797 (rmTextProps the object when it is no longer needed).
1798
1799 @dend
1800 * ----------------------------------------------------
1801 */
1802 RMenum
rmNodeGetSceneTextProps(const RMnode * n,RMtextProps ** t)1803 rmNodeGetSceneTextProps (const RMnode *n,
1804 RMtextProps **t)
1805 {
1806 if ((RM_ASSERT(n, "rmNodeGetSceneTextProps() error: the input RMnode pointer is NULL") == RM_WHACKED) ||
1807 (RM_ASSERT(t, "rmNodeGetSceneTextProps() error: the input pointer to an RMtextProps pointer is NULL.") == RM_WHACKED))
1808 return(RM_WHACKED);
1809
1810 if ((n->scene_parms == NULL) || (n->scene_parms->textProps == NULL))
1811 return(RM_WHACKED);
1812
1813 *t = rmTextPropsNew();
1814 private_rmTextPropsCopy(n->scene_parms->textProps, *t);
1815
1816 return(RM_CHILL);
1817 }
1818
1819
1820 /*
1821 * ----------------------------------------------------
1822 * @Name rmNodeSetSceneTexture
1823 @pstart
1824 RMenum rmNodeSetSceneTexture (RMnode *toModify,
1825 const RMtexture *newTexture)
1826 @pend
1827
1828 @astart
1829 RMnode *n - a handle to an RMnode (modified).
1830
1831 RMtexture *t - a handle to an RMtexture (input).
1832 @aend
1833
1834 @dstart
1835
1836 Assigns an RMtexture object as a scene parameter to the RMnode.
1837 The presence of a texture scene parameter will cause texture mapping
1838 to become active at the RMnode toModify, and will remain active
1839 using the supplied texture newTexture over the entire subtree
1840 rooted at the RMnode toModify, unless overridden by a different
1841 texture at a descendent node within the scene graph.
1842
1843 In order for texture mapping to occur at the pixel fragment level,
1844 primitives need to have texture coordinates (as well as vertex data).
1845
1846 Specifying a value of NULL for the input texture will remove
1847 any existing texture scene parameter from the RMnode, effectively
1848 disabling texture mapping within the scene graph subtree rooted
1849 at toModify.
1850
1851 Upon success, RM_CHILL is returned; otherwise, RM_WHACKED is
1852 returned.
1853
1854 Starting with OpenRM version 1.5.1 and later, when you assign an
1855 RMtexture as a scene parameter to an RMnode, only a reference to the
1856 source RMtexture is copied. In this way, you can use a single RMtexture
1857 object as a source texture for an arbitrary number of scene graph nodes
1858 without incurring additional memory storage overhead for each instance
1859 of the texture. The caveat from an application developer's perspective
1860 is that you must treat RMtextures like RMnodes - don't delete them
1861 until they are really no longer needed.
1862
1863 If you try to rmTextureDelete a texture that has been assigned as a
1864 scene parameter, rmTextureDelete will fail - the RMtexture has a
1865 reference counter that is incremented or decremented when it is assigned
1866 or removed as a scene parameter at the scene graph node level. The
1867 simplest way to delete the RMtexture assigned to one or more nodes
1868 as a scene parameter is to simply delete the node or tree of nodes.
1869 All associated scene parameters will be deleted when their reference
1870 counters reach a value of zero.
1871
1872 @dend
1873 * ----------------------------------------------------
1874 */
1875 RMenum
rmNodeSetSceneTexture(RMnode * n,RMtexture * t)1876 rmNodeSetSceneTexture (RMnode *n,
1877 RMtexture *t)
1878 {
1879 RMenum rstat;
1880
1881 if (RM_ASSERT(n, "rmNodeSetSceneTexture() error: the input RMnode pointer is NULL.") == RM_WHACKED)
1882 return RM_WHACKED;
1883
1884 /* the index RM_MAX_MULTITEXTURES is reserved for "plain old,
1885 non-multitextured textures */
1886 rstat = private_rmNodeSetSceneTexture(n, t, RM_MAX_MULTITEXTURES);
1887
1888 return rstat;
1889 }
1890
1891 /*
1892 * ----------------------------------------------------
1893 * @Name rmNodeSetSceneMultiTexture
1894 @pstart
1895 RMenum rmNodeSetSceneMultiTexture (RMnode *toModify,
1896 const RMtexture *newTexture,
1897 int textureUnit)
1898 @pend
1899
1900 @astart
1901 RMnode *n - a handle to an RMnode (modified).
1902
1903 RMtexture *t - a handle to an RMtexture (input).
1904
1905 int textureUnit - an integer value (input).
1906 @aend
1907
1908 @dstart
1909
1910 Similar in function to rmNodeSetSceneTexture, but different in the
1911 respect that the RMtexture is assigned to a specific multitexturing
1912 texturing unit.
1913
1914 Multitexturing the process whereby pixel fragments are colored using
1915 texel colors obtained from multiple textures using multiple texture
1916 coordinates. It is not supported on all OpenGL platforms. During the
1917 rmPipeMakeCurrent() initialization sequence, the underlying OpenGL
1918 platform is queried to determine extensions, capabilities and so
1919 forth. After rmPipeMakeCurrent(), your application can call
1920 rmPipeGetNumMultitextureUnits() to determine the number of OpenGL
1921 texture units available.
1922
1923 Note that this routine does not perform any error checking with regard
1924 to ensuring that the value you provide for textureUnit does not exceed
1925 the number of texture units. That sort of problem will result in an
1926 runtime error that may be difficult to track down. It is the
1927 application's responsiblity to ensure that the value for texturenit is
1928 valid for the particular implementation.
1929
1930 Valid values for the "textureUnit" parameter are non-negative integers in the
1931 range 0..RM_MAX_MULTITEXTURES. Note that RM_MAX_MULTITEXTURES is a
1932 compile-time constant, and does not necessarily reflect the actual
1933 number of texture units supported by your OpenGL implementation.
1934
1935 @dend
1936 * ----------------------------------------------------
1937 */
1938 RMenum
rmNodeSetSceneMultiTexture(RMnode * n,RMtexture * t,int textureUnit)1939 rmNodeSetSceneMultiTexture (RMnode *n,
1940 RMtexture *t,
1941 int textureUnit)
1942 {
1943 RMenum rstat;
1944
1945 if (RM_ASSERT(n, "rmNodeSetSceneMultiTexture() error: the input RMnode pointer is NULL.") == RM_WHACKED)
1946 return RM_WHACKED;
1947
1948 /* sanity check the input value. Want something between zero and
1949 RM_MAX_MULTITEXTURES */
1950 if ((textureUnit < 0) || (textureUnit > (RM_MAX_MULTITEXTURES-1)))
1951 {
1952 char buf[256];
1953 sprintf(buf, "rmNodeSetSceneMultitexture error - the input value for the textureUnit parameter needs to be between 0 and %d.", RM_MAX_MULTITEXTURES-1);
1954 rmError(buf);
1955 return RM_WHACKED;
1956 }
1957
1958 rstat = private_rmNodeSetSceneTexture(n, t, textureUnit);
1959
1960 return rstat;
1961 }
1962
1963 /*
1964 * ----------------------------------------------------
1965 * @Name rmNodeGetSceneTexture
1966 @pstart
1967 RMenum rmNodeGetSceneTexture (const RMnode *toQuery,
1968 RMtexture **returnTexture)
1969 @pend
1970
1971 @astart
1972 const RMnode *toQuery - a handle to an RMnode (input).
1973
1974 RMtexture **returnTexture - a handle to an RMtexture handle (return).
1975 @aend
1976
1977 @dstart
1978
1979 Use this routine to obtain the handle of the RMtexture scene parameter
1980 at an RMnode. If such a scene parameter is present, a handle to the
1981 internal RMtexture object is copied into caller-supplied memory
1982 (returnTexture), and RM_CHILL is returned on the stack. Otherwise,
1983 RM_WHACKED is returned, and caller-supplied memory remains unmodified.
1984
1985 This routine will be useful for applications that will use the
1986 routine rmNodeUpdateSceneTexture to replace the contents of a
1987 particular texture, perhaps on a time-varying basis.
1988
1989 @dend
1990 * ----------------------------------------------------
1991 */
1992 RMenum
rmNodeGetSceneTexture(const RMnode * n,RMtexture ** t)1993 rmNodeGetSceneTexture (const RMnode *n,
1994 RMtexture **t)
1995 {
1996 if ((RM_ASSERT(n, "rmNodeGetSceneTexture() error: input RMnode pointer is NULL.") == RM_WHACKED) ||
1997 (RM_ASSERT(t, "rmNodeGetSceneTexture() error: input pointer to RMtexture pointer is NULL.") == RM_WHACKED))
1998 return(RM_WHACKED);
1999
2000 if ((n->scene_parms == NULL) || (n->scene_parms->textures[RM_MAX_MULTITEXTURES] == NULL))
2001 return(RM_WHACKED);
2002
2003 *t = n->scene_parms->textures[RM_MAX_MULTITEXTURES];
2004
2005 return(RM_CHILL);
2006 }
2007
2008
2009 /*
2010 * ----------------------------------------------------
2011 * @Name rmNodeGetSceneMultiTexture
2012 @pstart
2013 RMenum rmNodeGetSceneMultiTexture (const RMnode *toQuery,
2014 int textureIndx,
2015 RMtexture **returnTexture)
2016 @pend
2017
2018 @astart
2019 const RMnode *toQuery - a handle to an RMnode (input).
2020
2021 int textureIndx - an integer value (input).
2022
2023 RMtexture **returnTexture - a handle to an RMtexture handle (return).
2024 @aend
2025
2026 @dstart
2027
2028 Similar in function and return values to rmNodeGetSceneTexture. This
2029 routine is used to obtain a handle to the RMtexture that is assigned to
2030 a specific multitexturing texture unit.
2031
2032 @dend
2033 * ----------------------------------------------------
2034 */
2035 RMenum
rmNodeGetSceneMultiTexture(const RMnode * n,int textureIndx,RMtexture ** t)2036 rmNodeGetSceneMultiTexture (const RMnode *n,
2037 int textureIndx,
2038 RMtexture **t)
2039 {
2040 if ((RM_ASSERT(n, "rmNodeGetSceneMultiTexture() error: input RMnode pointer is NULL.") == RM_WHACKED) ||
2041 (RM_ASSERT(t, "rmNodeGetSceneMultiTexture() error: input pointer to RMtexture pointer is NULL.") == RM_WHACKED))
2042 return(RM_WHACKED);
2043
2044 if ((textureIndx < 0) || (textureIndx > (RM_MAX_MULTITEXTURES-1)))
2045 {
2046 char buf[256];
2047 sprintf(buf,"rmNodeGetSceneMultiTexture error - the input textureIndx has a value of %d, but it should have a value in the range zero..%d \n", textureIndx, RM_MAX_MULTITEXTURES-1);
2048 rmWarning(buf);
2049 return RM_WHACKED;
2050 }
2051
2052 if ((n->scene_parms == NULL) || (n->scene_parms->textures[textureIndx] == NULL))
2053 return(RM_WHACKED);
2054
2055 *t = n->scene_parms->textures[textureIndx];
2056
2057 return RM_CHILL;
2058 }
2059
2060 /*
2061 * ----------------------------------------------------
2062 * @Name rmNodeSetSceneViewport
2063 @pstart
2064 RMenum rmNodeSetSceneViewport (RMnode *toModify,
2065 const float *newViewport)
2066 @pend
2067
2068 @astart
2069 RMnode *toModify - a handle to an RMnode (modified).
2070
2071 const float *newViewport - a handle to an array of four floats, defining a
2072 viewport (input) [x, y, w, h].
2073 @aend
2074
2075 @dstart
2076
2077 The viewport scene parameter defines a pixel rectangle in the window
2078 into which the final image is mapped. The four viewport parameters,
2079 (x, y, width, height), are passed in as a single array of floats.
2080 The (x,y) coordinate specifies the lower left corner of the viewport
2081 rectangle. Width and height are the size of the viewport. The input
2082 values are specified in normalized device coordinates: Use input values
2083 of {0.0, 0.0, 1.0, 1.0} to consume the entire window; an NDC coordinate
2084 of (0.5, 0.5) refers to a point in the middle of the display window,
2085 regardless of its pixel dimensions.
2086
2087 Use this routine to specify a viewport as a scene parameter at an
2088 RMnode. Upon success, any existing viewport at the RMnode is removed,
2089 then a copy of the input viewport parameters are made, then assigned
2090 to the RMnode toModify. Passing in a value of NULL for the viewport
2091 parameter will result in the removal of any existing viewport
2092 scene parameter from the RMnode.
2093
2094 Upon success, RM_CHILL is returned; otherwise, RM_WHACKED is
2095 returned.
2096
2097 Because this routine makes a copy of the input scene parameter (an
2098 viewport specification), callers do not need to manage the input object
2099 after a successful return from this routine. This has important
2100 ramificiations:
2101
2102 1. Since a copy is made, any changes made to the caller's object will have
2103 no effect upon the scene graph, unless this routine is called again to
2104 update the scene parameter inside the scene graph;
2105
2106 2. Callers may safely delete their copy of the input object after a
2107 successful return from this routine.
2108
2109 @dend
2110 * ----------------------------------------------------
2111 */
2112 RMenum
rmNodeSetSceneViewport(RMnode * n,const float * vp)2113 rmNodeSetSceneViewport (RMnode *n,
2114 const float *vp) /* [x, y, w, h], ndc coords */
2115 {
2116 if (RM_ASSERT(n, "rmNodeSetSceneViewport() error: the input RMnode pointer is NULL") == RM_WHACKED)
2117 return(RM_WHACKED);
2118
2119 if (n->scene_parms == NULL)
2120 n->scene_parms = private_rmNodeSceneParmsNew();
2121
2122 if (n->scene_parms->viewport != NULL)
2123 {
2124 rmFloatDelete(n->scene_parms->viewport);
2125 n->scene_parms->viewport = NULL;
2126 }
2127
2128 if (vp != NULL)
2129 {
2130 n->scene_parms->viewport = rmFloatNew(4);
2131 memcpy((void *)(n->scene_parms->viewport), (void *)vp, (sizeof(float) * 4));
2132 }
2133
2134 private_rmNodeAttribMask(n,private_rmNodeComputeAttribMask(n),RM_SET);
2135 return(RM_CHILL);
2136 }
2137
2138
2139 /*
2140 * ----------------------------------------------------
2141 * @Name rmNodeGetSceneViewport
2142 @pstart
2143 RMenum rmNodeGetSceneViewport (const RMnode *toQuery,
2144 float **returnViewport)
2145 @pend
2146
2147 @astart
2148 const RMnode *toQuery - a handle to an RMnode (input).
2149
2150 float **returnViewport - a handle to an array of float (returned).
2151 @aend
2152
2153 @dstart
2154
2155 This routine is used to query the viewport scene parameters at an
2156 RMnode. If the input RMnode toQuery has a viewport scene parameter,
2157 a copy of the viewport is created, then the handle to the copy returned
2158 to the caller through the parameter returnViewport, and RM_CHILL is
2159 returned on the stack.
2160
2161 Otherwise, RM_WHACKED is returned and the caller supplied return
2162 parameter returnViewport remains unmodified.
2163
2164 Because this routine returns a COPY of the RMnode's scene parameter (an
2165 array of floats), two important ramifications should be noted:
2166
2167 1. Since a copy is returned, any changes made to the caller's object will have
2168 no effect upon the scene graph, unless the appropriate routine is called
2169 again to update the scene parameter inside the scene graph;
2170
2171 2. Callers are responsible for managing the returned object
2172 (rmFloatDelete the object when it is no longer needed).
2173
2174 @dend
2175 * ----------------------------------------------------
2176 */
2177 RMenum
rmNodeGetSceneViewport(const RMnode * n,float ** vp)2178 rmNodeGetSceneViewport (const RMnode *n,
2179 float **vp) /* [x, y, w, h] */
2180 {
2181 if ((RM_ASSERT(n, "rmNodeGetSceneViewport() error: the input RMnode pointer is NULL") == RM_WHACKED) ||
2182 (RM_ASSERT(vp, "rmNodeGetSceneViewport() error: the input pointer to a float pointer is NULL.") == RM_WHACKED))
2183 return(RM_WHACKED);
2184
2185 if ((n->scene_parms == NULL) || (n->scene_parms->viewport == NULL))
2186 return(RM_WHACKED);
2187
2188 *vp = rmFloatNew(4);
2189 memcpy((void *)(*vp), (void *)(n->scene_parms->viewport), sizeof(float)*4);
2190
2191 return(RM_CHILL);
2192 }
2193
2194
2195 /* PRIVATE */
2196 RMtextProps *
private_rmDefaultTextProps(RMpipe * p)2197 private_rmDefaultTextProps (RMpipe *p)
2198 {
2199 /*
2200 * create a known and "default" font that will be used when the
2201 * app wants to draw text, but fails to provide an RMtextProps
2202 * object anywhere in the scene graph.
2203 */
2204 RMtextProps *tp;
2205
2206 tp = rmTextPropsNew();
2207 rmTextPropsSetAttribs(tp, RM_FONT_SANS, RM_FONT_M, RM_FALSE, RM_FALSE, RM_LEFT, RM_BOTTOM);
2208
2209 if (p != NULL)
2210 private_rmPrepareBitmapFont(tp,p);
2211
2212 return(tp);
2213 }
2214
2215
2216 /* PRIVATE */
2217 internals_RMsceneParms *
private_rmNodeSceneParmsNew(void)2218 private_rmNodeSceneParmsNew (void)
2219 {
2220 internals_RMsceneParms *t;
2221
2222 t = (internals_RMsceneParms *)malloc(sizeof(internals_RMsceneParms));
2223 memset(t, 0, sizeof(internals_RMsceneParms));
2224
2225 t->haveAnyTextures = RM_FALSE;
2226
2227 return(t);
2228 }
2229
2230 /* PRIVATE */
2231 internals_RMfbClear *
private_rmFBClearNew(void)2232 private_rmFBClearNew (void)
2233 {
2234 internals_RMfbClear *t;
2235
2236 t = (internals_RMfbClear *)malloc(sizeof(internals_RMfbClear));
2237 memset(t, 0, sizeof(internals_RMfbClear));
2238
2239 return(t);
2240 }
2241
2242 /* PRIVATE */
2243 RMenum
private_rmNodeSetSceneTexture(RMnode * n,RMtexture * t,int textureUnit)2244 private_rmNodeSetSceneTexture(RMnode *n,
2245 RMtexture *t,
2246 int textureUnit)
2247 {
2248 if (n->scene_parms == NULL)
2249 n->scene_parms = private_rmNodeSceneParmsNew();
2250
2251 /* remove the old texture, if any */
2252 if (n->scene_parms->textures[textureUnit] != NULL)
2253 {
2254 int refCount = private_rmTextureGetRefCount(n->scene_parms->textures[textureUnit]);
2255
2256 /*
2257 * 11/21/03
2258 * if the refCount is -1, then the texture isn't a shared texture
2259 * and we should delete it.
2260 */
2261 if (refCount == -1)
2262 rmTextureDelete(n->scene_parms->textures[textureUnit], RM_TRUE);
2263 else
2264 {
2265 /*
2266 * otherwise, we want to decrement the reference count, but
2267 * clamp the new value to be >= 0. We won't automatically delete
2268 * a shared texture - that is the application's responsibility.
2269 */
2270 refCount -= 1;
2271 if (refCount < 0)
2272 refCount = 0;
2273 private_rmTextureSetRefCount(n->scene_parms->textures[textureUnit], refCount);
2274 }
2275 }
2276
2277 if (t != NULL)
2278 {
2279 /* update the RMtexture's context cache ID and data keys if they
2280 are not uninitialized. */
2281 if (t->cacheKeyID == RM_CACHEKEY_UNINITIALIZED_VALUE)
2282 private_rmTextureSetIDCacheKey(t);
2283
2284 if (t->cacheKeyData == RM_CACHEKEY_UNINITIALIZED_VALUE)
2285 private_rmTextureSetDataCacheKey(t);
2286
2287 /* increment the texture's refcount */
2288 private_rmTextureSetRefCount(t, private_rmTextureGetRefCount(t) + 1);
2289 n->scene_parms->textures[textureUnit] = t;
2290 }
2291 else
2292 n->scene_parms->textures[textureUnit] = NULL;
2293
2294 {
2295 int i;
2296 n->scene_parms->haveAnyTextures = RM_FALSE;
2297 for (i=0; i <= RM_MAX_MULTITEXTURES; i++)
2298 {
2299 if (n->scene_parms->textures[i] != NULL)
2300 {
2301 n->scene_parms->haveAnyTextures = RM_TRUE;
2302 break;
2303 }
2304 }
2305 }
2306
2307 private_rmNodeAttribMask(n,private_rmNodeComputeAttribMask(n),RM_SET);
2308 return RM_CHILL;
2309 }
2310
2311 /* EOF */
2312