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