os/graphics/m3g/m3gcore11/src/m3g_material.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: Material 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 Material 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_material.h"
sl@0
    30
#include "m3g_animationtrack.h"
sl@0
    31
sl@0
    32
#define ALL_TARGET_MASK (M3G_AMBIENT_BIT | M3G_DIFFUSE_BIT | M3G_EMISSIVE_BIT | M3G_SPECULAR_BIT)
sl@0
    33
sl@0
    34
/*----------------------------------------------------------------------
sl@0
    35
 * Internal functions
sl@0
    36
 *--------------------------------------------------------------------*/
sl@0
    37
sl@0
    38
/*!
sl@0
    39
 * \internal
sl@0
    40
 * \brief Applies default material to OpenGL.
sl@0
    41
 */
sl@0
    42
static void m3gApplyDefaultMaterial(void)
sl@0
    43
{
sl@0
    44
    glDisable(GL_COLOR_MATERIAL);
sl@0
    45
    glDisable(GL_LIGHTING);
sl@0
    46
}
sl@0
    47
sl@0
    48
/*!
sl@0
    49
 * \internal
sl@0
    50
 * \brief Applies material to OpenGL.
sl@0
    51
 *
sl@0
    52
 * \param material Material object
sl@0
    53
 * \param alphaFactor alpha factor as 1.16 fixed point
sl@0
    54
 */
sl@0
    55
static void m3gApplyMaterial(Material *material, M3Gint alphaFactor)
sl@0
    56
{
sl@0
    57
    if (material != NULL) {
sl@0
    58
    	M3Gfloat colors[4];
sl@0
    59
sl@0
    60
        /* NOTE We must set the ColorMaterial state *before* setting
sl@0
    61
         * any of the material colors, as they will not change if
sl@0
    62
         * tracking is enabled! */
sl@0
    63
        
sl@0
    64
        if (material->vertexColorTracking) {
sl@0
    65
            glEnable(GL_COLOR_MATERIAL);
sl@0
    66
        }
sl@0
    67
        else {
sl@0
    68
            glDisable(GL_COLOR_MATERIAL);
sl@0
    69
sl@0
    70
            /* Ambient and diffuse only need to be set when tracking
sl@0
    71
             * is disabled */
sl@0
    72
            
sl@0
    73
            m3gFloatColor(material->ambientColor, 1.0f, colors);
sl@0
    74
            glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, colors);
sl@0
    75
            m3gFloatColor(material->diffuseColor, 1.0f, colors);
sl@0
    76
            if (alphaFactor < 0x10000) {
sl@0
    77
                colors[3] = m3gMul(colors[3],
sl@0
    78
                                   m3gMul((M3Gfloat) alphaFactor,
sl@0
    79
                                          1.f/65536.f));
sl@0
    80
            }
sl@0
    81
            glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, colors);
sl@0
    82
        }
sl@0
    83
        m3gFloatColor(material->emissiveColor, 1.0f, colors);
sl@0
    84
        glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, colors);
sl@0
    85
        m3gFloatColor(material->specularColor, 1.0f, colors);
sl@0
    86
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, colors);
sl@0
    87
        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material->shininess);
sl@0
    88
sl@0
    89
        glEnable(GL_LIGHTING);
sl@0
    90
    }
sl@0
    91
    else {
sl@0
    92
        m3gApplyDefaultMaterial();
sl@0
    93
    }
sl@0
    94
    M3G_ASSERT_GL;
sl@0
    95
}
sl@0
    96
sl@0
    97
/*!
sl@0
    98
 * \internal
sl@0
    99
 * \brief Overloaded Object3D method.
sl@0
   100
 *
sl@0
   101
 * \param property      animation property
sl@0
   102
 * \retval M3G_TRUE     property supported
sl@0
   103
 * \retval M3G_FALSE    property not supported
sl@0
   104
 */
sl@0
   105
static M3Gbool m3gMaterialIsCompatible(M3Gint property)
sl@0
   106
{
sl@0
   107
    switch (property) {
sl@0
   108
    case M3G_ANIM_ALPHA:
sl@0
   109
    case M3G_ANIM_AMBIENT_COLOR:
sl@0
   110
    case M3G_ANIM_DIFFUSE_COLOR:
sl@0
   111
    case M3G_ANIM_EMISSIVE_COLOR:
sl@0
   112
    case M3G_ANIM_SHININESS:
sl@0
   113
    case M3G_ANIM_SPECULAR_COLOR:
sl@0
   114
        return M3G_TRUE;
sl@0
   115
    default:
sl@0
   116
        return m3gObjectIsCompatible(property);
sl@0
   117
    }
sl@0
   118
}
sl@0
   119
sl@0
   120
/*!
sl@0
   121
 * \internal
sl@0
   122
 * \brief Overloaded Object3D method.
sl@0
   123
 *
sl@0
   124
 * \param self          Material object
sl@0
   125
 * \param property      animation property
sl@0
   126
 * \param valueSize     size of value array
sl@0
   127
 * \param value         value array
sl@0
   128
 */
sl@0
   129
static void m3gMaterialUpdateProperty(Object *self,
sl@0
   130
                                      M3Gint property,
sl@0
   131
                                      M3Gint valueSize,
sl@0
   132
                                      const M3Gfloat *value)
sl@0
   133
{
sl@0
   134
    Material *material = (Material *)self;
sl@0
   135
    M3G_VALIDATE_OBJECT(material);
sl@0
   136
    M3G_ASSERT_PTR(value);
sl@0
   137
sl@0
   138
    switch (property) {
sl@0
   139
    case M3G_ANIM_ALPHA:
sl@0
   140
        M3G_ASSERT(valueSize >= 1);
sl@0
   141
        material->diffuseColor = (material->diffuseColor | M3G_ALPHA_MASK) &
sl@0
   142
            m3gAlpha1f(value[0]);
sl@0
   143
        break;
sl@0
   144
    case M3G_ANIM_AMBIENT_COLOR:
sl@0
   145
        M3G_ASSERT(valueSize >= 3);
sl@0
   146
        material->ambientColor = m3gColor3f(value[0], value[1], value[2]);
sl@0
   147
        break;
sl@0
   148
    case M3G_ANIM_DIFFUSE_COLOR:
sl@0
   149
        M3G_ASSERT(valueSize >= 3);
sl@0
   150
        material->diffuseColor = (material->diffuseColor | M3G_RGB_MASK)
sl@0
   151
            & m3gColor3f(value[0], value[1], value[2]);
sl@0
   152
        break;
sl@0
   153
    case M3G_ANIM_EMISSIVE_COLOR:
sl@0
   154
        M3G_ASSERT(valueSize >= 3);
sl@0
   155
        material->emissiveColor = m3gColor3f(value[0], value[1], value[2]) & M3G_RGB_MASK;
sl@0
   156
        break;
sl@0
   157
    case M3G_ANIM_SHININESS:
sl@0
   158
        M3G_ASSERT(valueSize >= 1);
sl@0
   159
        material->shininess = m3gClampFloat(value[0], 0.f, 128.f);
sl@0
   160
        break;
sl@0
   161
    case M3G_ANIM_SPECULAR_COLOR:
sl@0
   162
        M3G_ASSERT(valueSize >= 3);
sl@0
   163
        material->specularColor = m3gColor3f(value[0], value[1], value[2]);
sl@0
   164
        break;
sl@0
   165
    default:
sl@0
   166
        m3gObjectUpdateProperty(self, property, valueSize, value);
sl@0
   167
    }
sl@0
   168
}
sl@0
   169
sl@0
   170
/*!
sl@0
   171
 * \internal
sl@0
   172
 * \brief Overloaded Object3D method.
sl@0
   173
 *
sl@0
   174
 * \param originalObj original Material object
sl@0
   175
 * \param cloneObj pointer to cloned Material object
sl@0
   176
 * \param pairs array for all object-duplicate pairs
sl@0
   177
 * \param numPairs number of pairs
sl@0
   178
 */
sl@0
   179
static M3Gbool m3gMaterialDuplicate(const Object *originalObj,
sl@0
   180
                                    Object **cloneObj,
sl@0
   181
                                    Object **pairs,
sl@0
   182
                                    M3Gint *numPairs)
sl@0
   183
{
sl@0
   184
    const Material *original = (const Material *)originalObj;
sl@0
   185
sl@0
   186
    /* Create the clone object */
sl@0
   187
    
sl@0
   188
    Material *clone = (Material *)m3gCreateMaterial(originalObj->interface);
sl@0
   189
    if (!clone) {
sl@0
   190
        return M3G_FALSE;
sl@0
   191
    }
sl@0
   192
    *cloneObj = (Object *)clone;
sl@0
   193
sl@0
   194
    /* Duplicate base class and own data */
sl@0
   195
    
sl@0
   196
    if (m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
sl@0
   197
        clone->vertexColorTracking = original->vertexColorTracking;
sl@0
   198
        clone->ambientColor = original->ambientColor;
sl@0
   199
        clone->diffuseColor = original->diffuseColor;
sl@0
   200
        clone->emissiveColor = original->emissiveColor;
sl@0
   201
        clone->specularColor = original->specularColor;
sl@0
   202
        clone->shininess = original->shininess;
sl@0
   203
        return M3G_TRUE;
sl@0
   204
    }
sl@0
   205
    else {
sl@0
   206
        return M3G_FALSE;
sl@0
   207
    }
sl@0
   208
}
sl@0
   209
sl@0
   210
/*----------------------------------------------------------------------
sl@0
   211
 * Virtual function table
sl@0
   212
 *--------------------------------------------------------------------*/
sl@0
   213
sl@0
   214
static const ObjectVFTable m3gvf_Material = {
sl@0
   215
    m3gObjectApplyAnimation,
sl@0
   216
    m3gMaterialIsCompatible,
sl@0
   217
    m3gMaterialUpdateProperty,
sl@0
   218
    m3gObjectDoGetReferences,
sl@0
   219
    m3gObjectFindID,
sl@0
   220
    m3gMaterialDuplicate,
sl@0
   221
    m3gDestroyObject
sl@0
   222
};
sl@0
   223
sl@0
   224
sl@0
   225
/*----------------------------------------------------------------------
sl@0
   226
 * Public API functions
sl@0
   227
 *--------------------------------------------------------------------*/
sl@0
   228
sl@0
   229
/*!
sl@0
   230
 * \brief Creates a Material object.
sl@0
   231
 *
sl@0
   232
 * \param interface     M3G interface
sl@0
   233
 * \retval Material new Material object
sl@0
   234
 * \retval NULL Material creating failed
sl@0
   235
 */
sl@0
   236
M3G_API M3GMaterial m3gCreateMaterial(M3GInterface interface)
sl@0
   237
{
sl@0
   238
    Interface *m3g = (Interface *) interface;
sl@0
   239
    M3G_VALIDATE_INTERFACE(m3g);
sl@0
   240
sl@0
   241
    {
sl@0
   242
        Material *material = m3gAllocZ(m3g, sizeof(Material));
sl@0
   243
sl@0
   244
        if (material != NULL) {
sl@0
   245
            m3gInitObject(&material->object, m3g, M3G_CLASS_MATERIAL);
sl@0
   246
            /* Default values are from the jsr-184 specification */
sl@0
   247
            material->vertexColorTracking = GL_FALSE;
sl@0
   248
            material->ambientColor = 0x00333333U;
sl@0
   249
            material->diffuseColor = 0xFFCCCCCCU;
sl@0
   250
            material->emissiveColor = 0x00000000U;
sl@0
   251
            material->specularColor = 0x00000000U;
sl@0
   252
            material->shininess = 0.0f;
sl@0
   253
        }
sl@0
   254
sl@0
   255
        return (M3GMaterial)material;
sl@0
   256
    }
sl@0
   257
}
sl@0
   258
sl@0
   259
/*!
sl@0
   260
 * \brief Set material color.
sl@0
   261
 *
sl@0
   262
 * \param hMaterial Material object
sl@0
   263
 * \param target    color target
sl@0
   264
 * \param ARGB      ARGB color
sl@0
   265
 */
sl@0
   266
M3G_API void m3gSetColor(M3GMaterial hMaterial, M3Genum target, M3Guint ARGB)
sl@0
   267
{
sl@0
   268
    Material *material = (Material *) hMaterial;
sl@0
   269
    M3G_VALIDATE_OBJECT(material);
sl@0
   270
    /* is invalid target in the mask OR no target */
sl@0
   271
    if (((target | ALL_TARGET_MASK) != ALL_TARGET_MASK) || ((target & ALL_TARGET_MASK) == 0)) {
sl@0
   272
        m3gRaiseError(M3G_INTERFACE(material), M3G_INVALID_VALUE);
sl@0
   273
        return;
sl@0
   274
    }
sl@0
   275
    if ((target & M3G_AMBIENT_BIT) != 0) {
sl@0
   276
        material->ambientColor = ARGB & M3G_RGB_MASK;
sl@0
   277
    }
sl@0
   278
    if ((target & M3G_DIFFUSE_BIT) != 0) {
sl@0
   279
        material->diffuseColor = ARGB;
sl@0
   280
    }
sl@0
   281
    if ((target & M3G_EMISSIVE_BIT) != 0) {
sl@0
   282
        material->emissiveColor = ARGB & M3G_RGB_MASK;
sl@0
   283
    }
sl@0
   284
    if ((target & M3G_SPECULAR_BIT) != 0) {
sl@0
   285
        material->specularColor = ARGB & M3G_RGB_MASK;
sl@0
   286
    }
sl@0
   287
}
sl@0
   288
sl@0
   289
/*!
sl@0
   290
 * \brief Get material color.
sl@0
   291
 *
sl@0
   292
 * \param hMaterial Material object
sl@0
   293
 * \param target    color target
sl@0
   294
 * \return          ARGB color
sl@0
   295
 */
sl@0
   296
M3G_API M3Guint m3gGetColor(M3GMaterial hMaterial, M3Genum target)
sl@0
   297
{
sl@0
   298
    Material *material = (Material *) hMaterial;
sl@0
   299
    M3G_VALIDATE_OBJECT(material);
sl@0
   300
    
sl@0
   301
    switch (target) {
sl@0
   302
    case M3G_AMBIENT_BIT:
sl@0
   303
        return material->ambientColor;
sl@0
   304
    case M3G_DIFFUSE_BIT:
sl@0
   305
        return material->diffuseColor;
sl@0
   306
    case M3G_EMISSIVE_BIT:
sl@0
   307
        return material->emissiveColor;
sl@0
   308
    case M3G_SPECULAR_BIT:
sl@0
   309
        return material->specularColor;
sl@0
   310
    default:
sl@0
   311
        m3gRaiseError(M3G_INTERFACE(material), M3G_INVALID_VALUE);
sl@0
   312
        break;
sl@0
   313
    }
sl@0
   314
sl@0
   315
    return 0; /* Error */
sl@0
   316
}
sl@0
   317
sl@0
   318
/*!
sl@0
   319
 * \brief Set material shininess.
sl@0
   320
 *
sl@0
   321
 * \param hMaterial Material object
sl@0
   322
 * \param shininess shininess
sl@0
   323
 */
sl@0
   324
M3G_API void m3gSetShininess(M3GMaterial hMaterial, M3Gfloat shininess)
sl@0
   325
{
sl@0
   326
    Material *material = (Material *) hMaterial;
sl@0
   327
    M3G_VALIDATE_OBJECT(material);
sl@0
   328
    if (!m3gInRangef(shininess, 0.0f, 128.f)) {
sl@0
   329
        m3gRaiseError(M3G_INTERFACE(material), M3G_INVALID_VALUE);
sl@0
   330
        return;
sl@0
   331
    }
sl@0
   332
    material->shininess = shininess;
sl@0
   333
}
sl@0
   334
sl@0
   335
/*!
sl@0
   336
 * \brief Get material shininess.
sl@0
   337
 *
sl@0
   338
 * \param hMaterial Material object
sl@0
   339
 * \return          shininess
sl@0
   340
 */
sl@0
   341
M3G_API GLfloat m3gGetShininess(M3GMaterial hMaterial)
sl@0
   342
{
sl@0
   343
    Material *material = (Material *) hMaterial;
sl@0
   344
    M3G_VALIDATE_OBJECT(material);
sl@0
   345
    return material->shininess;
sl@0
   346
}
sl@0
   347
sl@0
   348
/*!
sl@0
   349
 * \brief Set vertex color tracking enable.
sl@0
   350
 *
sl@0
   351
 * \param hMaterial Material object
sl@0
   352
 * \param enable color tracking enable
sl@0
   353
 */
sl@0
   354
M3G_API void m3gSetVertexColorTrackingEnable(M3GMaterial hMaterial,
sl@0
   355
                                             M3Gbool enable)
sl@0
   356
{
sl@0
   357
    Material *material = (Material *) hMaterial;
sl@0
   358
    M3G_VALIDATE_OBJECT(material);
sl@0
   359
    material->vertexColorTracking = (GLboolean) enable;
sl@0
   360
}
sl@0
   361
sl@0
   362
/*!
sl@0
   363
 * \brief Get vertex color tracking enable.
sl@0
   364
 *
sl@0
   365
 * \param hMaterial Material object
sl@0
   366
 * \retval M3G_TRUE color tracking enabled
sl@0
   367
 * \retval M3G_FALSE color tracking disabled
sl@0
   368
 */
sl@0
   369
M3G_API M3Gbool m3gIsVertexColorTrackingEnabled(M3GMaterial hMaterial)
sl@0
   370
{
sl@0
   371
    Material *material = (Material *) hMaterial;
sl@0
   372
    M3G_VALIDATE_OBJECT(material);
sl@0
   373
    return (M3Gbool) material->vertexColorTracking;
sl@0
   374
}
sl@0
   375