os/graphics/m3g/m3gcore11/src/m3g_light.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of the License "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: Light implementation
sl@0
    15
*
sl@0
    16
*/
sl@0
    17
sl@0
    18
sl@0
    19
/*!
sl@0
    20
 * \internal
sl@0
    21
 * \file
sl@0
    22
 * \brief Light implementation
sl@0
    23
 */
sl@0
    24
sl@0
    25
#ifndef M3G_CORE_INCLUDE
sl@0
    26
#   error included by m3g_core.c; do not compile separately.
sl@0
    27
#endif
sl@0
    28
sl@0
    29
#include "m3g_light.h"
sl@0
    30
#include "m3g_animationtrack.h"
sl@0
    31
sl@0
    32
/*----------------------------------------------------------------------
sl@0
    33
 * Internal functions
sl@0
    34
 *--------------------------------------------------------------------*/
sl@0
    35
sl@0
    36
/*!
sl@0
    37
 * \internal
sl@0
    38
 * \brief Overloaded Node method.
sl@0
    39
 *
sl@0
    40
 * Insert light to render queue.
sl@0
    41
 *
sl@0
    42
 * \param self Light object
sl@0
    43
 * \param toCamera transform to camera
sl@0
    44
 * \param alphaFactor total alpha factor
sl@0
    45
 * \param caller caller node
sl@0
    46
 * \param renderQueue RenderQueue
sl@0
    47
 *
sl@0
    48
 * \retval M3G_TRUE continue render setup
sl@0
    49
 * \retval M3G_FALSE abort render setup
sl@0
    50
 */
sl@0
    51
static M3Gbool m3gLightSetupRender(Node *self,
sl@0
    52
                                   const Node *caller,
sl@0
    53
                                   SetupRenderState *s,
sl@0
    54
                                   RenderQueue *renderQueue)
sl@0
    55
{
sl@0
    56
    M3G_UNREF(caller);
sl@0
    57
sl@0
    58
    if (renderQueue->lightManager != NULL) {
sl@0
    59
        Light *light = (Light *)self;
sl@0
    60
        
sl@0
    61
        if (self->enableBits & NODE_RENDER_BIT) {
sl@0
    62
            if (m3gInsertLight(renderQueue->lightManager,
sl@0
    63
                               light, &s->toCamera, M3G_INTERFACE(light)) == -1)
sl@0
    64
                return M3G_FALSE;
sl@0
    65
        }
sl@0
    66
    }
sl@0
    67
sl@0
    68
    return M3G_TRUE;
sl@0
    69
}
sl@0
    70
sl@0
    71
/*!
sl@0
    72
 * \internal
sl@0
    73
 * \brief Overloaded Object3D method.
sl@0
    74
 *
sl@0
    75
 * \param property      animation property
sl@0
    76
 * \retval M3G_TRUE     property supported
sl@0
    77
 * \retval M3G_FALSE    property not supported
sl@0
    78
 */
sl@0
    79
static M3Gbool m3gLightIsCompatible(M3Gint property)
sl@0
    80
{
sl@0
    81
    switch (property) {
sl@0
    82
    case M3G_ANIM_COLOR:
sl@0
    83
    case M3G_ANIM_INTENSITY:
sl@0
    84
    case M3G_ANIM_SPOT_ANGLE:
sl@0
    85
    case M3G_ANIM_SPOT_EXPONENT:
sl@0
    86
        return M3G_TRUE;
sl@0
    87
    default:
sl@0
    88
        return m3gNodeIsCompatible(property);
sl@0
    89
    }
sl@0
    90
}
sl@0
    91
sl@0
    92
/*!
sl@0
    93
 * \internal
sl@0
    94
 * \brief Overloaded Object3D method.
sl@0
    95
 *
sl@0
    96
 * \param self          Light object
sl@0
    97
 * \param property      animation property
sl@0
    98
 * \param valueSize     size of value array
sl@0
    99
 * \param value         value array
sl@0
   100
 */
sl@0
   101
static void m3gLightUpdateProperty(Object *self,
sl@0
   102
                                   M3Gint property,
sl@0
   103
                                   M3Gint valueSize,
sl@0
   104
                                   const M3Gfloat *value)
sl@0
   105
{
sl@0
   106
    Light *light = (Light *)self;
sl@0
   107
    M3G_VALIDATE_OBJECT(light);
sl@0
   108
    M3G_ASSERT_PTR(value);
sl@0
   109
    
sl@0
   110
    switch (property) {
sl@0
   111
    case M3G_ANIM_COLOR:
sl@0
   112
        M3G_ASSERT(valueSize >= 3);
sl@0
   113
        light->color = m3gColor3f(value[0], value[1], value[2]);
sl@0
   114
        break;
sl@0
   115
    case M3G_ANIM_INTENSITY:
sl@0
   116
        M3G_ASSERT(valueSize >= 1);
sl@0
   117
        light->intensity = value[0];
sl@0
   118
        break;
sl@0
   119
    case M3G_ANIM_SPOT_ANGLE:
sl@0
   120
        M3G_ASSERT(valueSize >= 1);
sl@0
   121
        light->spotAngle = m3gClampFloat(value[0], 0.f, 90.f);
sl@0
   122
        break;
sl@0
   123
    case M3G_ANIM_SPOT_EXPONENT:
sl@0
   124
        M3G_ASSERT(valueSize >= 1);
sl@0
   125
        light->spotExponent = m3gClampFloat(value[0], 0.f, 128.f);
sl@0
   126
        break;
sl@0
   127
    default:
sl@0
   128
        m3gNodeUpdateProperty(self, property, valueSize, value);
sl@0
   129
    }
sl@0
   130
}
sl@0
   131
sl@0
   132
/*!
sl@0
   133
 * \internal
sl@0
   134
 * \brief Overloaded Object3D method.
sl@0
   135
 *
sl@0
   136
 * \param originalObj original Light object
sl@0
   137
 * \param cloneObj pointer to cloned Light object
sl@0
   138
 * \param pairs array for all object-duplicate pairs
sl@0
   139
 * \param numPairs number of pairs
sl@0
   140
 */
sl@0
   141
static M3Gbool m3gLightDuplicate(const Object *originalObj,
sl@0
   142
                                 Object **cloneObj,
sl@0
   143
                                 Object **pairs,
sl@0
   144
                                 M3Gint *numPairs)
sl@0
   145
{
sl@0
   146
    const Light *original = (const Light *) originalObj;
sl@0
   147
    Light *clone;
sl@0
   148
    M3G_ASSERT(*cloneObj == NULL); /* no derived classes for light */
sl@0
   149
    
sl@0
   150
    /* Create the clone object and exit on failure */
sl@0
   151
    
sl@0
   152
    clone = (Light *)m3gCreateLight(originalObj->interface);
sl@0
   153
    if (!clone) {
sl@0
   154
        return M3G_FALSE;
sl@0
   155
    }
sl@0
   156
    *cloneObj = (Object *)clone;
sl@0
   157
sl@0
   158
    /* Duplicate base class data */
sl@0
   159
    
sl@0
   160
    if (!m3gNodeDuplicate(originalObj, cloneObj, pairs, numPairs)) {
sl@0
   161
        return M3G_FALSE;
sl@0
   162
    }
sl@0
   163
sl@0
   164
    /* Duplicate own data */
sl@0
   165
    
sl@0
   166
	clone->constantAttenuation = original->constantAttenuation;
sl@0
   167
	clone->linearAttenuation = original->linearAttenuation;
sl@0
   168
	clone->quadraticAttenuation = original->quadraticAttenuation;
sl@0
   169
	clone->intensity = original->intensity;
sl@0
   170
	clone->color = original->color;
sl@0
   171
	clone->mode = original->mode;
sl@0
   172
    clone->spotAngle = original->spotAngle;
sl@0
   173
	clone->spotExponent = original->spotExponent;
sl@0
   174
    
sl@0
   175
    return M3G_TRUE;
sl@0
   176
}
sl@0
   177
sl@0
   178
/*!
sl@0
   179
 * \internal
sl@0
   180
 * \brief Initializes a Light object. See specification
sl@0
   181
 * for default values.
sl@0
   182
 *
sl@0
   183
 * \param m3g           M3G interface
sl@0
   184
 * \param light         Light object
sl@0
   185
 */
sl@0
   186
static void m3gInitLight(Interface *m3g, Light *light)
sl@0
   187
{
sl@0
   188
	/* Light is derived from node */
sl@0
   189
	m3gInitNode(m3g, &light->node, M3G_CLASS_LIGHT);
sl@0
   190
sl@0
   191
	light->constantAttenuation = 1.0f;
sl@0
   192
	light->intensity = 1.0f;
sl@0
   193
	light->color = 0x00ffffff;  /* Full white */
sl@0
   194
	light->mode = M3G_DIRECTIONAL;
sl@0
   195
	light->spotAngle = 45.0f;
sl@0
   196
}
sl@0
   197
sl@0
   198
/*!
sl@0
   199
 * \internal
sl@0
   200
 * \brief Applies this light to the current OpenGL context.
sl@0
   201
 *
sl@0
   202
 * \param self          Light object
sl@0
   203
 * \param glLight       OpenGL light index
sl@0
   204
 * \param pos           light position
sl@0
   205
 * \param spotDir       light direction
sl@0
   206
 */
sl@0
   207
static void m3gApplyLight(const Light *self,
sl@0
   208
                          GLenum glLight,
sl@0
   209
                          const Vec4 *pos,
sl@0
   210
                          const Vec4 *spotDir)
sl@0
   211
{
sl@0
   212
	static const M3Gfloat BLACK[] = { 0.0f, 0.0f, 0.0f, 0.0f };
sl@0
   213
	M3Gfloat light[4];
sl@0
   214
    
sl@0
   215
    M3G_ASSERT(m3gInRange(glLight, GL_LIGHT0, GL_LIGHT7));
sl@0
   216
    glEnable(glLight);
sl@0
   217
    
sl@0
   218
	m3gFloatColor(self->color, self->intensity, light);
sl@0
   219
sl@0
   220
    /* Set light position */
sl@0
   221
    
sl@0
   222
    if (self->mode == M3G_DIRECTIONAL) {
sl@0
   223
        GLfloat temp[4];
sl@0
   224
        temp[0] = -spotDir->x;
sl@0
   225
        temp[1] = -spotDir->y;
sl@0
   226
        temp[2] = -spotDir->z;
sl@0
   227
        temp[3] = 0.0f;
sl@0
   228
        glLightfv(glLight, GL_POSITION, temp);
sl@0
   229
    }
sl@0
   230
    else {
sl@0
   231
        glLightfv(glLight, GL_POSITION, &pos->x);
sl@0
   232
        if (self->mode == M3G_SPOT) {
sl@0
   233
            glLightfv(glLight, GL_SPOT_DIRECTION, &spotDir->x);
sl@0
   234
        }
sl@0
   235
    }
sl@0
   236
sl@0
   237
    /* Set ambient, diffuse, and specular contributions */
sl@0
   238
    
sl@0
   239
	if (self->mode == M3G_AMBIENT) {
sl@0
   240
		glLightfv(glLight, GL_AMBIENT, light);
sl@0
   241
		glLightfv(glLight, GL_DIFFUSE, BLACK);
sl@0
   242
		glLightfv(glLight, GL_SPECULAR, BLACK);
sl@0
   243
	}
sl@0
   244
	else {
sl@0
   245
		glLightfv(glLight, GL_AMBIENT, BLACK);
sl@0
   246
		glLightfv(glLight, GL_DIFFUSE, light);
sl@0
   247
		glLightfv(glLight, GL_SPECULAR, light);
sl@0
   248
	}
sl@0
   249
sl@0
   250
    /* Set spot parameters */
sl@0
   251
    
sl@0
   252
	if (self->mode == M3G_SPOT) {
sl@0
   253
		glLightf(glLight, GL_SPOT_EXPONENT, self->spotExponent);
sl@0
   254
		glLightf(glLight, GL_SPOT_CUTOFF, self->spotAngle);
sl@0
   255
	}
sl@0
   256
	else {
sl@0
   257
		glLightf(glLight, GL_SPOT_CUTOFF, 180.0f);
sl@0
   258
	}
sl@0
   259
sl@0
   260
    /* Set attenuation */
sl@0
   261
    
sl@0
   262
	if (self->mode == M3G_OMNI || self->mode == M3G_SPOT) {
sl@0
   263
		glLightf(glLight, GL_CONSTANT_ATTENUATION,  self->constantAttenuation);
sl@0
   264
		glLightf(glLight, GL_LINEAR_ATTENUATION,    self->linearAttenuation);
sl@0
   265
		glLightf(glLight, GL_QUADRATIC_ATTENUATION, self->quadraticAttenuation);
sl@0
   266
	}
sl@0
   267
	else if (self->mode == M3G_AMBIENT) {
sl@0
   268
		glLightf(glLight, GL_CONSTANT_ATTENUATION,  1.0f);
sl@0
   269
		glLightf(glLight, GL_LINEAR_ATTENUATION,    0.0f);
sl@0
   270
		glLightf(glLight, GL_QUADRATIC_ATTENUATION, 0.0f);
sl@0
   271
	}
sl@0
   272
}
sl@0
   273
sl@0
   274
/*----------------------------------------------------------------------
sl@0
   275
 * Virtual function table
sl@0
   276
 *--------------------------------------------------------------------*/
sl@0
   277
sl@0
   278
static const NodeVFTable m3gvf_Light = {
sl@0
   279
    {
sl@0
   280
        {
sl@0
   281
            m3gObjectApplyAnimation,
sl@0
   282
            m3gLightIsCompatible,
sl@0
   283
            m3gLightUpdateProperty,
sl@0
   284
            m3gObjectDoGetReferences,
sl@0
   285
            m3gObjectFindID,
sl@0
   286
            m3gLightDuplicate,
sl@0
   287
            m3gDestroyNode
sl@0
   288
        }
sl@0
   289
    },
sl@0
   290
    m3gNodeAlign,
sl@0
   291
    NULL, /* pure virtual DoRender */
sl@0
   292
    m3gNodeGetBBox,
sl@0
   293
    m3gNodeRayIntersect,
sl@0
   294
    m3gLightSetupRender,
sl@0
   295
    m3gNodeUpdateDuplicateReferences,
sl@0
   296
    m3gNodeValidate
sl@0
   297
};
sl@0
   298
sl@0
   299
sl@0
   300
/*----------------------------------------------------------------------
sl@0
   301
 * Public API functions
sl@0
   302
 *--------------------------------------------------------------------*/
sl@0
   303
sl@0
   304
/*!
sl@0
   305
 * \brief Creates a Light object.
sl@0
   306
 *
sl@0
   307
 * \param interface     M3G interface
sl@0
   308
 * \retval Light new Light object
sl@0
   309
 * \retval NULL Light creating failed
sl@0
   310
 */
sl@0
   311
M3G_API M3GLight m3gCreateLight(M3GInterface interface)
sl@0
   312
{
sl@0
   313
    Interface *m3g = (Interface *) interface;
sl@0
   314
    M3G_VALIDATE_INTERFACE(m3g);
sl@0
   315
sl@0
   316
	{
sl@0
   317
		Light *light =  m3gAllocZ(m3g, sizeof(Light));
sl@0
   318
sl@0
   319
        if (light != NULL) {
sl@0
   320
    		m3gInitLight(m3g, light);
sl@0
   321
        }
sl@0
   322
sl@0
   323
		return (M3GLight) light;
sl@0
   324
	}
sl@0
   325
}
sl@0
   326
sl@0
   327
/*!
sl@0
   328
 * \brief Set light intensity.
sl@0
   329
 *
sl@0
   330
 * \param handle        Light object
sl@0
   331
 * \param intensity     light intensity
sl@0
   332
 */
sl@0
   333
M3G_API void m3gSetIntensity(M3GLight handle, M3Gfloat intensity)
sl@0
   334
{
sl@0
   335
	Light *light = (Light *) handle;
sl@0
   336
	M3G_VALIDATE_OBJECT(light);
sl@0
   337
	
sl@0
   338
	light->intensity = intensity;
sl@0
   339
}
sl@0
   340
sl@0
   341
/*!
sl@0
   342
 * \brief Set light color as RGB.
sl@0
   343
 *
sl@0
   344
 * \param handle        Light object
sl@0
   345
 * \param rgb           light color as RGB
sl@0
   346
 */
sl@0
   347
M3G_API void m3gSetLightColor(M3GLight handle, M3Guint rgb)
sl@0
   348
{
sl@0
   349
	Light *light = (Light *) handle;
sl@0
   350
	M3G_VALIDATE_OBJECT(light);
sl@0
   351
sl@0
   352
	light->color = rgb & M3G_RGB_MASK;
sl@0
   353
}
sl@0
   354
sl@0
   355
/*!
sl@0
   356
 * \brief Set light mode.
sl@0
   357
 *
sl@0
   358
 * \param handle        Light object
sl@0
   359
 * \param mode          light mode
sl@0
   360
 */
sl@0
   361
M3G_API void m3gSetLightMode(M3GLight handle, M3Gint mode)
sl@0
   362
{
sl@0
   363
	Light *light = (Light *) handle;
sl@0
   364
	M3G_VALIDATE_OBJECT(light);
sl@0
   365
sl@0
   366
	if (mode < M3G_AMBIENT || mode > M3G_SPOT) {
sl@0
   367
    	m3gRaiseError(M3G_INTERFACE(light), M3G_INVALID_VALUE);
sl@0
   368
        return;
sl@0
   369
    }
sl@0
   370
sl@0
   371
	light->mode = mode;
sl@0
   372
}
sl@0
   373
sl@0
   374
/*!
sl@0
   375
 * \brief Set light spot angle.
sl@0
   376
 *
sl@0
   377
 * \param handle        Light object
sl@0
   378
 * \param angle         spot angle
sl@0
   379
 */
sl@0
   380
M3G_API void m3gSetSpotAngle(M3GLight handle, M3Gfloat angle)
sl@0
   381
{
sl@0
   382
	Light *light = (Light *) handle;
sl@0
   383
	M3G_VALIDATE_OBJECT(light);
sl@0
   384
sl@0
   385
	if (angle < 0.0f || angle > 90.f) {
sl@0
   386
    	m3gRaiseError(M3G_INTERFACE(light), M3G_INVALID_VALUE);
sl@0
   387
        return;
sl@0
   388
	}
sl@0
   389
sl@0
   390
	light->spotAngle = angle;
sl@0
   391
}
sl@0
   392
sl@0
   393
/*!
sl@0
   394
 * \brief Set light spot exponent.
sl@0
   395
 *
sl@0
   396
 * \param handle        Light object
sl@0
   397
 * \param exponent      spot exponent
sl@0
   398
 */
sl@0
   399
M3G_API void m3gSetSpotExponent(M3GLight handle, M3Gfloat exponent)
sl@0
   400
{
sl@0
   401
	Light *light = (Light *) handle;
sl@0
   402
	M3G_VALIDATE_OBJECT(light);
sl@0
   403
sl@0
   404
    if (exponent < 0.0f || exponent > 128.0f) {
sl@0
   405
    	m3gRaiseError(M3G_INTERFACE(light), M3G_INVALID_VALUE);
sl@0
   406
        return;
sl@0
   407
    }
sl@0
   408
sl@0
   409
    light->spotExponent = exponent;
sl@0
   410
}
sl@0
   411
sl@0
   412
/*!
sl@0
   413
 * \brief Set light attenuation factors.
sl@0
   414
 *
sl@0
   415
 * \param handle        Light object
sl@0
   416
 * \param constant      constant attenuation
sl@0
   417
 * \param linear        linear attenuation
sl@0
   418
 * \param quadratic     quadratic attenuation
sl@0
   419
 */
sl@0
   420
M3G_API void m3gSetAttenuation(M3GLight handle,
sl@0
   421
                               M3Gfloat constant,
sl@0
   422
                               M3Gfloat linear,
sl@0
   423
                               M3Gfloat quadratic)
sl@0
   424
{
sl@0
   425
	Light *light = (Light *) handle;
sl@0
   426
	M3G_VALIDATE_OBJECT(light);
sl@0
   427
sl@0
   428
    if (constant < 0.0f || linear < 0.0f || quadratic < 0.0f
sl@0
   429
        || (constant == 0.0f && linear == 0.0f && quadratic == 0.0f)) {
sl@0
   430
    	m3gRaiseError(M3G_INTERFACE(light), M3G_INVALID_VALUE);
sl@0
   431
        return;
sl@0
   432
    }
sl@0
   433
sl@0
   434
    light->constantAttenuation  = constant;
sl@0
   435
    light->linearAttenuation    = linear;
sl@0
   436
    light->quadraticAttenuation = quadratic;
sl@0
   437
}
sl@0
   438
sl@0
   439
/*!
sl@0
   440
 * \brief Get light intensity.
sl@0
   441
 *
sl@0
   442
 * \param handle        Light object
sl@0
   443
 * \return              light intensity
sl@0
   444
 */
sl@0
   445
M3G_API M3Gfloat m3gGetIntensity(M3GLight handle)
sl@0
   446
{
sl@0
   447
	Light *light = (Light *) handle;
sl@0
   448
	M3G_VALIDATE_OBJECT(light);
sl@0
   449
sl@0
   450
    return light->intensity;
sl@0
   451
}
sl@0
   452
sl@0
   453
/*!
sl@0
   454
 * \brief Get light color as RGB.
sl@0
   455
 *
sl@0
   456
 * \param handle        Light object
sl@0
   457
 * \return              light color as RGB
sl@0
   458
 */
sl@0
   459
M3G_API M3Guint m3gGetLightColor(M3GLight handle)
sl@0
   460
{
sl@0
   461
	Light *light = (Light *) handle;
sl@0
   462
	M3G_VALIDATE_OBJECT(light);
sl@0
   463
sl@0
   464
    return light->color;
sl@0
   465
}
sl@0
   466
sl@0
   467
/*!
sl@0
   468
 * \brief Get light mode.
sl@0
   469
 *
sl@0
   470
 * \param handle        Light object
sl@0
   471
 * \return              light mode
sl@0
   472
 */
sl@0
   473
M3G_API M3Gint m3gGetLightMode(M3GLight handle)
sl@0
   474
{
sl@0
   475
	Light *light = (Light *) handle;
sl@0
   476
	M3G_VALIDATE_OBJECT(light);
sl@0
   477
sl@0
   478
    return light->mode;
sl@0
   479
}
sl@0
   480
sl@0
   481
/*!
sl@0
   482
 * \brief Get light spot angle.
sl@0
   483
 *
sl@0
   484
 * \param handle        Light object
sl@0
   485
 * \return              light spot angle
sl@0
   486
 */
sl@0
   487
M3G_API M3Gfloat m3gGetSpotAngle(M3GLight handle)
sl@0
   488
{
sl@0
   489
	Light *light = (Light *) handle;
sl@0
   490
	M3G_VALIDATE_OBJECT(light);
sl@0
   491
sl@0
   492
    return light->spotAngle;
sl@0
   493
}
sl@0
   494
sl@0
   495
/*!
sl@0
   496
 * \brief Get light spot exponent.
sl@0
   497
 *
sl@0
   498
 * \param handle        Light object
sl@0
   499
 * \return              light spot exponent
sl@0
   500
 */
sl@0
   501
M3G_API M3Gfloat m3gGetSpotExponent(M3GLight handle)
sl@0
   502
{
sl@0
   503
	Light *light = (Light *) handle;
sl@0
   504
	M3G_VALIDATE_OBJECT(light);
sl@0
   505
sl@0
   506
    return light->spotExponent;
sl@0
   507
}
sl@0
   508
sl@0
   509
/*!
sl@0
   510
 * \brief Get light attenuation factor.
sl@0
   511
 *
sl@0
   512
 * \param handle        Light object
sl@0
   513
 * \param type          which factor to return
sl@0
   514
 *                      \arg M3G_GET_CONSTANT
sl@0
   515
 *                      \arg M3G_GET_LINEAR
sl@0
   516
 *                      \arg M3G_GET_QUADRATIC
sl@0
   517
 * \return              light attenuation factor
sl@0
   518
 */
sl@0
   519
M3G_API M3Gfloat m3gGetAttenuation(M3GLight handle, M3Gint type)
sl@0
   520
{
sl@0
   521
	Light *light = (Light *) handle;
sl@0
   522
	M3G_VALIDATE_OBJECT(light);
sl@0
   523
sl@0
   524
	switch(type) {
sl@0
   525
	case M3G_GET_CONSTANT:
sl@0
   526
	    return light->constantAttenuation;
sl@0
   527
	case M3G_GET_LINEAR:
sl@0
   528
    	return light->linearAttenuation;
sl@0
   529
    case M3G_GET_QUADRATIC:
sl@0
   530
	default:
sl@0
   531
	    return light->quadraticAttenuation;
sl@0
   532
	}
sl@0
   533
}
sl@0
   534