Update contrib.
2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of the License "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
14 * Description: Light implementation
22 * \brief Light implementation
25 #ifndef M3G_CORE_INCLUDE
26 # error included by m3g_core.c; do not compile separately.
29 #include "m3g_light.h"
30 #include "m3g_animationtrack.h"
32 /*----------------------------------------------------------------------
34 *--------------------------------------------------------------------*/
38 * \brief Overloaded Node method.
40 * Insert light to render queue.
42 * \param self Light object
43 * \param toCamera transform to camera
44 * \param alphaFactor total alpha factor
45 * \param caller caller node
46 * \param renderQueue RenderQueue
48 * \retval M3G_TRUE continue render setup
49 * \retval M3G_FALSE abort render setup
51 static M3Gbool m3gLightSetupRender(Node *self,
54 RenderQueue *renderQueue)
58 if (renderQueue->lightManager != NULL) {
59 Light *light = (Light *)self;
61 if (self->enableBits & NODE_RENDER_BIT) {
62 if (m3gInsertLight(renderQueue->lightManager,
63 light, &s->toCamera, M3G_INTERFACE(light)) == -1)
73 * \brief Overloaded Object3D method.
75 * \param property animation property
76 * \retval M3G_TRUE property supported
77 * \retval M3G_FALSE property not supported
79 static M3Gbool m3gLightIsCompatible(M3Gint property)
83 case M3G_ANIM_INTENSITY:
84 case M3G_ANIM_SPOT_ANGLE:
85 case M3G_ANIM_SPOT_EXPONENT:
88 return m3gNodeIsCompatible(property);
94 * \brief Overloaded Object3D method.
96 * \param self Light object
97 * \param property animation property
98 * \param valueSize size of value array
99 * \param value value array
101 static void m3gLightUpdateProperty(Object *self,
104 const M3Gfloat *value)
106 Light *light = (Light *)self;
107 M3G_VALIDATE_OBJECT(light);
108 M3G_ASSERT_PTR(value);
112 M3G_ASSERT(valueSize >= 3);
113 light->color = m3gColor3f(value[0], value[1], value[2]);
115 case M3G_ANIM_INTENSITY:
116 M3G_ASSERT(valueSize >= 1);
117 light->intensity = value[0];
119 case M3G_ANIM_SPOT_ANGLE:
120 M3G_ASSERT(valueSize >= 1);
121 light->spotAngle = m3gClampFloat(value[0], 0.f, 90.f);
123 case M3G_ANIM_SPOT_EXPONENT:
124 M3G_ASSERT(valueSize >= 1);
125 light->spotExponent = m3gClampFloat(value[0], 0.f, 128.f);
128 m3gNodeUpdateProperty(self, property, valueSize, value);
134 * \brief Overloaded Object3D method.
136 * \param originalObj original Light object
137 * \param cloneObj pointer to cloned Light object
138 * \param pairs array for all object-duplicate pairs
139 * \param numPairs number of pairs
141 static M3Gbool m3gLightDuplicate(const Object *originalObj,
146 const Light *original = (const Light *) originalObj;
148 M3G_ASSERT(*cloneObj == NULL); /* no derived classes for light */
150 /* Create the clone object and exit on failure */
152 clone = (Light *)m3gCreateLight(originalObj->interface);
156 *cloneObj = (Object *)clone;
158 /* Duplicate base class data */
160 if (!m3gNodeDuplicate(originalObj, cloneObj, pairs, numPairs)) {
164 /* Duplicate own data */
166 clone->constantAttenuation = original->constantAttenuation;
167 clone->linearAttenuation = original->linearAttenuation;
168 clone->quadraticAttenuation = original->quadraticAttenuation;
169 clone->intensity = original->intensity;
170 clone->color = original->color;
171 clone->mode = original->mode;
172 clone->spotAngle = original->spotAngle;
173 clone->spotExponent = original->spotExponent;
180 * \brief Initializes a Light object. See specification
181 * for default values.
183 * \param m3g M3G interface
184 * \param light Light object
186 static void m3gInitLight(Interface *m3g, Light *light)
188 /* Light is derived from node */
189 m3gInitNode(m3g, &light->node, M3G_CLASS_LIGHT);
191 light->constantAttenuation = 1.0f;
192 light->intensity = 1.0f;
193 light->color = 0x00ffffff; /* Full white */
194 light->mode = M3G_DIRECTIONAL;
195 light->spotAngle = 45.0f;
200 * \brief Applies this light to the current OpenGL context.
202 * \param self Light object
203 * \param glLight OpenGL light index
204 * \param pos light position
205 * \param spotDir light direction
207 static void m3gApplyLight(const Light *self,
212 static const M3Gfloat BLACK[] = { 0.0f, 0.0f, 0.0f, 0.0f };
215 M3G_ASSERT(m3gInRange(glLight, GL_LIGHT0, GL_LIGHT7));
218 m3gFloatColor(self->color, self->intensity, light);
220 /* Set light position */
222 if (self->mode == M3G_DIRECTIONAL) {
224 temp[0] = -spotDir->x;
225 temp[1] = -spotDir->y;
226 temp[2] = -spotDir->z;
228 glLightfv(glLight, GL_POSITION, temp);
231 glLightfv(glLight, GL_POSITION, &pos->x);
232 if (self->mode == M3G_SPOT) {
233 glLightfv(glLight, GL_SPOT_DIRECTION, &spotDir->x);
237 /* Set ambient, diffuse, and specular contributions */
239 if (self->mode == M3G_AMBIENT) {
240 glLightfv(glLight, GL_AMBIENT, light);
241 glLightfv(glLight, GL_DIFFUSE, BLACK);
242 glLightfv(glLight, GL_SPECULAR, BLACK);
245 glLightfv(glLight, GL_AMBIENT, BLACK);
246 glLightfv(glLight, GL_DIFFUSE, light);
247 glLightfv(glLight, GL_SPECULAR, light);
250 /* Set spot parameters */
252 if (self->mode == M3G_SPOT) {
253 glLightf(glLight, GL_SPOT_EXPONENT, self->spotExponent);
254 glLightf(glLight, GL_SPOT_CUTOFF, self->spotAngle);
257 glLightf(glLight, GL_SPOT_CUTOFF, 180.0f);
260 /* Set attenuation */
262 if (self->mode == M3G_OMNI || self->mode == M3G_SPOT) {
263 glLightf(glLight, GL_CONSTANT_ATTENUATION, self->constantAttenuation);
264 glLightf(glLight, GL_LINEAR_ATTENUATION, self->linearAttenuation);
265 glLightf(glLight, GL_QUADRATIC_ATTENUATION, self->quadraticAttenuation);
267 else if (self->mode == M3G_AMBIENT) {
268 glLightf(glLight, GL_CONSTANT_ATTENUATION, 1.0f);
269 glLightf(glLight, GL_LINEAR_ATTENUATION, 0.0f);
270 glLightf(glLight, GL_QUADRATIC_ATTENUATION, 0.0f);
274 /*----------------------------------------------------------------------
275 * Virtual function table
276 *--------------------------------------------------------------------*/
278 static const NodeVFTable m3gvf_Light = {
281 m3gObjectApplyAnimation,
282 m3gLightIsCompatible,
283 m3gLightUpdateProperty,
284 m3gObjectDoGetReferences,
291 NULL, /* pure virtual DoRender */
295 m3gNodeUpdateDuplicateReferences,
300 /*----------------------------------------------------------------------
301 * Public API functions
302 *--------------------------------------------------------------------*/
305 * \brief Creates a Light object.
307 * \param interface M3G interface
308 * \retval Light new Light object
309 * \retval NULL Light creating failed
311 M3G_API M3GLight m3gCreateLight(M3GInterface interface)
313 Interface *m3g = (Interface *) interface;
314 M3G_VALIDATE_INTERFACE(m3g);
317 Light *light = m3gAllocZ(m3g, sizeof(Light));
320 m3gInitLight(m3g, light);
323 return (M3GLight) light;
328 * \brief Set light intensity.
330 * \param handle Light object
331 * \param intensity light intensity
333 M3G_API void m3gSetIntensity(M3GLight handle, M3Gfloat intensity)
335 Light *light = (Light *) handle;
336 M3G_VALIDATE_OBJECT(light);
338 light->intensity = intensity;
342 * \brief Set light color as RGB.
344 * \param handle Light object
345 * \param rgb light color as RGB
347 M3G_API void m3gSetLightColor(M3GLight handle, M3Guint rgb)
349 Light *light = (Light *) handle;
350 M3G_VALIDATE_OBJECT(light);
352 light->color = rgb & M3G_RGB_MASK;
356 * \brief Set light mode.
358 * \param handle Light object
359 * \param mode light mode
361 M3G_API void m3gSetLightMode(M3GLight handle, M3Gint mode)
363 Light *light = (Light *) handle;
364 M3G_VALIDATE_OBJECT(light);
366 if (mode < M3G_AMBIENT || mode > M3G_SPOT) {
367 m3gRaiseError(M3G_INTERFACE(light), M3G_INVALID_VALUE);
375 * \brief Set light spot angle.
377 * \param handle Light object
378 * \param angle spot angle
380 M3G_API void m3gSetSpotAngle(M3GLight handle, M3Gfloat angle)
382 Light *light = (Light *) handle;
383 M3G_VALIDATE_OBJECT(light);
385 if (angle < 0.0f || angle > 90.f) {
386 m3gRaiseError(M3G_INTERFACE(light), M3G_INVALID_VALUE);
390 light->spotAngle = angle;
394 * \brief Set light spot exponent.
396 * \param handle Light object
397 * \param exponent spot exponent
399 M3G_API void m3gSetSpotExponent(M3GLight handle, M3Gfloat exponent)
401 Light *light = (Light *) handle;
402 M3G_VALIDATE_OBJECT(light);
404 if (exponent < 0.0f || exponent > 128.0f) {
405 m3gRaiseError(M3G_INTERFACE(light), M3G_INVALID_VALUE);
409 light->spotExponent = exponent;
413 * \brief Set light attenuation factors.
415 * \param handle Light object
416 * \param constant constant attenuation
417 * \param linear linear attenuation
418 * \param quadratic quadratic attenuation
420 M3G_API void m3gSetAttenuation(M3GLight handle,
425 Light *light = (Light *) handle;
426 M3G_VALIDATE_OBJECT(light);
428 if (constant < 0.0f || linear < 0.0f || quadratic < 0.0f
429 || (constant == 0.0f && linear == 0.0f && quadratic == 0.0f)) {
430 m3gRaiseError(M3G_INTERFACE(light), M3G_INVALID_VALUE);
434 light->constantAttenuation = constant;
435 light->linearAttenuation = linear;
436 light->quadraticAttenuation = quadratic;
440 * \brief Get light intensity.
442 * \param handle Light object
443 * \return light intensity
445 M3G_API M3Gfloat m3gGetIntensity(M3GLight handle)
447 Light *light = (Light *) handle;
448 M3G_VALIDATE_OBJECT(light);
450 return light->intensity;
454 * \brief Get light color as RGB.
456 * \param handle Light object
457 * \return light color as RGB
459 M3G_API M3Guint m3gGetLightColor(M3GLight handle)
461 Light *light = (Light *) handle;
462 M3G_VALIDATE_OBJECT(light);
468 * \brief Get light mode.
470 * \param handle Light object
473 M3G_API M3Gint m3gGetLightMode(M3GLight handle)
475 Light *light = (Light *) handle;
476 M3G_VALIDATE_OBJECT(light);
482 * \brief Get light spot angle.
484 * \param handle Light object
485 * \return light spot angle
487 M3G_API M3Gfloat m3gGetSpotAngle(M3GLight handle)
489 Light *light = (Light *) handle;
490 M3G_VALIDATE_OBJECT(light);
492 return light->spotAngle;
496 * \brief Get light spot exponent.
498 * \param handle Light object
499 * \return light spot exponent
501 M3G_API M3Gfloat m3gGetSpotExponent(M3GLight handle)
503 Light *light = (Light *) handle;
504 M3G_VALIDATE_OBJECT(light);
506 return light->spotExponent;
510 * \brief Get light attenuation factor.
512 * \param handle Light object
513 * \param type which factor to return
514 * \arg M3G_GET_CONSTANT
515 * \arg M3G_GET_LINEAR
516 * \arg M3G_GET_QUADRATIC
517 * \return light attenuation factor
519 M3G_API M3Gfloat m3gGetAttenuation(M3GLight handle, M3Gint type)
521 Light *light = (Light *) handle;
522 M3G_VALIDATE_OBJECT(light);
525 case M3G_GET_CONSTANT:
526 return light->constantAttenuation;
528 return light->linearAttenuation;
529 case M3G_GET_QUADRATIC:
531 return light->quadraticAttenuation;