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