os/graphics/m3g/m3gcore11/src/m3g_fog.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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: Fog implementation
    15 *
    16 */
    17 
    18 
    19 /*!
    20  * \internal
    21  * \file
    22  * \brief Fog 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_fog.h"
    30 #include "m3g_animationtrack.h"
    31 
    32 /*----------------------------------------------------------------------
    33  * Internal functions
    34  *--------------------------------------------------------------------*/
    35 
    36 /*!
    37  * \internal
    38  * \brief Destroys this Fog object.
    39  *
    40  * \param obj Fog object
    41  */
    42 static void m3gDestroyFog(Object *obj)
    43 {
    44     Fog *fog = (Fog *) obj;
    45     M3G_VALIDATE_OBJECT(fog);
    46 
    47     m3gDestroyObject(&fog->object);
    48 }
    49 
    50 /*!
    51  * \internal
    52  * \brief Overloaded Object3D method.
    53  *
    54  * \param property      animation property
    55  * \retval M3G_TRUE     property supported
    56  * \retval M3G_FALSE    property not supported
    57  */
    58 static M3Gbool m3gFogIsCompatible(M3Gint property)
    59 {
    60     switch (property) {
    61     case M3G_ANIM_COLOR:
    62     case M3G_ANIM_DENSITY:
    63     case M3G_ANIM_FAR_DISTANCE:
    64     case M3G_ANIM_NEAR_DISTANCE:
    65         return M3G_TRUE;
    66     default:
    67         return m3gObjectIsCompatible(property);
    68     }
    69 }
    70 
    71 /*!
    72  * \internal
    73  * \brief Overloaded Object3D method.
    74  *
    75  * \param self          Fog object
    76  * \param property      animation property
    77  * \param valueSize     size of value array
    78  * \param value         value array
    79  */
    80 static void m3gFogUpdateProperty(Object *self,
    81                                  M3Gint property,
    82                                  M3Gint valueSize,
    83                                  const M3Gfloat *value)
    84 {
    85     Fog *fog = (Fog *)self;
    86     M3G_VALIDATE_OBJECT(fog);
    87     M3G_ASSERT_PTR(value);
    88 
    89     switch (property) {
    90     case M3G_ANIM_COLOR:
    91         M3G_ASSERT(valueSize >= 3);
    92         fog->color = m3gColor3f(value[0], value[1], value[2]) & M3G_RGB_MASK;
    93         break;
    94     case M3G_ANIM_DENSITY:
    95         M3G_ASSERT(valueSize >= 1);
    96         fog->density = (value[0] < 0.f) ? 0.f : value[0];
    97         break;
    98     case M3G_ANIM_FAR_DISTANCE:
    99         M3G_ASSERT(valueSize >= 1);
   100         fog->end = value[0];
   101         break;
   102     case M3G_ANIM_NEAR_DISTANCE:
   103         M3G_ASSERT(valueSize >= 1);
   104         fog->start = value[0];
   105         break;
   106     default:
   107         m3gObjectUpdateProperty(self, property, valueSize, value);
   108     }
   109 }
   110 
   111 /*!
   112  * \internal
   113  * \brief Overloaded Object3D method.
   114  *
   115  * \param originalObj original Fog object
   116  * \param cloneObj pointer to cloned Fog object
   117  * \param pairs array for all object-duplicate pairs
   118  * \param numPairs number of pairs
   119  */
   120 static M3Gbool m3gFogDuplicate(const Object *originalObj,
   121                                Object **cloneObj,
   122                                Object **pairs,
   123                                M3Gint *numPairs)
   124 {
   125     Fog *original = (Fog *)originalObj;
   126     Fog *clone = (Fog *)m3gCreateFog(originalObj->interface);
   127     *cloneObj = (Object *)clone;
   128     if (*cloneObj == NULL) {
   129         return M3G_FALSE;
   130     }
   131 
   132     if(m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
   133         clone->color = original->color;
   134         clone->density = original->density;
   135         clone->start = original->start;
   136         clone->end = original->end;
   137         clone->mode = original->mode;
   138         return M3G_TRUE;
   139     }
   140     else {
   141         return M3G_FALSE;
   142     }
   143 }
   144 
   145 /*!
   146  * \internal
   147  * \brief Initializes a Fog object. See specification
   148  * for default values.
   149  *
   150  * \param m3g           M3G interface
   151  * \param fog           Fog object
   152  */
   153 static void m3gInitFog(Interface *m3g, Fog *fog)
   154 {
   155 	/* Fog is derived from object */
   156 	m3gInitObject(&fog->object, m3g, M3G_CLASS_FOG);
   157 
   158 	fog->density = 1.0f;
   159 	fog->start = 0.0f;
   160 	fog->end = 1.0f;
   161 	fog->mode = M3G_LINEAR_FOG;
   162 }
   163 
   164 /*!
   165  * \internal
   166  * \brief Applies fog to OpenGL. This is used for
   167  * all Mesh objects.
   168  *
   169  * \param self          Fog object
   170  */
   171 static void m3gApplyFog(const Fog *self)
   172 {
   173 	if (self != NULL) {
   174 		GLfixed temp[4];
   175 
   176         m3gGLColor(self->color, temp);
   177 
   178 		switch (self->mode) {
   179 		case M3G_LINEAR_FOG:
   180 			glEnable(GL_FOG);
   181 			glFogf(GL_FOG_MODE, GL_LINEAR);
   182 			glFogf(GL_FOG_START, self->start);
   183 			glFogf(GL_FOG_END, self->end);
   184 			glFogxv(GL_FOG_COLOR, temp);
   185 			break;
   186 		case M3G_EXPONENTIAL_FOG:
   187 			glEnable(GL_FOG);
   188 			glFogf(GL_FOG_MODE, GL_EXP);
   189 			glFogf(GL_FOG_DENSITY, self->density);
   190 			glFogxv(GL_FOG_COLOR, temp);
   191 			break;
   192 		}
   193 	}
   194 	else {
   195 		glDisable(GL_FOG);
   196 	}
   197     M3G_ASSERT_GL;
   198 }
   199 
   200 #ifdef M3G_USE_NGL_API
   201 /*!
   202  * \internal
   203  * \brief Applies fog to NGL. This is used for
   204  * Sprite3D objects only.
   205  *
   206  * \param self          Fog object
   207  * \param eyeZ          Eye space Z (e.g. after modelview)
   208  * \param finalZ        Final Z (e.g. after modelview and projection)
   209  */
   210 static void m3gApplySpriteFog(const Fog *self, M3Gfloat eyeZ, M3Gfloat finalZ)
   211 {
   212     if(self != NULL) {
   213 		M3Gint temp[4];
   214     	M3Gfloat fogValue = 1;
   215 
   216         /* Calculate fog value and use OpenGL linear fog
   217          * to result in same value. Sprites are drawn with
   218          * identity MV and P and therefore the fog has to
   219          * be adjusted like this */
   220         switch (self->mode) {
   221     	case M3G_LINEAR_FOG:
   222             fogValue = m3gDiv(m3gAdd(self->end, eyeZ), m3gSub(self->end, self->start));
   223     		break;
   224     	case M3G_EXPONENTIAL_FOG:
   225             fogValue = m3gExp(m3gMul(self->density, eyeZ));
   226     		break;
   227         default:
   228             M3G_ASSERT(M3G_FALSE);
   229             break;
   230     	}
   231 
   232         m3gGLColor(self->color, temp);
   233 
   234 		glEnable(GL_FOG);
   235 		glFogf(GL_FOG_MODE, GL_LINEAR);
   236 
   237         /* NGL works differently in fog calculation */
   238 		glFogf(GL_FOG_START, -m3gDiv(finalZ, fogValue));
   239 		glFogf(GL_FOG_END, 0.f);
   240 		glFogxv(GL_FOG_COLOR, temp);
   241     }
   242     else {
   243 		glDisable(GL_FOG);
   244     }
   245 }
   246 #endif
   247 /*----------------------------------------------------------------------
   248  * Virtual function table
   249  *--------------------------------------------------------------------*/
   250 
   251 static const ObjectVFTable m3gvf_Fog = {
   252     m3gObjectApplyAnimation,
   253     m3gFogIsCompatible,
   254     m3gFogUpdateProperty,
   255     m3gObjectDoGetReferences,
   256     m3gObjectFindID,
   257     m3gFogDuplicate,
   258     m3gDestroyFog
   259 };
   260 
   261 
   262 /*----------------------------------------------------------------------
   263  * Public API functions
   264  *--------------------------------------------------------------------*/
   265 
   266 /*!
   267  * \brief Creates a Fog object.
   268  *
   269  * \param interface     M3G interface
   270  * \retval Fog new Fog object
   271  * \retval NULL Fog creating failed
   272  */
   273 M3G_API M3GFog m3gCreateFog(M3GInterface interface)
   274 {
   275     Interface *m3g = (Interface *) interface;
   276     M3G_VALIDATE_INTERFACE(m3g);
   277 
   278 	{
   279 		Fog *fog =  m3gAllocZ(m3g, sizeof(Fog));
   280 
   281         if (fog != NULL) {
   282     		m3gInitFog(m3g, fog);
   283         }
   284 
   285 		return (M3GFog) fog;
   286 	}
   287 }
   288 
   289 /*!
   290  * \brief Sets fog mode.
   291  *
   292  * \param handle        Fog object
   293  * \param mode          fog mode
   294  */
   295 M3G_API void m3gSetFogMode(M3GFog handle, M3Gint mode)
   296 {
   297 	Fog *fog = (Fog *) handle;
   298 	M3G_VALIDATE_OBJECT(fog);
   299 
   300 	/* Check for errors */
   301 	if(mode < M3G_EXPONENTIAL_FOG || mode > M3G_LINEAR_FOG) {
   302 		m3gRaiseError(M3G_INTERFACE(fog), M3G_INVALID_VALUE);
   303         return;
   304 	}
   305 
   306 	fog->mode = mode;
   307 }
   308 
   309 /*!
   310  * \brief Gets fog mode.
   311  *
   312  * \param handle        Fog object
   313  * \return              fog mode
   314  */
   315 M3G_API M3Gint m3gGetFogMode(M3GFog handle)
   316 {
   317 	Fog *fog = (Fog *) handle;
   318 	M3G_VALIDATE_OBJECT(fog);
   319 
   320 	return fog->mode;
   321 }
   322 
   323 /*!
   324  * \brief Sets linear fog parameters.
   325  *
   326  * \param handle        Fog object
   327  * \param fogNear       near distance
   328  * \param fogFar        far distance
   329  */
   330 M3G_API void m3gSetFogLinear(M3GFog handle, M3Gfloat fogNear, M3Gfloat fogFar)
   331 {
   332 	Fog *fog = (Fog *) handle;
   333 	M3G_VALIDATE_OBJECT(fog);
   334 
   335 	fog->start = fogNear;
   336 	fog->end = fogFar;
   337 }
   338 
   339 /*!
   340  * \brief Gets linear fog parameters.
   341  *
   342  * \param handle        Fog object
   343  * \param which         which parameter to return
   344  *                      \arg M3G_GET_NEAR
   345  *                      \arg M3G_GET_FAR
   346  * \return              near or far distance
   347  */
   348 M3G_API M3Gfloat m3gGetFogDistance(M3GFog handle, M3Gint which)
   349 {
   350 	Fog *fog = (Fog *) handle;
   351 	M3G_VALIDATE_OBJECT(fog);
   352 
   353 	switch(which) {
   354 	case M3G_GET_NEAR:
   355 		return fog->start;
   356 	case M3G_GET_FAR:
   357 	default:
   358 		return fog->end;
   359 	}
   360 }
   361 
   362 /*!
   363  * \brief Sets exponential fog density.
   364  *
   365  * \param handle        Fog object
   366  * \param density       fog density
   367  */
   368 M3G_API void m3gSetFogDensity(M3GFog handle, M3Gfloat density)
   369 {
   370 	Fog *fog = (Fog *) handle;
   371 	M3G_VALIDATE_OBJECT(fog);
   372 
   373 	if(density < 0.f) {
   374 		m3gRaiseError(M3G_INTERFACE(fog), M3G_INVALID_VALUE);
   375         return;
   376 	}
   377 
   378 	fog->density = density;
   379 }
   380 
   381 /*!
   382  * \brief Gets exponential fog density.
   383  *
   384  * \param handle        Fog object
   385  * \return              fog density
   386  */
   387 M3G_API M3Gfloat m3gGetFogDensity(M3GFog handle)
   388 {
   389 	Fog *fog = (Fog *) handle;
   390 	M3G_VALIDATE_OBJECT(fog);
   391 
   392 	return fog->density;
   393 }
   394 
   395 /*!
   396  * \brief Sets fog color as RGB.
   397  *
   398  * \param handle        Fog object
   399  * \param rgb           fog color as RGB
   400  */
   401 M3G_API void m3gSetFogColor(M3GFog handle, M3Guint rgb)
   402 {
   403 	Fog *fog = (Fog *) handle;
   404 	M3G_VALIDATE_OBJECT(fog);
   405 
   406     fog->color = rgb & M3G_RGB_MASK;
   407 }
   408 
   409 /*!
   410  * \brief Gets fog color as RGB.
   411  *
   412  * \param handle        Fog object
   413  * \return              fog color as RGB
   414  */
   415 M3G_API M3Guint m3gGetFogColor(M3GFog handle)
   416 {
   417 	Fog *fog = (Fog *) handle;
   418 	M3G_VALIDATE_OBJECT(fog);
   419 
   420     return fog->color;
   421 }
   422