os/graphics/m3g/m3gcore11/src/m3g_appearance.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: Appearance 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 Appearance 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_appearance.h"
sl@0
    30
#include "m3g_vertexbuffer.h"
sl@0
    31
sl@0
    32
/*----------------------------------------------------------------------
sl@0
    33
 * Private functions
sl@0
    34
 *--------------------------------------------------------------------*/
sl@0
    35
sl@0
    36
/*!
sl@0
    37
 * \internal
sl@0
    38
 * \brief Applies default appearance values to OpenGL.
sl@0
    39
 */
sl@0
    40
static void m3gApplyAppearanceDefaults(RenderContext *ctx)
sl@0
    41
{
sl@0
    42
    int i;
sl@0
    43
    m3gApplyCompositingMode(NULL, ctx);
sl@0
    44
    m3gApplyPolygonMode(NULL);
sl@0
    45
    m3gApplyMaterial(NULL, 0x10000);
sl@0
    46
	m3gApplyFog(NULL);
sl@0
    47
sl@0
    48
    for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
sl@0
    49
        glActiveTexture(GL_TEXTURE0 + i);
sl@0
    50
        glDisable(GL_TEXTURE_2D);
sl@0
    51
    }
sl@0
    52
}
sl@0
    53
sl@0
    54
/*!
sl@0
    55
 * \internal
sl@0
    56
 * \brief Generate a hash number for a pointer
sl@0
    57
 */
sl@0
    58
static M3Guint m3gGenPointerHash(const void *ptr)
sl@0
    59
{
sl@0
    60
    M3Guint p = ((M3Guint) ptr) >> 2;
sl@0
    61
    M3Guint key = p ^ (p >> 5) ^ (p >> 10) ^ (p >> 15) ^ (p >> 20) ^ (p >> 25);
sl@0
    62
    return key;
sl@0
    63
}
sl@0
    64
sl@0
    65
/*!
sl@0
    66
 * \internal
sl@0
    67
 * \brief Generate a quick hash bit pattern for the textures of this
sl@0
    68
 * appearance object
sl@0
    69
 */
sl@0
    70
static M3Guint m3gGen12BitTextureHash(const Appearance *app)
sl@0
    71
{
sl@0
    72
    M3Guint key = 0; 
sl@0
    73
	
sl@0
    74
    int i;
sl@0
    75
    
sl@0
    76
    for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
sl@0
    77
        const Texture *tex = app->texture[i];
sl@0
    78
        if (tex) {
sl@0
    79
            key ^= (m3gGenPointerHash(m3gGetTextureImage((M3GTexture)tex)) >> i) << 6;
sl@0
    80
            key ^= (m3gGenPointerHash(tex) >> i) & 0x3Fu;
sl@0
    81
        }
sl@0
    82
    }
sl@0
    83
    return key & ((1u<<12)-1);
sl@0
    84
}
sl@0
    85
sl@0
    86
/*!
sl@0
    87
 * \internal
sl@0
    88
 * \brief Generate the sorting key for render queue
sl@0
    89
 *
sl@0
    90
 * Sort key is a combination of user settable layer and
sl@0
    91
 * blending mode. Blended objects are always drawn last.
sl@0
    92
 *
sl@0
    93
 * \param appearance    Appearance object
sl@0
    94
 * \return              sort key
sl@0
    95
 */
sl@0
    96
static void m3gRegenerateSortKey(Appearance *appearance)
sl@0
    97
{
sl@0
    98
	M3Guint key = 0;
sl@0
    99
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   100
sl@0
   101
    /*------------------------------------------------------------
sl@0
   102
     * First do the mandatory sorting by layer index and blending
sl@0
   103
     * state; this currently uses the top eight bits, 31..24
sl@0
   104
     *-----------------------------------------------------------*/
sl@0
   105
        
sl@0
   106
    key = (appearance->layer - M3G_APPEARANCE_MIN_LAYER)
sl@0
   107
        << (33 - M3G_APPEARANCE_HARD_SORT_BITS);
sl@0
   108
    
sl@0
   109
    /* NOTE the blending state bit is not set here, but dynamically in
sl@0
   110
     * m3gGetAppearanceSortKey; this way we do not need to implement
sl@0
   111
     * signaling from CompositingMode to Appearance when the blending
sl@0
   112
     * state changes */
sl@0
   113
sl@0
   114
    /*-----------------------------------------------------------------
sl@0
   115
     * The rest of the bits, 23..0, affect performance only; ideally,
sl@0
   116
     * these should be sorted so that the more expensive state is in the
sl@0
   117
     * higher bits, but this is largely dependent on the hardware
sl@0
   118
     *----------------------------------------------------------------*/
sl@0
   119
sl@0
   120
    /* Texturing changes are often expensive in graphics hardware, so
sl@0
   121
     * we put a hash of the texture objects into the top twelve
sl@0
   122
     * bits
sl@0
   123
     *
sl@0
   124
     * NOTE we do not currently update this if a texture image
sl@0
   125
     * changes, but that shouldn't happen too often and only has
sl@0
   126
     * relatively minor performance implications
sl@0
   127
     */
sl@0
   128
sl@0
   129
    key |= m3gGen12BitTextureHash(appearance) << 12;
sl@0
   130
sl@0
   131
    /* Use the rest of the bits for the various components; depth
sl@0
   132
     * function changes are another potentially costly operation, so
sl@0
   133
     * put that next */
sl@0
   134
sl@0
   135
    key |= (m3gGenPointerHash(appearance->compositingMode) & 0x0Fu) << 8;
sl@0
   136
    key |= (m3gGenPointerHash(appearance->material) & 0x07u) << 5;
sl@0
   137
    key |= (m3gGenPointerHash(appearance->polygonMode) & 0x07u) << 2;
sl@0
   138
    key |= (m3gGenPointerHash(appearance->fog) & 0x03u);
sl@0
   139
    
sl@0
   140
    /* Store the final value */
sl@0
   141
    appearance->sortKey = key;
sl@0
   142
}
sl@0
   143
sl@0
   144
/*----------------------------------------------------------------------
sl@0
   145
 * Internal functions
sl@0
   146
 *--------------------------------------------------------------------*/
sl@0
   147
sl@0
   148
/*!
sl@0
   149
 * \internal
sl@0
   150
 * \brief Destroys this Appearance object.
sl@0
   151
 *
sl@0
   152
 * \param obj Appearance object
sl@0
   153
 */
sl@0
   154
static void m3gDestroyAppearance(Object *obj)
sl@0
   155
{
sl@0
   156
    int i;
sl@0
   157
    Appearance *appearance = (Appearance *) obj;
sl@0
   158
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   159
sl@0
   160
    M3G_ASSIGN_REF(appearance->compositingMode, NULL);
sl@0
   161
    M3G_ASSIGN_REF(appearance->fog,             NULL);
sl@0
   162
    M3G_ASSIGN_REF(appearance->material,        NULL);
sl@0
   163
    M3G_ASSIGN_REF(appearance->polygonMode,     NULL);
sl@0
   164
    for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
sl@0
   165
        M3G_ASSIGN_REF(appearance->texture[i], NULL);
sl@0
   166
    }
sl@0
   167
    
sl@0
   168
    m3gDestroyObject(obj);
sl@0
   169
}
sl@0
   170
sl@0
   171
/*!
sl@0
   172
 * \internal
sl@0
   173
 * \brief Applies Apperance settings to current OpenGL state
sl@0
   174
 *
sl@0
   175
 * \note m3gReleaseTextures must be called when no longer using this,
sl@0
   176
 * to properly reset texture usage counters and unmap the texture
sl@0
   177
 * images.
sl@0
   178
 * 
sl@0
   179
 * \param appearance    Appearance object
sl@0
   180
 * \param alphaFactor   alpha factor as 1.16 fixed point
sl@0
   181
 */
sl@0
   182
static void m3gApplyAppearance(const Appearance *appearance,
sl@0
   183
							   RenderContext *ctx,
sl@0
   184
                               M3Gint alphaFactor)
sl@0
   185
{
sl@0
   186
    M3G_ASSERT_GL;
sl@0
   187
sl@0
   188
    if (appearance != NULL) {
sl@0
   189
        int i;
sl@0
   190
sl@0
   191
#       if defined(M3G_NGL_TEXTURE_API)
sl@0
   192
        m3gLockMemory(M3G_INTERFACE(appearance)); /* for textures */
sl@0
   193
#       endif
sl@0
   194
    
sl@0
   195
        m3gApplyCompositingMode(appearance->compositingMode, ctx);
sl@0
   196
        m3gApplyPolygonMode(appearance->polygonMode);
sl@0
   197
        m3gApplyMaterial(appearance->material, alphaFactor);
sl@0
   198
        m3gApplyFog(appearance->fog);
sl@0
   199
sl@0
   200
        for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
sl@0
   201
            Texture *tex = appearance->texture[i];
sl@0
   202
            glActiveTexture(GL_TEXTURE0 + i);
sl@0
   203
            if (tex != NULL) {
sl@0
   204
                glEnable(GL_TEXTURE_2D);
sl@0
   205
                m3gBindTexture(appearance->texture[i]);
sl@0
   206
            }
sl@0
   207
            else {
sl@0
   208
                glDisable(GL_TEXTURE_2D);
sl@0
   209
            }
sl@0
   210
        }
sl@0
   211
    }
sl@0
   212
    else {
sl@0
   213
        m3gApplyAppearanceDefaults(ctx);
sl@0
   214
    }
sl@0
   215
sl@0
   216
    M3G_ASSERT_GL;
sl@0
   217
}
sl@0
   218
sl@0
   219
/*!
sl@0
   220
 * \internal
sl@0
   221
 * \brief Release the textures bound for this appearance
sl@0
   222
 */
sl@0
   223
static void m3gReleaseTextures(const Appearance *appearance)
sl@0
   224
{
sl@0
   225
    if (appearance != NULL) {
sl@0
   226
        int i;
sl@0
   227
sl@0
   228
        for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
sl@0
   229
            Texture *tex = appearance->texture[i];
sl@0
   230
            if (tex != NULL) {
sl@0
   231
                m3gReleaseTexture(tex);
sl@0
   232
            }
sl@0
   233
        }
sl@0
   234
sl@0
   235
#       if defined(M3G_NGL_TEXTURE_API)
sl@0
   236
        m3gUnlockMemory(M3G_INTERFACE(appearance));
sl@0
   237
#       endif
sl@0
   238
    }
sl@0
   239
}
sl@0
   240
sl@0
   241
/*!
sl@0
   242
 * \internal
sl@0
   243
 * \brief Overloaded Object3D method.
sl@0
   244
 *
sl@0
   245
 * \param self Appearance object
sl@0
   246
 * \param time current world time
sl@0
   247
 * \return minimum validity
sl@0
   248
 */
sl@0
   249
static M3Gint m3gAppearanceApplyAnimation(Object *self, M3Gint time) {
sl@0
   250
    M3Gint i, validity, minValidity = 0x7fffffff;
sl@0
   251
    Appearance *appearance = (Appearance *)self;
sl@0
   252
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   253
sl@0
   254
    if (appearance->compositingMode != NULL) {
sl@0
   255
        validity = M3G_VFUNC(Object, appearance->compositingMode, applyAnimation)((Object *)appearance->compositingMode, time);
sl@0
   256
        minValidity = (validity < minValidity ? validity : minValidity);
sl@0
   257
    }
sl@0
   258
    if (appearance->fog != NULL) {
sl@0
   259
        validity = M3G_VFUNC(Object, appearance->fog, applyAnimation)((Object *)appearance->fog, time);
sl@0
   260
        minValidity = (validity < minValidity ? validity : minValidity);
sl@0
   261
    }
sl@0
   262
    if (appearance->material != NULL) {
sl@0
   263
        validity = M3G_VFUNC(Object, appearance->material, applyAnimation)((Object *)appearance->material, time);
sl@0
   264
        minValidity = (validity < minValidity ? validity : minValidity);
sl@0
   265
    }
sl@0
   266
    for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
sl@0
   267
        if (appearance->texture[i] != NULL) {
sl@0
   268
            validity = M3G_VFUNC(Object, appearance->texture[i], applyAnimation)((Object *)appearance->texture[i], time);
sl@0
   269
            minValidity = (validity < minValidity ? validity : minValidity);
sl@0
   270
        }
sl@0
   271
    }
sl@0
   272
sl@0
   273
    /* no animations can target an Appearance directly, so we need
sl@0
   274
       not call super.applyAnimation() here. */
sl@0
   275
    return minValidity;
sl@0
   276
}    
sl@0
   277
sl@0
   278
/*!
sl@0
   279
 * \internal
sl@0
   280
 * \brief Overloaded Object3D method.
sl@0
   281
 */
sl@0
   282
static Object *m3gAppearanceFindID(Object *self, M3Gint userID)
sl@0
   283
{
sl@0
   284
    int i;
sl@0
   285
    Appearance *app = (Appearance *)self;
sl@0
   286
    Object *found = m3gObjectFindID(self, userID);
sl@0
   287
    
sl@0
   288
    if (!found && app->compositingMode) {
sl@0
   289
        found = m3gFindID((Object*) app->compositingMode, userID);
sl@0
   290
    }
sl@0
   291
    if (!found && app->polygonMode) {
sl@0
   292
        found = m3gFindID((Object*) app->polygonMode, userID);
sl@0
   293
    }
sl@0
   294
    if (!found && app->fog) {
sl@0
   295
        found = m3gFindID((Object*) app->fog, userID);
sl@0
   296
    }
sl@0
   297
    if (!found && app->material) {
sl@0
   298
        found = m3gFindID((Object*) app->material, userID);
sl@0
   299
    }
sl@0
   300
    for (i = 0; !found && i < M3G_NUM_TEXTURE_UNITS; ++i) {
sl@0
   301
        if (app->texture[i]) {
sl@0
   302
            found = m3gFindID((Object*) app->texture[i], userID);
sl@0
   303
        }
sl@0
   304
    }
sl@0
   305
    return found;
sl@0
   306
}
sl@0
   307
sl@0
   308
/*!
sl@0
   309
 * \internal
sl@0
   310
 * \brief Overloaded Object3D method.
sl@0
   311
 *
sl@0
   312
 * \param self Appearance object
sl@0
   313
 * \param references array of reference objects
sl@0
   314
 * \return number of references
sl@0
   315
 */
sl@0
   316
static M3Gint m3gAppearanceDoGetReferences(Object *self, Object **references)
sl@0
   317
{
sl@0
   318
    Appearance *app = (Appearance *)self;
sl@0
   319
    M3Gint i, num = m3gObjectDoGetReferences(self, references);
sl@0
   320
    if (app->compositingMode != NULL) {
sl@0
   321
        if (references != NULL)
sl@0
   322
            references[num] = (Object *)app->compositingMode;
sl@0
   323
        num++;
sl@0
   324
    }
sl@0
   325
    if (app->polygonMode != NULL) {
sl@0
   326
        if (references != NULL)
sl@0
   327
            references[num] = (Object *)app->polygonMode;
sl@0
   328
        num++;
sl@0
   329
    }
sl@0
   330
    if (app->fog != NULL) {
sl@0
   331
        if (references != NULL)
sl@0
   332
            references[num] = (Object *)app->fog;
sl@0
   333
        num++;
sl@0
   334
    }
sl@0
   335
    if (app->material != NULL) {
sl@0
   336
        if (references != NULL)
sl@0
   337
            references[num] = (Object *)app->material;
sl@0
   338
        num++;
sl@0
   339
    }
sl@0
   340
    for (i = 0; i < M3G_NUM_TEXTURE_UNITS; i++) {
sl@0
   341
        if (app->texture[i] != NULL) {
sl@0
   342
            if (references != NULL)
sl@0
   343
                references[num] = (Object *)app->texture[i];
sl@0
   344
            num++;
sl@0
   345
        }
sl@0
   346
    }
sl@0
   347
    return num;
sl@0
   348
}
sl@0
   349
sl@0
   350
sl@0
   351
/*!
sl@0
   352
 * \internal
sl@0
   353
 * \brief Overloaded Object3D method.
sl@0
   354
 *
sl@0
   355
 * \param originalObj original Appearance object
sl@0
   356
 * \param cloneObj pointer to cloned Appearance object
sl@0
   357
 * \param pairs array for all object-duplicate pairs
sl@0
   358
 * \param numPairs number of pairs
sl@0
   359
 */
sl@0
   360
static M3Gbool m3gAppearanceDuplicate(const Object *originalObj,
sl@0
   361
                                      Object **cloneObj,
sl@0
   362
                                      Object **pairs,
sl@0
   363
                                      M3Gint *numPairs)
sl@0
   364
{
sl@0
   365
    M3Gint i;
sl@0
   366
    Appearance *original = (Appearance *)originalObj;
sl@0
   367
    Appearance *clone = (Appearance *)m3gCreateAppearance(originalObj->interface);
sl@0
   368
    *cloneObj = (Object *)clone;
sl@0
   369
    if (*cloneObj == NULL) {
sl@0
   370
        return M3G_FALSE;
sl@0
   371
    }
sl@0
   372
sl@0
   373
    if (m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
sl@0
   374
        clone->layer = original->layer;
sl@0
   375
    
sl@0
   376
        M3G_ASSIGN_REF(clone->compositingMode, original->compositingMode);
sl@0
   377
        M3G_ASSIGN_REF(clone->fog, original->fog);
sl@0
   378
        M3G_ASSIGN_REF(clone->polygonMode, original->polygonMode);
sl@0
   379
        M3G_ASSIGN_REF(clone->material, original->material);
sl@0
   380
        for (i = 0; i < M3G_NUM_TEXTURE_UNITS; i++) {
sl@0
   381
            M3G_ASSIGN_REF(clone->texture[i], original->texture[i]);
sl@0
   382
        }
sl@0
   383
sl@0
   384
        m3gRegenerateSortKey(clone);
sl@0
   385
        
sl@0
   386
        return M3G_TRUE;
sl@0
   387
    }
sl@0
   388
    else {
sl@0
   389
        return M3G_FALSE;
sl@0
   390
    }
sl@0
   391
}
sl@0
   392
sl@0
   393
/*----------------------------------------------------------------------
sl@0
   394
 * Virtual function table
sl@0
   395
 *--------------------------------------------------------------------*/
sl@0
   396
sl@0
   397
static const ObjectVFTable m3gvf_Appearance = {
sl@0
   398
    m3gAppearanceApplyAnimation,
sl@0
   399
    m3gObjectIsCompatible,
sl@0
   400
    m3gObjectUpdateProperty,
sl@0
   401
    m3gAppearanceDoGetReferences,
sl@0
   402
    m3gAppearanceFindID,
sl@0
   403
    m3gAppearanceDuplicate,
sl@0
   404
    m3gDestroyAppearance
sl@0
   405
};
sl@0
   406
sl@0
   407
sl@0
   408
/*----------------------------------------------------------------------
sl@0
   409
 * Public API functions
sl@0
   410
 *--------------------------------------------------------------------*/
sl@0
   411
sl@0
   412
/*!
sl@0
   413
 * \brief Creates a new Appearance with default values
sl@0
   414
 *
sl@0
   415
 * \param hInterface            M3G interface
sl@0
   416
 * \retval Appearance new Appearance object
sl@0
   417
 * \retval NULL Appearance creating failed
sl@0
   418
 */
sl@0
   419
/*@access M3GInterface@*/
sl@0
   420
/*@access M3GAppearance@*/
sl@0
   421
M3G_API M3GAppearance m3gCreateAppearance(M3GInterface hInterface)
sl@0
   422
{
sl@0
   423
    Interface *m3g = (Interface *) hInterface;
sl@0
   424
    M3G_VALIDATE_INTERFACE(m3g);
sl@0
   425
    {
sl@0
   426
        Appearance *appearance = m3gAllocZ(m3g, sizeof(Appearance));
sl@0
   427
sl@0
   428
        if (appearance != NULL) {
sl@0
   429
    		m3gInitObject(&appearance->object, m3g, M3G_CLASS_APPEARANCE);
sl@0
   430
            m3gRegenerateSortKey(appearance);
sl@0
   431
        }
sl@0
   432
        
sl@0
   433
        return (M3GAppearance) appearance;
sl@0
   434
    }
sl@0
   435
}
sl@0
   436
sl@0
   437
/*!
sl@0
   438
 * \brief Get compositing mode
sl@0
   439
 *
sl@0
   440
 * \param hAppearance Appearance object
sl@0
   441
 * \return CompositingMode object
sl@0
   442
 */
sl@0
   443
M3G_API M3GCompositingMode m3gGetCompositingMode(M3GAppearance hAppearance)
sl@0
   444
{
sl@0
   445
    const Appearance *appearance = (const Appearance *) hAppearance;
sl@0
   446
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   447
    return (M3GCompositingMode)(appearance->compositingMode);
sl@0
   448
}
sl@0
   449
sl@0
   450
/*!
sl@0
   451
 * \brief Get fog
sl@0
   452
 *
sl@0
   453
 * \param hAppearance Appearance object
sl@0
   454
 * \return Fog object
sl@0
   455
 */
sl@0
   456
M3G_API M3GFog m3gGetFog(M3GAppearance hAppearance)
sl@0
   457
{
sl@0
   458
    const Appearance *appearance = (const Appearance *) hAppearance;
sl@0
   459
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   460
    return (M3GFog)(appearance->fog);
sl@0
   461
}
sl@0
   462
sl@0
   463
/*!
sl@0
   464
 * \brief Get material
sl@0
   465
 *
sl@0
   466
 * \param hAppearance Appearance object
sl@0
   467
 * \return Material object
sl@0
   468
 */
sl@0
   469
M3G_API M3GMaterial m3gGetMaterial(M3GAppearance hAppearance)
sl@0
   470
{
sl@0
   471
    const Appearance *appearance = (const Appearance *) hAppearance;
sl@0
   472
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   473
    return (M3GMaterial)(appearance->material);
sl@0
   474
}
sl@0
   475
sl@0
   476
/*!
sl@0
   477
 * \brief Get polygon mode
sl@0
   478
 *
sl@0
   479
 * \param hAppearance Appearance object
sl@0
   480
 * \return PolygonMode object
sl@0
   481
 */
sl@0
   482
M3G_API M3GPolygonMode m3gGetPolygonMode(M3GAppearance hAppearance)
sl@0
   483
{
sl@0
   484
    const Appearance *appearance = (const Appearance *) hAppearance;
sl@0
   485
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   486
    return (M3GPolygonMode)(appearance->polygonMode);
sl@0
   487
}
sl@0
   488
sl@0
   489
/*!
sl@0
   490
 * \brief Get texture
sl@0
   491
 *
sl@0
   492
 * \param hAppearance Appearance object
sl@0
   493
 * \param unit texturing unit
sl@0
   494
 * \return Texture2D object
sl@0
   495
 */
sl@0
   496
M3G_API M3GTexture m3gGetTexture(M3GAppearance hAppearance, M3Gint unit)
sl@0
   497
{
sl@0
   498
    const Appearance *appearance = (const Appearance *) hAppearance;
sl@0
   499
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   500
    if (!m3gInRange(unit, 0, M3G_NUM_TEXTURE_UNITS - 1)) {
sl@0
   501
        m3gRaiseError(M3G_INTERFACE(appearance), M3G_INVALID_INDEX);
sl@0
   502
        return (M3GTexture) NULL;
sl@0
   503
    }
sl@0
   504
    return (M3GTexture)(appearance->texture[unit]);
sl@0
   505
}
sl@0
   506
sl@0
   507
/*!
sl@0
   508
 * \brief Get layer
sl@0
   509
 *
sl@0
   510
 * \param hAppearance Appearance object
sl@0
   511
 * \return layer number
sl@0
   512
 */
sl@0
   513
M3G_API M3Gint m3gGetLayer(M3GAppearance hAppearance)
sl@0
   514
{
sl@0
   515
    const Appearance *appearance = (const Appearance *) hAppearance;
sl@0
   516
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   517
    return appearance->layer;
sl@0
   518
}
sl@0
   519
sl@0
   520
/*!
sl@0
   521
 * \brief Set compositing mode
sl@0
   522
 *
sl@0
   523
 * \param hAppearance Appearance object
sl@0
   524
 * \param hMode CompositingMode object
sl@0
   525
 */
sl@0
   526
M3G_API void m3gSetCompositingMode(M3GAppearance hAppearance,
sl@0
   527
                                   M3GCompositingMode hMode)
sl@0
   528
{
sl@0
   529
    Appearance *appearance = (Appearance *) hAppearance;
sl@0
   530
    CompositingMode *mode = (CompositingMode *) hMode;
sl@0
   531
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   532
    
sl@0
   533
    M3G_ASSIGN_REF(appearance->compositingMode, mode);
sl@0
   534
sl@0
   535
    m3gRegenerateSortKey(appearance);
sl@0
   536
}
sl@0
   537
sl@0
   538
/*!
sl@0
   539
 * \brief Set polygon mode
sl@0
   540
 *
sl@0
   541
 * \param hAppearance Appearance object
sl@0
   542
 * \param hMode PolygonMode object
sl@0
   543
 */
sl@0
   544
M3G_API void m3gSetPolygonMode(M3GAppearance hAppearance,
sl@0
   545
                               M3GPolygonMode hMode)
sl@0
   546
{
sl@0
   547
    Appearance *appearance = (Appearance *) hAppearance;
sl@0
   548
    PolygonMode *mode = (PolygonMode *) hMode;
sl@0
   549
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   550
sl@0
   551
    M3G_ASSIGN_REF(appearance->polygonMode, mode);
sl@0
   552
sl@0
   553
    m3gRegenerateSortKey(appearance);
sl@0
   554
}
sl@0
   555
sl@0
   556
/*!
sl@0
   557
 * \brief Set layer
sl@0
   558
 *
sl@0
   559
 * \param hAppearance Appearance object
sl@0
   560
 * \param layer layer number
sl@0
   561
 */
sl@0
   562
M3G_API void m3gSetLayer(M3GAppearance hAppearance, M3Gint layer)
sl@0
   563
{
sl@0
   564
    Appearance *appearance = (Appearance *) hAppearance;
sl@0
   565
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   566
sl@0
   567
    /* Check for errors */
sl@0
   568
    if (!m3gInRange(layer, M3G_APPEARANCE_MIN_LAYER, M3G_APPEARANCE_MAX_LAYER)) {
sl@0
   569
        m3gRaiseError(M3G_INTERFACE(appearance), M3G_INVALID_INDEX);
sl@0
   570
        return;
sl@0
   571
    }
sl@0
   572
sl@0
   573
    appearance->layer = (M3Gshort) layer;
sl@0
   574
    
sl@0
   575
    m3gRegenerateSortKey(appearance);
sl@0
   576
}
sl@0
   577
sl@0
   578
/*!
sl@0
   579
 * \brief Set material
sl@0
   580
 *
sl@0
   581
 * \param hAppearance Appearance object
sl@0
   582
 * \param hMaterial Material object
sl@0
   583
 */
sl@0
   584
M3G_API void m3gSetMaterial(M3GAppearance hAppearance,
sl@0
   585
                            M3GMaterial hMaterial)
sl@0
   586
{
sl@0
   587
    Appearance *appearance = (Appearance *) hAppearance;
sl@0
   588
    Material *material = (Material *) hMaterial;
sl@0
   589
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   590
sl@0
   591
    M3G_ASSIGN_REF(appearance->material, material);
sl@0
   592
    
sl@0
   593
    if (material != NULL) {
sl@0
   594
        appearance->vertexMask |= (M3Gushort)M3G_NORMAL_BIT;
sl@0
   595
    }
sl@0
   596
    else {
sl@0
   597
        appearance->vertexMask &= ~(M3Gushort)M3G_NORMAL_BIT;
sl@0
   598
    }
sl@0
   599
sl@0
   600
    m3gRegenerateSortKey(appearance);
sl@0
   601
}
sl@0
   602
sl@0
   603
/*!
sl@0
   604
 * \brief Set texture
sl@0
   605
 *
sl@0
   606
 * \param hAppearance Appearance object
sl@0
   607
 * \param unit texturing unit
sl@0
   608
 * \param hTexture Texture2D object
sl@0
   609
 */
sl@0
   610
M3G_API void m3gSetTexture(M3GAppearance hAppearance,
sl@0
   611
                           M3Gint unit, M3GTexture hTexture)
sl@0
   612
{
sl@0
   613
    Appearance *appearance = (Appearance *) hAppearance;
sl@0
   614
    Texture *texture = (Texture *) hTexture;
sl@0
   615
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   616
    
sl@0
   617
    if (!m3gInRange(unit, 0, M3G_NUM_TEXTURE_UNITS - 1)) {
sl@0
   618
        m3gRaiseError(M3G_INTERFACE(appearance), M3G_INVALID_INDEX);
sl@0
   619
        return;
sl@0
   620
    }
sl@0
   621
    
sl@0
   622
    M3G_ASSIGN_REF(appearance->texture[unit], texture);
sl@0
   623
    
sl@0
   624
    if (texture != NULL) {
sl@0
   625
        appearance->vertexMask |= (M3Gushort) (M3G_TEXCOORD0_BIT << unit);
sl@0
   626
    }
sl@0
   627
    else {
sl@0
   628
        appearance->vertexMask &= (M3Gushort) ~(M3G_TEXCOORD0_BIT << unit);
sl@0
   629
    }
sl@0
   630
sl@0
   631
    m3gRegenerateSortKey(appearance);
sl@0
   632
}
sl@0
   633
sl@0
   634
/*!
sl@0
   635
 * \brief Set fog
sl@0
   636
 *
sl@0
   637
 * \param hAppearance Appearance object
sl@0
   638
 * \param hFog Fog object
sl@0
   639
 */
sl@0
   640
M3G_API void m3gSetFog(M3GAppearance hAppearance, M3GFog hFog)
sl@0
   641
{
sl@0
   642
    Appearance *appearance = (Appearance *) hAppearance;
sl@0
   643
    M3G_VALIDATE_OBJECT(appearance);
sl@0
   644
	
sl@0
   645
	M3G_ASSIGN_REF(appearance->fog, hFog);
sl@0
   646
sl@0
   647
    m3gRegenerateSortKey(appearance);
sl@0
   648
}
sl@0
   649