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