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: rmlites.c,v 1.8 2005/08/06 15:30:39 wes Exp $
27 * Version: $Name: OpenRM-1-6-0-2-RC2 $
28 * $Revision: 1.8 $
29 * $Log: rmlites.c,v $
30 * Revision 1.8 2005/08/06 15:30:39 wes
31 * Reverted to RM_FALSE for localviewer in rmDefaultLighting. Turning off
32 * localviewer results in about a 50% increase in frame rate in one of
33 * our test cases.
34 *
35 * Revision 1.7 2005/06/26 18:51:23 wes
36 * In rmDefaultLighting, changed default setting of localview to RM_TRUE.
37 *
38 * Revision 1.6 2005/02/19 16:22:50 wes
39 * Distro sync and consolidation.
40 *
41 * Revision 1.5 2005/01/23 17:04:03 wes
42 * Copyright update to 2005.
43 *
44 * Revision 1.4 2004/03/10 01:45:10 wes
45 * Enabled use of global default spotlight exponent when a new light
46 * is created with rmLightNew.
47 *
48 * Revision 1.3 2004/01/16 16:45:12 wes
49 * Updated copyright line for 2004.
50 *
51 * Revision 1.2 2003/02/02 02:07:15 wes
52 * Updated copyright to 2003.
53 *
54 * Revision 1.1.1.1 2003/01/28 02:15:23 wes
55 * Manual rebuild of rm150 repository.
56 *
57 * Revision 1.6 2003/01/16 22:21:17 wes
58 * Updated all source files to reflect new organization of header files:
59 * all header files formerly located in include/rmaux, include/rmi, include/rmv
60 * are now located in include/rm.
61 *
62 * Revision 1.5 2002/04/30 19:32:22 wes
63 * Updated copyright dates.
64 *
65 * Revision 1.4 2001/05/26 14:35:10 wes
66 * Doc mods.
67 *
68 * Revision 1.3 2001/03/31 17:12:38 wes
69 * v1.4.0-alpha-2 checkin.
70 *
71 * Revision 1.2 2000/04/20 16:29:47 wes
72 * Documentation additions/enhancements, some code rearragement.
73 *
74 * Revision 1.1.1.1 2000/02/28 21:29:40 wes
75 * OpenRM 1.2 Checkin
76 *
77 * Revision 1.1.1.1 2000/02/28 17:18:48 wes
78 * Initial entry - pre-RM120 release, source base for OpenRM 1.2.
79 *
80 */
81
82 #include <rm/rm.h>
83 #include "rmprivat.h"
84
85 /*
86 * ----------------------------------------------------
87 * @Name rmLightNew
88 @pstart
89 RMlight * rmLightNew (void)
90 @pend
91
92 @astart
93 No arguments.
94 @aend
95
96 @dstart
97
98 Creates a new RMlight object, returning a handle to the new object to
99 the caller.
100
101 The RMlight object is initialized with these values:
102
103 1. Light type set to RM_LIGHT_DIRECTIONAL (see rmLightSetType).
104
105 2. Light direction set to {0.0, 0.0, 1.0} (see rmLightSetXYZ).
106
107 3. Light ambient, diffuse and specular colors set to {0, 0, 0},
108 {0.75, 0.75, 0.75} and {1.0, 1.0, 1.0} respectively (see
109 rmLightSetColor).
110
111 4. Spotlight direction, and cutoff set to {0,0,-1} and 90 degrees,
112 respectively (see rmLightSetSpotDirection and rmLightSetSpotCutoff).
113 Note that these parameters have no meaning with a light source that
114 is not a spotlight.
115
116 5. Light attenuation coefficients consist of a constant, linear and
117 quadratic terms. These are initialized to 1.0, 0.0 and 0.0,
118 respectively (see rmLightSetAttenuation).
119
120 6. The light is enabled (see rmLightSetEnable) with RM_TRUE.
121
122 Notes:
123
124 The process of lighting in RM consists of a number of interrelated
125 factors. One is the presence of light sources in the scene as scene
126 parameters assigned to RMnodes. Another is the specification of a
127 light model, another scene parameter that specifies whether or not
128 lighting is two-sided (illumination of both front- and back-facing
129 polygons by ignoring the sign of the dot product of the surface
130 normal with the direction to/of the light source). Third, objects to
131 be illuminated must have 3D surface normals. The absence of any of
132 these three components will cause lighting/shading to "not work."
133
134 Note that setting attributes in an RMlight does not change them in
135 the scene graph. They must be assigned as scene parameters to an
136 RMnode before they will be used in rendering (see
137 rmNodeSetSceneLight).
138
139 @dend
140 * ----------------------------------------------------
141 */
142 RMlight *
rmLightNew(void)143 rmLightNew (void)
144 {
145 extern float RM_DEFAULT_LIGHT_SPOT_CUTOFF;
146 extern float RM_DEFAULT_LIGHT_CONSTANT_ATTENUATION;
147 extern float RM_DEFAULT_LIGHT_LINEAR_ATTENUATION;
148 extern float RM_DEFAULT_LIGHT_QUADRATIC_ATTENUATION;
149 extern float RM_DEFAULT_LIGHT_SPOT_EXPONENT;
150 extern RMenum RM_DEFAULT_LIGHT_ENABLE;
151 extern RMenum RM_DEFAULT_LIGHT_TYPE;
152 extern RMvertex3D RM_DEFAULT_LIGHT_XYZ;
153 extern RMcolor4D RM_DEFAULT_LIGHT_AMBIENT_COLOR;
154 extern RMcolor4D RM_DEFAULT_LIGHT_DIFFUSE_COLOR;
155 extern RMcolor4D RM_DEFAULT_LIGHT_SPECULAR_COLOR;
156 extern RMvertex3D RM_DEFAULT_LIGHT_SPOT_DIRECTION;
157
158 RMlight *t = (RMlight *)malloc(sizeof(RMlight));
159
160 if (t == NULL)
161 return(NULL);
162
163 memset(t, 0, sizeof(RMlight));
164
165 /* assign default values */
166 rmLightSetType(t, RM_DEFAULT_LIGHT_TYPE);
167 rmLightSetXYZ(t, &RM_DEFAULT_LIGHT_XYZ);
168 rmLightSetColor(t, &RM_DEFAULT_LIGHT_AMBIENT_COLOR, &RM_DEFAULT_LIGHT_DIFFUSE_COLOR, &RM_DEFAULT_LIGHT_SPECULAR_COLOR);
169 rmLightSetSpotExponent(t, RM_DEFAULT_LIGHT_SPOT_EXPONENT);
170 rmLightSetSpotDirection(t, &RM_DEFAULT_LIGHT_SPOT_DIRECTION);
171 rmLightSetSpotCutoff(t, RM_DEFAULT_LIGHT_SPOT_CUTOFF);
172 rmLightSetAttenuation (t, RM_DEFAULT_LIGHT_CONSTANT_ATTENUATION, RM_DEFAULT_LIGHT_LINEAR_ATTENUATION, RM_DEFAULT_LIGHT_QUADRATIC_ATTENUATION);
173 rmLightSetEnable (t, RM_DEFAULT_LIGHT_ENABLE);
174
175 return(t);
176 }
177
178
179 /*
180 * ----------------------------------------------------
181 * @Name rmLightDelete
182 @pstart
183 void rmLightDelete (RMlight *toDelete)
184 @pend
185
186 @astart
187 RMlight *toDelete - a handle to an RMlight object.
188 @aend
189
190 @dstart
191
192 Frees resources associated with an RMlight object. This routine is
193 the opposite of rmLightNew().
194
195 @dend
196 * ----------------------------------------------------
197 */
198 void
rmLightDelete(RMlight * t)199 rmLightDelete (RMlight *t)
200 {
201 if (RM_ASSERT(t, "rmLightDelete() error: the input RMlight is NULL.") == RM_WHACKED)
202 return;
203
204 free((void *)t);
205 }
206
207
208 /*
209 * ----------------------------------------------------
210 * @Name rmLightSetType
211 @pstart
212 RMenum rmLightSetType (RMlight *toModify,
213 RMenum newType)
214 @pend
215
216 @astart
217 RMlight *toModify - a handle to an RMlight object (modified).
218
219 RMenum newType - an RMenum value specifying the new light type for
220 the RMlight object. Must be one of RM_LIGHT_POINT,
221 RM_LIGHT_DIRECTIONAL, or RM_LIGHT_SPOT (input).
222 @aend
223
224 @dstart
225
226 RM light sources may be directional, spot or point light sources, and
227 this routine is used to set the type of an RMlight object to one of
228 those light source types. Returns RM_CHILL upon success, or
229 RM_WHACKED upon failure.
230
231 RMlight objects represent light sources. Of the parameters in an
232 RMlight object, some are used regardless of light source type, while
233 others have meaning only for certain types of lights.
234
235 The ambient, diffuse and specular color attributes are used by all
236 light source types (see rmLightSetColor). Also, the light attenuation
237 coefficients are used by all light source types (see
238 rmLightSetAttenuation).
239
240 All light sources have a 3D coordinate associated with them, set with
241 rmLightSetXYZ. The position of Point light sources (RM_LIGHT_POINT)
242 and spotlight sources (RM_LIGHT_SPOT) is specified with
243 rmLightSetXYZ. Directional light sources have their orientation
244 vector specified with rmLightSetXYZ.
245
246 Note that setting attributes in an RMlight does not change them in
247 the scene graph. They must be assigned as scene parameters to an
248 RMnode before they will be used in rendering (see
249 rmNodeSetSceneLight).
250
251 @dend
252 * ----------------------------------------------------
253 */
254 RMenum
rmLightSetType(RMlight * t,RMenum newType)255 rmLightSetType (RMlight *t,
256 RMenum newType)
257 {
258 if (RM_ASSERT(t, "rmLightSetType() error: the input RMlight is NULL") == RM_WHACKED)
259 return(RM_WHACKED);
260
261 if ((newType == RM_LIGHT_POINT) || (newType == RM_LIGHT_DIRECTIONAL) || (newType == RM_LIGHT_SPOT))
262 {
263 t->ltype = newType;
264 }
265 else
266 {
267 rmError("rmLightSetType() error: the newType enumerator is not one of RM_LIGHT_POINT, RM_LIGHT_DIRECTIONAL or RM_LIGHT_SPOT");
268 return(RM_WHACKED);
269 }
270 return(RM_CHILL);
271 }
272
273
274 /*
275 * ----------------------------------------------------
276 * @Name rmLightGetType
277 @pstart
278 RMenum rmLightGetType (const RMlight *toQuery)
279 @pend
280
281 @astart
282 const RMlight *toQuery - a handle to an RMlight object (input).
283 @aend
284
285 @dstart
286
287 Upon success, returns to the caller the RMlight light source type;
288 RM_LIGHT_POINT, RM_LIGHT_SPOT or RM_LIGHT_DIRECTIONAL. Otherwise,
289 returns RM_WHACKED.
290
291 @dend
292 * ----------------------------------------------------
293 */
294 RMenum
rmLightGetType(const RMlight * t)295 rmLightGetType (const RMlight *t)
296 {
297 if (RM_ASSERT(t, "rmLightGetType() error: the input RMlight is NULL") == RM_WHACKED)
298 return(RM_WHACKED);
299
300 return(t->ltype);
301 }
302
303
304 /*
305 * ----------------------------------------------------
306 * @Name rmLightSetXYZ
307 @pstart
308 RMenum rmLightSetXYZ (RMlight *toModify,
309 const RMvertex3D *newXYZ)
310 @pend
311
312 @astart
313 RMlight *toModify - a handle to an RMlight object (modified).
314
315 const RMvertex3D *newXYZ - a handle to an RMvertex3D object (input).
316 @aend
317
318 @dstart
319
320 This routine is used to set the XYZ attribute of a light source
321 object, controlling the position of RM_LIGHT_POINT and RM_LIGHT_SPOT
322 sources, or the direction of RM_LIGHT_DIRECTIONAL objects. Copies
323 from the caller-supplied RMvertex3D object into the RMlight object.
324
325 Returns RM_CHILL upon success, or RM_WHACKED upon failure.
326
327 Note that setting attributes in an RMlight does not change them in
328 the scene graph. They must be assigned as scene parameters to an
329 RMnode before they will be used in rendering (see
330 rmNodeSetSceneLight).
331
332 @dend
333 * ----------------------------------------------------
334 */
335 RMenum
rmLightSetXYZ(RMlight * t,const RMvertex3D * newXYZ)336 rmLightSetXYZ (RMlight *t,
337 const RMvertex3D *newXYZ)
338 {
339 if ((RM_ASSERT(t, "rmLightSetXYZ() error: the input RMlight is NULL") == RM_WHACKED) ||
340 (RM_ASSERT(newXYZ, "rmLightSetXYZ() error: the input newXYZ pointer is NULL") == RM_WHACKED))
341 return(RM_WHACKED);
342
343 t->lightXYZ = *newXYZ;
344
345 return(RM_CHILL);
346 }
347
348
349 /*
350 * ----------------------------------------------------
351 * @Name rmLightGetXYZ
352 @pstart
353 RMenum rmLightGetXYZ (const RMlight *toQuery,
354 RMvertex3D *retXYZ)
355 @pend
356
357 @astart
358 const RMlight *toQuery - a handle to an RMlight object (input).
359
360 RMvertex3D *retXYZ - a handle to an RMvertex3D object (modified).
361 @aend
362
363 @dstart
364
365 Upon success, copies the light source's XYZ position/orientation
366 attribute from the RMlight object into the caller-supplied memory,
367 and returns RM_CHILL. Upon failure, returns RM_WHACKED.
368
369 @dend
370 * ----------------------------------------------------
371 */
372 RMenum
rmLightGetXYZ(const RMlight * t,RMvertex3D * retXYZ)373 rmLightGetXYZ (const RMlight *t,
374 RMvertex3D *retXYZ)
375 {
376 if ((RM_ASSERT(t, "rmLightGetXYZ() error: the input RMlight is NULL") == RM_WHACKED) ||
377 (RM_ASSERT(retXYZ, "rmLightGetXYZ() error: the input retXYZ pointer is NULL") == RM_WHACKED))
378 return(RM_WHACKED);
379
380 *retXYZ = t->lightXYZ;
381
382 return(RM_CHILL);
383 }
384
385
386 /*
387 * ----------------------------------------------------
388 * @Name rmLightSetColor
389 @pstart
390 RMenum rmLightSetColor (RMlight *toModify,
391 const RMcolor4D *newAmbientColor,
392 const RMcolor4D *newDiffuseColor,
393 const RMcolor4D *newSpecularColor)
394 @pend
395
396 @astart
397 RMlight *toModify - a handle to an RMlight object (modified).
398
399 const RMcolor4D *newAmbientColor, *newDiffuseColor, *newSpecularColor
400 - handles to RMcolor4D objects specifying the RGBA colors for the
401 light source ambient, diffuse and specular light terms. Use of
402 NULL for some or all terms is acceptable (input).
403 @aend
404
405 @dstart
406
407 In RM (and OpenGL), the final shade computed at a vertex is a
408 function of the vertex color, the current material properties and the
409 light source(s). OpenGL uses a Phong-type shading model at each
410 vertex that computes the dot product of the surface normal at the
411 vertex (specified by the application) with the direction to each
412 light source (directional light sources require less work at this
413 stage than positional light sources). This dot product to weight the
414 diffuse and specular reflectance terms of the shading equation.
415
416 The Phong shading equation has terms for three types of light
417 reflectance: ambient, diffuse and specular. It is possible for
418 applications to specify the ambient, diffuse and specular terms
419 (colors) for both the light sources as well as the objects in the
420 scene to implement custom scenes like a yellow light shining on a
421 green ball.
422
423 This routine is used to set the ambient, diffuse and specular color
424 terms for a specific light source.
425
426 Note that the "global ambient light" level is set in the RMlightModel
427 object, not in the RMlight object (see rmLightModelNew).
428
429 It is possible for applications to selectively modify a particular
430 reflectence color term - by specifying NULL for one of the input
431 color vectors, that term in the RMlight object is not modified. In
432 other words, only those non-NULL color terms are modified in the
433 RMlight object.
434
435 Upon success, this routine copies from the caller-supplied RMcolor4D
436 objects into the RMlight object and returns RM_CHILL. Otherwise,
437 RM_WHACKED is returned.
438
439 Note that setting attributes in an RMlight does not change them in
440 the scene graph. They must be assigned as scene parameters to an
441 RMnode before they will be used in rendering (see
442 rmNodeSetSceneLight).
443
444 @dend
445 * ----------------------------------------------------
446 */
447 RMenum
rmLightSetColor(RMlight * t,const RMcolor4D * newAmbientColor,const RMcolor4D * newDiffuseColor,const RMcolor4D * newSpecularColor)448 rmLightSetColor (RMlight *t,
449 const RMcolor4D *newAmbientColor,
450 const RMcolor4D *newDiffuseColor,
451 const RMcolor4D *newSpecularColor)
452 {
453 if (RM_ASSERT(t, "rmLightSetAmbientColor() error: the input RMlight is NULL") == RM_WHACKED)
454 return(RM_WHACKED);
455
456 if (newAmbientColor != NULL)
457 t->ambientLightColor = *newAmbientColor;
458
459 if (newDiffuseColor != NULL)
460 t->diffuseLightColor = *newDiffuseColor;
461
462 if (newSpecularColor != NULL)
463 t->specularLightColor = *newSpecularColor;
464
465 return(RM_CHILL);
466 }
467
468
469 /*
470 * ----------------------------------------------------
471 * @Name rmLightGetColor
472 @pstart
473 RMenum rmLightGetColor (const RMlight *toQuery,
474 RMcolor4D *retAmbientColor,
475 RMcolor4D *retDiffuseColor,
476 RMcolor4D *retSpecularColor)
477 @pend
478
479 @astart
480 const RMlight *toQuery - a handle to an RMlight object (input).
481
482 RMcolor4D *retAmbientColor, *retDiffuseColor, *retSpecularColor -
483 handles to RMcolor4D objects (modified). Use of NULL for some or
484 all terms is acceptable (input).
485 @aend
486
487 @dstart
488
489 Use this routine to obtain one or more light source color vectors
490 from an RMlight object. Upon success, one or more color vectors is
491 copied from the RMlight object into caller-supplied memory, and
492 RM_CHILL is returned. Otherwise, RM_WHACKED is returned.
493
494 @dend
495 * ----------------------------------------------------
496 */
497 RMenum
rmLightGetColor(const RMlight * t,RMcolor4D * retAmbientColor,RMcolor4D * retDiffuseColor,RMcolor4D * retSpecularColor)498 rmLightGetColor (const RMlight *t,
499 RMcolor4D *retAmbientColor,
500 RMcolor4D *retDiffuseColor,
501 RMcolor4D *retSpecularColor)
502 {
503 if (RM_ASSERT(t, "rmLightGetColor() error: the input RMlight is NULL") == RM_WHACKED)
504 return(RM_WHACKED);
505
506 if (retAmbientColor != NULL)
507 *retAmbientColor = t->ambientLightColor;
508
509 if (retDiffuseColor != NULL)
510 *retDiffuseColor = t->diffuseLightColor;
511
512 if (retSpecularColor != NULL)
513 *retSpecularColor = t->specularLightColor;
514
515 return(RM_CHILL);
516 }
517
518
519 /*
520 * ----------------------------------------------------
521 * @Name rmLightSetAttenuation
522 @pstart
523 RMenum rmLightSetAttenuation (RMlight *toModify,
524 float newConstantAttenuation,
525 float newLinearAttenuation,
526 float newQuadraticAttenuation)
527 @pend
528
529 @astart
530 RMlight *toModify - a handle to an RMlight object (modified).
531
532 float newConstantAttenuation, newLinearAttenuation,
533 newQuadraticAttenuation - floating point values specifying the
534 coefficients for constant, linear and quadratic light attenuation,
535 or decay, for an RMlight source (input).
536 @aend
537
538 @dstart
539
540 In the real world, light intensity decays as a function of distance
541 from the light source. The further away from the light source, the
542 weaker the light. The rate at which light decays is largely a
543 function of the medium through which the light energy passes. In a
544 vaccuum, like space, light decays slowly. In another medium, like
545 water, light decays more rapidly as the light energy is absorbed by
546 the participating medium.
547
548 Applications have some measure of control over how light energy
549 decays as a function of distance from the light source through the
550 manipulation of "light attenuation factors." The equation used to
551 compute attenuation of light intensity at some point in space is:
552
553 L = 1 / (Kc + Kl * d + Kq * d^2)
554
555 where d is the distance to the light source.
556
557 By default, that constant term (Kc) is set to 1.0, and the linear
558 (Kl) and quadratic (Kq) terms are set to zero; light energy does not
559 decay at all. Most OpenGL implementations are optimized for this
560 condition.
561
562 Upon success, the three attenuation coefficients are copied into the
563 RMlight object, and RM_CHILL is returned. Otherwise, RM_WHACKED is
564 returned.
565
566 Note that setting attributes in an RMlight does not change them in
567 the scene graph. They must be assigned as scene parameters to an
568 RMnode before they will be used in rendering (see
569 rmNodeSetSceneLight).
570
571 @dend
572 * ----------------------------------------------------
573 */
574 RMenum
rmLightSetAttenuation(RMlight * t,float newConstantAttenuation,float newLinearAttenuation,float newQuadraticAttenuation)575 rmLightSetAttenuation (RMlight *t,
576 float newConstantAttenuation,
577 float newLinearAttenuation,
578 float newQuadraticAttenuation)
579 {
580 if (RM_ASSERT(t, "rmLightSetAttenuation() error: the input RMlight is NULL") == RM_WHACKED)
581 return(RM_WHACKED);
582
583 t->constantAttenuation = newConstantAttenuation;
584 t->linearAttenuation = newLinearAttenuation;
585 t->quadraticAttenuation = newQuadraticAttenuation;
586
587 return(RM_CHILL);
588 }
589
590
591 /*
592 * ----------------------------------------------------
593 * @Name rmLightGetAttenuation
594 @pstart
595 RMenum rmLightGetAttenuation (const RMlight *toQuery,
596 float *retConstantAttenuation,
597 float *retLinearAttenuation,
598 float *retQuadraticAttenuation)
599 @pend
600
601 @astart
602 const RMlight *toQuery - a handle to an RMlight object (input).
603
604 float *retConstantAttenuation, *retLinearAttenuation,
605 *retQuadraticAttenuation - handle to caller-supplied floats
606 (modified).
607 @aend
608
609 @dstart
610
611 Upon success, copies the three light attenuation factors into
612 caller-supplied memory and returns RM_CHILL. Otherwise, RM_WHACKED is
613 returned.
614
615 Note that all three input parameters must be non-NULL, otherwise an
616 error condition is produced.
617
618 See rmLightSetAttenuation for more details about these attributes.
619
620 @dend
621 * ----------------------------------------------------
622 */
623 RMenum
rmLightGetAttenuation(const RMlight * t,float * retConstantAttenuation,float * retLinearAttenuation,float * retQuadraticAttenuation)624 rmLightGetAttenuation (const RMlight *t,
625 float *retConstantAttenuation,
626 float *retLinearAttenuation,
627 float *retQuadraticAttenuation)
628 {
629 if ((RM_ASSERT(t, "rmLightGetAttenuation() error: the input RMlight is NULL") == RM_WHACKED) ||
630 (RM_ASSERT(retConstantAttenuation, "rmLightGetAttenuation() error: the retConstantAttenuation pointer is NULL") == RM_WHACKED) ||
631 (RM_ASSERT(retLinearAttenuation, "rmLightGetAttenuation() error: the retLinearAttenuation pointer is NULL") == RM_WHACKED) ||
632 (RM_ASSERT(retQuadraticAttenuation, "rmLightGetAttenuation() error: the retQuadraticAttenuation pointer is NULL") == RM_WHACKED))
633 return(RM_WHACKED);
634
635 *retConstantAttenuation = t->constantAttenuation;
636 *retLinearAttenuation = t->linearAttenuation;
637 *retQuadraticAttenuation = t->quadraticAttenuation;
638
639 return(RM_CHILL);
640 }
641
642
643 /*
644 * ----------------------------------------------------
645 * @Name rmLightSetEnable
646 @pstart
647 RMenum rmLightSetEnable (RMlight *toModify,
648 RMenum newValue)
649 @pend
650
651 @astart
652 RMlight *toModify - a handle to an RMlight object (modified).
653
654 RMenum newValue - an RMenum value, must be either RM_TRUE or
655 RM_FALSE.
656 @aend
657
658 @dstart
659
660 Light sources may be individually turned on or off by using this
661 routine. To turn a light on, use RM_TRUE, and to turn it off, use
662 RM_FALSE.
663
664 Upon success, the newValue attribute is copied into the RMlight
665 object, and RM_CHILL is returned, otherwise RM_WHACKED is returned.
666
667 Note that setting attributes in an RMlight does not change them in
668 the scene graph. They must be assigned as scene parameters to an
669 RMnode before they will be used in rendering (see
670 rmNodeSetSceneLight).
671
672 @dend
673 * ----------------------------------------------------
674 */
675 RMenum
rmLightSetEnable(RMlight * t,RMenum newValue)676 rmLightSetEnable (RMlight *t,
677 RMenum newValue)
678 {
679 if (RM_ASSERT(t, "rmLightSetEnable() error: the input RMlight pointer is NULL.") == RM_WHACKED)
680 return(RM_WHACKED);
681
682 if (newValue == RM_TRUE || newValue == RM_FALSE)
683 t->enabled = newValue;
684 else
685 {
686 rmError("rmLightSetEnable() error: the input newValue enumerator is niether RM_TRUE nor RM_FALSE.");
687 return(RM_WHACKED);
688 }
689 return(RM_CHILL);
690 }
691
692
693 /*
694 * ----------------------------------------------------
695 * @Name rmLightGetEnable
696 @pstart
697 RMenum rmLightGetEnable (const RMlight *toQuery)
698 @pend
699
700 @astart
701 const RMlight *toQuery - a handle to an RMlight object (input).
702 @aend
703
704 @dstart
705
706 Upon success, returns to the caller either RM_TRUE or RM_FALSE,
707 indicating that the light source is either turned on or turned off,
708 respectively. Otherwise, returns RM_WHACKED.
709
710 @dend
711 * ----------------------------------------------------
712 */
713 RMenum
rmLightGetEnable(const RMlight * t)714 rmLightGetEnable (const RMlight *t)
715 {
716 if (RM_ASSERT(t, "rmLightGetEnable() error: the input RMlight object is NULL.") == RM_WHACKED)
717 return(RM_WHACKED);
718
719 return(t->enabled);
720 }
721
722
723 /*
724 * ----------------------------------------------------
725 * @Name rmLightSetSpotDirection
726 @pstart
727 RMenum rmLightSetSpotDirection (RMlight *toModify,
728 const RMvertex3D *newSpotDirection)
729 @pend
730
731 @astart
732 RMlight *toModify - a handle to an RMlight object (modified).
733
734 const RMvertex3D *newSpotDirection - a handle to an RMvertex3D object
735 (input).
736 @aend
737
738 @dstart
739
740 Spotlight geometry is specified with both a position (rmLightSetXYZ)
741 and a direction (rmLightSetSpotDirection). This routine is used to
742 set the 3D orientation, or direction, of the spotlight light source.
743
744 Upon success, this routine will copy the 3D vector from the
745 caller-supplied RMvertex3D object into the RMlight object and return
746 RM_CHILL. Upon failure, RM_WHACKED is returned.
747
748 Note that setting attributes in an RMlight does not change them in
749 the scene graph. They must be assigned as scene parameters to an
750 RMnode before they will be used in rendering (see
751 rmNodeSetSceneLight).
752
753 @dend
754 * ----------------------------------------------------
755 */
756 RMenum
rmLightSetSpotDirection(RMlight * t,const RMvertex3D * newSpotDirection)757 rmLightSetSpotDirection (RMlight *t,
758 const RMvertex3D *newSpotDirection)
759 {
760 if ((RM_ASSERT(t, "rmLightSetSpotDirection() error: the input RMlight is NULL") == RM_WHACKED) ||
761 (RM_ASSERT(newSpotDirection, "rmLightSetSpotDirection() error: the input newSpotDirection pointer is NULL") == RM_WHACKED))
762 return(RM_WHACKED);
763
764 t->spotDirection = *newSpotDirection;
765
766 return(RM_CHILL);
767 }
768
769
770 /*
771 * ----------------------------------------------------
772 * @Name rmLightGetSpotDirection
773 @pstart
774 RMenum rmLightGetSpotDirection (const RMlight *toModify,
775 RMvertex3D *retDirection)
776 @pend
777
778 @astart
779 const RMlight *toModify - a handle to an RMlight object (input).
780
781 RMvertex3D *retDirection - a handle to an RMvertex3D object
782 (modified, return).
783 @aend
784
785 @dstart
786
787 Spotlights are specified with both a position (rmLightSetXYZ) and a
788 direction (rmLightSetSpotDirection). Use this routine to obtain the
789 direction vector of a spotlight source.
790
791 Upon success, this routine copies the spotlight direction vector from
792 the RMlight object into the caller-supplied memory and returns
793 RM_CHILL. Upon failure, RM_WHACKED is returned.
794
795 @dend
796 * ----------------------------------------------------
797 */
798 RMenum
rmLightGetSpotDirection(const RMlight * t,RMvertex3D * retDirection)799 rmLightGetSpotDirection (const RMlight *t,
800 RMvertex3D *retDirection)
801 {
802 if ((RM_ASSERT(t, "rmLightGetSpotDirection() error: the input RMlight is NULL") == RM_WHACKED) ||
803 (RM_ASSERT(retDirection, "rmLightGetSpotDirection() error: the input retDirection pointer is NULL") == RM_WHACKED))
804 return(RM_WHACKED);
805
806 *retDirection = t->spotDirection;
807
808 return(RM_CHILL);
809 }
810
811
812 /*
813 * ----------------------------------------------------
814 * @Name rmLightSetSpotCutoff
815 @pstart
816 RMenum rmLightSetSpotCutoff (RMlight *toModify,
817 float newValue)
818 @pend
819
820 @astart
821 RMlight *toModify - a handle to an RMlight object (modified).
822
823 float newValue - a floating point value in the range [0..90] (or the
824 special value of 180) specifying the spread angle of the
825 spotlight (input).
826 @aend
827
828 @dstart
829
830 The spotlight light source consists of a number of
831 parameters. Spotlight position is it's location in 3-space
832 (rmLightSetXYZ). The direction in which the spotlight is pointed is
833 it's orientation (rmLightSetSpotDirection). The light color consists
834 of ambient, diffuse and specular colors (rmLightSetColor). The rate
835 at which light decays as a function of distance from the light source
836 position is specified with constant, linear and quadratic
837 coefficients (rmLightSetAttenuation). The spread angle of the
838 spotlight is a measure of the half-angle, in degrees, of the apex of
839 a cone formed by the spotlight, with the light positioned at the apex
840 of the cone and oriented towards the base of the cone
841 (rmLightSetSpotCutoff). Finally, the rate at which light decays, or
842 falls off, as a function of distance from the vector formed by the
843 center of the spotlight cone (rmLightSetSpotExponent).
844
845 This routine is used to set the value that controls the spread angle
846 of the spotlight light source. The value must be in the range 0 to
847 90, or the special value 180. This value specifies the half-angle of
848 the cone apex formed by the illumination volume of the spotlight
849 source. The spotlight source is positioned at the apex of this cone,
850 and shines in the direction of the base of the cone. The greater this
851 value, the larger the illumination volume. A value of 45 (degrees)
852 specifies an illumination volume with a cone apex of 90 degrees.
853
854 The special value of 180.0 specifies a spotlight source that shines
855 in all directions.
856
857 Upon success, the spotlight cutoff attribute of the RMlight object is
858 modified, and RM_CHILL is returned to the caller. Otherwise,
859 RM_WHACKED is returned.
860
861 Note that setting attributes in an RMlight does not change them in
862 the scene graph. They must be assigned as scene parameters to an
863 RMnode before they will be used in rendering (see
864 rmNodeSetSceneLight).
865
866 @dend
867 * ----------------------------------------------------
868 */
869 RMenum
rmLightSetSpotCutoff(RMlight * t,float newValue)870 rmLightSetSpotCutoff (RMlight *t,
871 float newValue)
872 {
873 if (RM_ASSERT(t, "rmLightSetSpotCutoff() error: the input RMlight is NULL") == RM_WHACKED)
874 return(RM_WHACKED);
875
876 t->spotCutoff = newValue;
877
878 return(RM_CHILL);
879 }
880
881
882 /*
883 * ----------------------------------------------------
884 * @Name rmLightGetSpotCutoff
885 @pstart
886 RMenum rmLightGetSpotCutoff (const RMlight *toQuery,
887 float *retValue)
888 @pend
889
890 @astart
891 const RMlight *toQuery - a handle to an RMlight object (input).
892
893 float *retValue - a handle to a caller-supplied float (modified).
894 @aend
895
896 @dstart
897
898 Use this routine to obtain the spotlight cutoff value from an RMlight
899 object. Upon success, the spotlight cutoff value is copied into the
900 caller-supplied memory and RM_CHILL is returned. Otherwise,
901 RM_WHACKED is returned.
902
903 See rmLightSetSpotCutoff for more details about the meaning of the
904 spotlight cutoff attribute.
905
906 @dend
907 * ----------------------------------------------------
908 */
909 RMenum
rmLightGetSpotCutoff(const RMlight * t,float * retValue)910 rmLightGetSpotCutoff (const RMlight *t,
911 float *retValue)
912 {
913 if ((RM_ASSERT(t, "rmLightGetSpotCutoff() error: the input RMlight is NULL") == RM_WHACKED) ||
914 (RM_ASSERT(retValue, "rmLightSetSpotCutoff() error: the return float pointer is NULL") == RM_WHACKED))
915 return(RM_WHACKED);
916
917 *retValue = t->spotCutoff;
918
919 return(RM_CHILL);
920 }
921
922
923 /*
924 * ----------------------------------------------------
925 * @Name rmLightSetSpotExponent
926 @pstart
927 RMenum rmLightSetSpotExponent (RMlight *toModify,
928 float newValue)
929 @pend
930
931 @astart
932 RMlight *toModify - a handle to an RMlight object (modified).
933
934 float newValue - a non-negative floating point value (input).
935 @aend
936
937 @dstart
938
939 The spotlight light source consists of a number of
940 parameters. Spotlight position is it's location in 3-space
941 (rmLightSetXYZ). The direction in which the spotlight is pointed is
942 it's orientation (rmLightSetSpotDirection). The light color consists
943 of ambient, diffuse and specular colors (rmLightSetColor). The rate
944 at which light decays as a function of distance from the light source
945 position is specified with constant, linear and quadratic
946 coefficients (rmLightSetAttenuation). The spread angle of the
947 spotlight is a measure of the half-angle, in degrees, of the apex of
948 a cone formed by the spotlight, with the light positioned at the apex
949 of the cone and oriented towards the base of the cone
950 (rmLightSetSpotCutoff). Finally, the rate at which light decays, or
951 falls off, as a function of distance from the vector formed by the
952 center of the spotlight cone (rmLightSetSpotExponent).
953
954 This routine is used to set the spotlight exponent value, or the rate
955 at which light decays as a function of distance from the center of
956 the illumination cone. By default, this parameter is set to zero,
957 indicating uniform light distribution (no decay) within the
958 illumination cone. Since this attribute specifies an exponent, light
959 decay falls off more rapidly as the value for this parameter
960 increases. Linear decay (inverse distance) is specified using a value
961 of 1.0 for this parameter; a value of 2.0 specifies that light falls
962 off as the inverse of the square of the distance to the center of the
963 illumination cone.
964
965 Upon success, this routine copies the caller-supplied newValue
966 floating point value into the RMlight object's spotlight exponent
967 attribute and returns RM_CHILL, otherwise RM_WHACKED is returned.
968
969 Note that setting attributes in an RMlight does not change them in
970 the scene graph. They must be assigned as scene parameters to an
971 RMnode before they will be used in rendering (see
972 rmNodeSetSceneLight).
973
974 @dend
975 * ----------------------------------------------------
976 */
977 RMenum
rmLightSetSpotExponent(RMlight * t,float newValue)978 rmLightSetSpotExponent (RMlight *t,
979 float newValue)
980 {
981 if (RM_ASSERT(t, "rmLightSetSpotExponent() error: the input RMlight is NULL") == RM_WHACKED)
982 return(RM_WHACKED);
983
984 t->spotExponent = newValue;
985
986 return(RM_CHILL);
987 }
988
989
990 /*
991 * ----------------------------------------------------
992 * @Name rmLightGetSpotExponent
993 @pstart
994 RMenum rmLightGetSpotExponent (const RMlight *toQuery,
995 float *retValue)
996 @pend
997
998 @astart
999 const RMlight *toQuery - a handle to an RMlight object (input).
1000
1001 float *retValue - a handle to a caller-supplied float (modified).
1002 @aend
1003
1004 @dstart
1005
1006 Use this routine to obtain the spotlight exponent attribute of an
1007 RMlight object. Upon success, the spotlight exponent attribute of the
1008 RMlight object is copied into caller-supplied memory, and RM_CHILL is
1009 returned. Otherwise, RM_WHACKED is returned.
1010
1011 See rmLightSetSpotExponent for more details about the meaning and use
1012 of this attribute.
1013
1014 @dend
1015 * ----------------------------------------------------
1016 */
1017 RMenum
rmLightGetSpotExponent(const RMlight * t,float * retValue)1018 rmLightGetSpotExponent (const RMlight *t,
1019 float *retValue)
1020 {
1021 if ((RM_ASSERT(t, "rmLightGetSpotExponent() error: the input RMlight is NULL") == RM_WHACKED) ||
1022 (RM_ASSERT(retValue, "rmLightSetSpotExponent() error: the return float pointer is NULL") == RM_WHACKED))
1023 return(RM_WHACKED);
1024
1025 *retValue = t->spotExponent;
1026
1027 return(RM_CHILL);
1028 }
1029
1030
1031 /*
1032 * ----------------------------------------------------
1033 * @Name rmLightModelNew
1034 @pstart
1035 RMlightModel * rmLightModelNew (void)
1036 @pend
1037
1038 @astart
1039 No arguments.
1040 @aend
1041
1042 @dstart
1043
1044 Creates a new RMlightModel object, initializes it with default
1045 values, and returns to handle to the caller. NULL is returned upon
1046 failure.
1047
1048 Lighting in RM (and OpenGL) is a function of light sources and the
1049 lighting environment. The RMlight objects contain information about
1050 the specific light sources, such as their position, light decay
1051 properties, color and so forth. The RMlightModel object controls
1052 global lighting parameters, including global ambient illumination,
1053 two-sided illumination control and selection of one of two algorithms
1054 used to compute specular reflection values.
1055
1056 Global ambient illumination is the amount of light that is present
1057 everywhere in the scene, and represents the combination of overall
1058 composite luminance with the degree to which light is scattered. By
1059 default, the ambient color assigned to the RMlightModel object is
1060 {0.,0.,0.}, indicating the absence of global ambient light. During
1061 shading, the global ambient term is applied to all vertices,
1062 regardless of the amount of ambient light specified in an RMlight
1063 object. This term can be thought of as another independent light
1064 source in the scene (see rmLightModelSetAmbient).
1065
1066 Two-sided illumination is used to create the effect of a
1067 bi-directional light source. By default, two-sided lighting is turned
1068 off (see rmLightModelSetTwoSided).
1069
1070 Specular reflections take into account the surface normal, the
1071 direction to the light source from a vertex, and the direction to the
1072 viewer from the vertex. When the "local viewer" attribute is set to
1073 RM_TRUE, the direction to the viewer from each vertex is calculated
1074 during shading. This results in more realistic shading, but at added
1075 computational expense. When set to RM_FALSE, the position of the
1076 viewer is fixed at (0,0,0) in eye coordinates (not world
1077 coordinates) for the purposes of shading.
1078
1079 Note: OpenGL 1.2 adds a new term to the lighting model that can be
1080 used to control the computation specular reflection color. This
1081 feature has not yet been integrated into RM.
1082
1083 Applications need to create both a light source and a light model in
1084 order for lighting to work properly.
1085
1086 @dend
1087 * ----------------------------------------------------
1088 */
1089 RMlightModel *
rmLightModelNew(void)1090 rmLightModelNew (void)
1091 {
1092 RMlightModel *t;
1093
1094 t = (RMlightModel *)malloc(sizeof(RMlightModel));
1095
1096 if (t == NULL)
1097 {
1098 rmError("rmLightModelNew() error: unable to malloc a new RMlightModel object. ");
1099 return(NULL);
1100 }
1101
1102 memset(t, 0, sizeof(RMlightModel));
1103
1104 /* default ambient is (0,0,0,0) */
1105 t->twoSideEnable = RM_FALSE;
1106 t->localViewerEnable = RM_FALSE;
1107
1108 return(t);
1109 }
1110
1111
1112 /*
1113 * ----------------------------------------------------
1114 * @Name rmLightModelDelete
1115 @pstart
1116 RMenum rmLightModelDelete (RMlightModel *toDelete)
1117 @pend
1118
1119 @astart
1120 RMlightModel *toDelete - a handle to an RMlightModel object to be
1121 deleted (modified).
1122 @aend
1123
1124 @dstart
1125
1126 Releases resources associated with an RMlightModel object. Returns
1127 RM_CHILL upon success, or RM_WHACKED upon failure. This routine is
1128 the opposite of rmLightModelNew.
1129
1130 @dend
1131 * ----------------------------------------------------
1132 */
1133 RMenum
rmLightModelDelete(RMlightModel * toDelete)1134 rmLightModelDelete (RMlightModel *toDelete)
1135 {
1136 if (RM_ASSERT(toDelete, "rmLightModelDelete() error: the input RMlightModel pointer is NULL") == RM_WHACKED)
1137 return(RM_WHACKED);
1138
1139 free((void *)toDelete);
1140
1141 return(RM_CHILL);
1142 }
1143
1144
1145 /*
1146 * ----------------------------------------------------
1147 * @Name rmLightModelSetAmbient
1148 @pstart
1149 RMenum rmLightModelSetAmbient (RMlightModel *toModify,
1150 const RMcolor4D *newAmbientColor)
1151 @pend
1152
1153 @astart
1154 RMlightModel *toModify - a handle to an RMlightModel object (modified).
1155
1156 const RMcolor4D *newAmbientColor - a handle to an RMcolor4D object
1157 (input).
1158 @aend
1159
1160 @dstart
1161
1162 Upon success, copies the contents of the RMcolor4D object to the
1163 RMlightModel object, and returns RM_CHILL. Otherwise, RM_WHACKED is
1164 returned.
1165
1166 Color attributes are specified with floating point values in the
1167 range 0..1, where 0 is "off" and 1 is "on." The RMcolor4D object
1168 represents red, green, blue and alpha.
1169
1170 See rmLightModelNew for more information about the global ambient
1171 light model attribute.
1172
1173 Note that setting attributes in an RMlightModel does not change them
1174 in the scene graph. They must be assigned as scene parameters to an
1175 RMnode before they will be used in rendering (see
1176 rmNodeSetSceneLightModel).
1177
1178 @dend
1179 * ----------------------------------------------------
1180 */
1181 RMenum
rmLightModelSetAmbient(RMlightModel * toModify,const RMcolor4D * newAmbientColor)1182 rmLightModelSetAmbient (RMlightModel *toModify,
1183 const RMcolor4D *newAmbientColor)
1184 {
1185 if ((RM_ASSERT(toModify, "rmLightModelSetAmbient() error: the input RMlightModel pointer is NULL") == RM_WHACKED) ||
1186 (RM_ASSERT(newAmbientColor, "rmLightModelSetAmbient() error: the input newAmbientColor pointer is NULL") == RM_WHACKED))
1187 return(RM_WHACKED);
1188
1189 toModify->globalAmbient = *newAmbientColor;
1190
1191 return(RM_CHILL);
1192 }
1193
1194
1195 /*
1196 * ----------------------------------------------------
1197 * @Name rmLightModelGetAmbient
1198 @pstart
1199 RMenum rmLightModelGetAmbient (const RMlightModel *toQuery,
1200 RMcolor4D *retAmbientColor)
1201 @pend
1202
1203 @astart
1204 const RMlightModel *toQuery - a handle to an RMlightModel object
1205 (input).
1206
1207 RMcolor4D *retAmbientColor - a handle to an RMcolor4D object
1208 (modified).
1209 @aend
1210
1211 @dstart
1212
1213 Upon success, this routine will copy the global ambient light
1214 attribute from the RMlightModel object into the caller-supplied
1215 RMcolor4D object, and return RM_CHILL. Otherwise, RM_WHACKED is
1216 returned.
1217
1218 See rmLightModelNew for more information about the global ambient
1219 light model attribute.
1220
1221 @dend
1222 * ----------------------------------------------------
1223 */
1224 RMenum
rmLightModelGetAmbient(const RMlightModel * toQuery,RMcolor4D * retAmbientColor)1225 rmLightModelGetAmbient (const RMlightModel *toQuery,
1226 RMcolor4D *retAmbientColor)
1227 {
1228 if ((RM_ASSERT(toQuery, "rmLightModelGetAmbient() error: the input RMlightModel pointer is NULL") == RM_WHACKED) ||
1229 (RM_ASSERT(retAmbientColor, "rmLightModelGetAmbient() error: the input retAmbientColor pointer is NULL") == RM_WHACKED))
1230 return(RM_WHACKED);
1231
1232 *retAmbientColor = toQuery->globalAmbient;
1233
1234 return(RM_CHILL);
1235 }
1236
1237
1238 /*
1239 * ----------------------------------------------------
1240 * @Name rmLightModelSetTwoSided
1241 @pstart
1242 RMenum rmLightModelSetTwoSided (RMlightModel *toModify,
1243 RMenum newValue)
1244 @pend
1245
1246 @astart
1247 RMlightModel *toModify - a handle to an RMlightModel object
1248 (modified).
1249
1250 RMenum newValue - an RMenum value, should be either RM_TRUE or
1251 RM_FALSE (input).
1252 @aend
1253
1254 @dstart
1255
1256 This routine sets the two-sided lighting attribute of an RMlightModel
1257 object. When RM_TRUE is specified, two-sided lighting is activitated
1258 for this light model. When set to RM_FALSE, two-sided lighting is
1259 disabled, and single-sided lighting takes effect.
1260
1261 Returns RM_CHILL upon success, or RM_WHACKED upon failure.
1262
1263 Note that setting attributes in an RMlightModel does not change them
1264 in the scene graph. They must be assigned as scene parameters to an
1265 RMnode before they will be used in rendering (see
1266 rmNodeSetSceneLightModel).
1267
1268 @dend
1269 * ----------------------------------------------------
1270 */
1271 RMenum
rmLightModelSetTwoSided(RMlightModel * toModify,RMenum newValue)1272 rmLightModelSetTwoSided (RMlightModel *toModify,
1273 RMenum newValue)
1274 {
1275 if (RM_ASSERT(toModify, "rmLightModelSetTwoSided() error: the input RMlightModel pointer is NULL") == RM_WHACKED)
1276 return(RM_WHACKED);
1277
1278 if (newValue == RM_TRUE || newValue == RM_FALSE)
1279 toModify->twoSideEnable = newValue;
1280 else
1281 {
1282 rmWarning("rmLightModelTwoSided warning: the input RMenum is neither RM_TRUE nor RM_FALSE");
1283 return(RM_WHACKED);
1284 }
1285
1286 return(RM_CHILL);
1287 }
1288
1289
1290 /*
1291 * ----------------------------------------------------
1292 * @Name rmLightModelGetTwoSided
1293 @pstart
1294 RMenum rmLightModelGetTwoSided (const RMlightModel *toQuery)
1295 @pend
1296
1297 @astart
1298 const RMlightModel *toQuery - a handle to an RMlightModel object
1299 (input).
1300 @aend
1301
1302 @dstart
1303
1304 Upon success, returns the setting of the two-sided lighting attribute
1305 of an RMlightModel object, either RM_TRUE or RM_FALSE. Otherwise,
1306 RM_WHACKED is returned.
1307
1308 @dend
1309 * ----------------------------------------------------
1310 */
1311 RMenum
rmLightModelGetTwoSided(const RMlightModel * toQuery)1312 rmLightModelGetTwoSided (const RMlightModel *toQuery)
1313 {
1314 if (RM_ASSERT(toQuery, "rmLightModelGetTwoSided() error: the input RMlightModel pointer is NULL") == RM_WHACKED)
1315 return(RM_WHACKED);
1316
1317 return((RMenum)toQuery->twoSideEnable);
1318 }
1319
1320
1321 /*
1322 * ----------------------------------------------------
1323 * @Name rmLightModelSetLocalViewer
1324 @pstart
1325 RMenum rmLightModelSetLocalViewer (RMlightModel *toModify,
1326 RMenum newValue)
1327 @pend
1328
1329 @astart
1330 RMlightModel *toModify - a handle to an RMlightModel object
1331 (modified).
1332
1333 RMenum newValue - an RMenum value, must be either RM_TRUE or RM_FALSE
1334 (input).
1335 @aend
1336
1337 @dstart
1338
1339 This routine will set the "local viewer" attribute of the
1340 RMlightModel object to the value specified by the caller and return
1341 RM_CHILL upon success. Otherwise, RM_WHACKED is returned.
1342
1343 See rmLightModelNew for more information about the "local viewer"
1344 attribute.
1345
1346 Note that setting attributes in an RMlightModel does not change them
1347 in the scene graph. They must be assigned as scene parameters to an
1348 RMnode before they will be used in rendering (see
1349 rmNodeSetSceneLightModel).
1350
1351 @dend
1352 * ----------------------------------------------------
1353 */
1354 RMenum
rmLightModelSetLocalViewer(RMlightModel * toModify,RMenum newValue)1355 rmLightModelSetLocalViewer (RMlightModel *toModify,
1356 RMenum newValue)
1357 {
1358 if (RM_ASSERT(toModify, "rmLightModelSetLocalViewer() error: the input RMlightModel pointer is NULL") == RM_WHACKED)
1359 return(RM_WHACKED);
1360
1361 if (newValue == RM_TRUE || newValue == RM_FALSE)
1362 toModify->localViewerEnable = newValue;
1363 else
1364 {
1365 rmError(" rmLightModelSetLocalViewer() error: the input enumerator is neither RM_TRUE nor RM_FALSE ");
1366 return(RM_WHACKED);
1367 }
1368
1369 return(RM_CHILL);
1370 }
1371
1372
1373 /*
1374 * ----------------------------------------------------
1375 * @Name rmLightModelGetLocalViewer
1376 @pstart
1377 RMenum rmLightModelGetLocalViewer (const RMlightModel *toQuery)
1378 @pend
1379
1380 @astart
1381 const RMlightModel *toQuery - a handle to an RMlightModel object
1382 (input).
1383 @aend
1384
1385 @dstart
1386
1387 Upon success, returns the "local viewer" attribute of the
1388 RMlightModel object. Otherwise, RM_WHACKED is returned.
1389
1390 See rmLightModelNew for more information about the "local viewer"
1391 attribute of the RMlightModel object.
1392
1393 @dend
1394 * ----------------------------------------------------
1395 */
1396 RMenum
rmLightModelGetLocalViewer(const RMlightModel * toQuery)1397 rmLightModelGetLocalViewer (const RMlightModel *toQuery)
1398 {
1399 if (RM_ASSERT(toQuery, "rmLightModelGetLocalViewer() error: the input RMlightModel pointer is NULL") == RM_WHACKED)
1400 return(RM_WHACKED);
1401
1402 return((RMenum)toQuery->localViewerEnable);
1403 }
1404
1405
1406 /*
1407 * ----------------------------------------------------
1408 * @Name rmDefaultLighting
1409 @pstart
1410 RMenum rmDefaultLighting (RMnode *toModify)
1411 @pend
1412
1413 @astart
1414 RMnode *toModify - a handle to an RMnode (modified).
1415 @aend
1416
1417 @dstart
1418
1419 This convenience routine is used to create a default set of lights
1420 and a default lighting model, and to assign them as scene parameters
1421 to an RMnode. The new lights and lighting model have effect over all
1422 children of the specified RMnode.
1423
1424 The default lighting configuration consists of:
1425
1426 1. One directional light source at 0,10,3 (overhead and slightly
1427 behind the viewer) with no ambient term, diffuse set to
1428 (0.7,0.7,0.7,1.0) and specular set to (0.5,0.5,0.5,1.0). A second
1429 light source is available by uncommenting one line of code inside
1430 this routine.
1431
1432 2. A light model with global ambient light set to (0.2,0.2,0.2,1.0),
1433 two-sided lighting disabled and disabling of "local viewer"
1434 specular reflection calculations.
1435
1436 The net result is a lighting model that works reasonably well for
1437 most scenes both in terms of performance as well as illumination
1438 characteristics. While this convenience function is useful,
1439 developers are encouraged to examine this routine because it is a
1440 good example of how to create and modify light sources and light
1441 models, as well as assign them as scene parameters to an RMnode.
1442
1443 Returns RM_CHILL upon success, or RM_WHACKED upon failure.
1444
1445 @dend
1446 * ----------------------------------------------------
1447 */
1448 RMenum
rmDefaultLighting(RMnode * n)1449 rmDefaultLighting (RMnode *n)
1450 {
1451 /* light source zero is a from-the-top directional light */
1452 RMlight *l0, *l1;
1453 RMcolor4D diffuse = {0.7, 0.7, 0.7, 1.0};
1454 RMcolor4D specular = {0.5, 0.5, 0.5, 1.0};
1455 RMcolor4D diffuse2 = {0.3, 0.3, 0.5, 1.0};
1456 RMvertex3D pos2 = {0.0, -3.0, 1.0};
1457 RMvertex3D position = {0.0, 10.0, 3.0};
1458
1459 l0 = rmLightNew();
1460 if (l0 == NULL)
1461 return(RM_WHACKED);
1462
1463 rmLightSetType(l0, RM_LIGHT_DIRECTIONAL);
1464 rmLightSetColor(l0, NULL, &diffuse, &specular);
1465 rmLightSetXYZ (l0, &position);
1466
1467 /*
1468 * light source one is a from-the-bottom directional light with
1469 * reduced emphasis on diffuse and specular. the more dim
1470 * diffuse light is kind of blue.
1471 */
1472 l1 = rmLightNew();
1473 if (l1 == NULL)
1474 return(RM_WHACKED);
1475
1476 rmLightSetType(l1, RM_LIGHT_DIRECTIONAL);
1477 rmLightSetColor(l1, NULL, &diffuse2, &specular);
1478 rmLightSetXYZ(l1, &pos2);
1479
1480 rmNodeSetSceneLight(n, RM_LIGHT0, l0);
1481 /*
1482 * uncomment the following line to add the second light source
1483 * into the scene. we leave it out by default for performance reasons,
1484 * but having it readily available for experimentation has proven useful.
1485 *
1486 * rmNodeSetSceneLight(n, RM_LIGHT1, l1);
1487 */
1488
1489 /*
1490 * when the lights are added as scene parameters, RM makes a copy
1491 * of them, and we don't need our RMlight objects anymore, so we
1492 * need to delete them.
1493 */
1494
1495 rmLightDelete(l0);
1496 rmLightDelete(l1);
1497
1498 /* set up the light model/lighting environment */
1499 {
1500 RMcolor4D defAmbient = {0.2, 0.2, 0.2, 1.0};
1501 RMlightModel *lm = rmLightModelNew();
1502
1503 if (lm == NULL)
1504 return(RM_WHACKED);
1505
1506 rmLightModelSetAmbient(lm, &defAmbient);
1507 rmLightModelSetTwoSided (lm, RM_FALSE);
1508 /* rmLightModelSetLocalViewer(lm, RM_TRUE); */
1509 rmLightModelSetLocalViewer(lm, RM_FALSE);
1510 rmNodeSetSceneLightModel(n, lm);
1511
1512 rmLightModelDelete (lm);
1513 }
1514 return(RM_CHILL);
1515 }
1516 /* EOF */
1517