os/graphics/m3g/m3gcore11/src/m3g_appearance.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/m3g/m3gcore11/src/m3g_appearance.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,649 @@
     1.4 +/*
     1.5 +* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +* All rights reserved.
     1.7 +* This component and the accompanying materials are made available
     1.8 +* under the terms of the License "Eclipse Public License v1.0"
     1.9 +* which accompanies this distribution, and is available
    1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +*
    1.12 +* Initial Contributors:
    1.13 +* Nokia Corporation - initial contribution.
    1.14 +*
    1.15 +* Contributors:
    1.16 +*
    1.17 +* Description: Appearance implementation
    1.18 +*
    1.19 +*/
    1.20 +
    1.21 +
    1.22 +/*!
    1.23 + * \internal
    1.24 + * \file
    1.25 + * \brief Appearance implementation
    1.26 + */
    1.27 +
    1.28 +#ifndef M3G_CORE_INCLUDE
    1.29 +#   error included by m3g_core.c; do not compile separately.
    1.30 +#endif
    1.31 +
    1.32 +#include "m3g_appearance.h"
    1.33 +#include "m3g_vertexbuffer.h"
    1.34 +
    1.35 +/*----------------------------------------------------------------------
    1.36 + * Private functions
    1.37 + *--------------------------------------------------------------------*/
    1.38 +
    1.39 +/*!
    1.40 + * \internal
    1.41 + * \brief Applies default appearance values to OpenGL.
    1.42 + */
    1.43 +static void m3gApplyAppearanceDefaults(RenderContext *ctx)
    1.44 +{
    1.45 +    int i;
    1.46 +    m3gApplyCompositingMode(NULL, ctx);
    1.47 +    m3gApplyPolygonMode(NULL);
    1.48 +    m3gApplyMaterial(NULL, 0x10000);
    1.49 +	m3gApplyFog(NULL);
    1.50 +
    1.51 +    for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
    1.52 +        glActiveTexture(GL_TEXTURE0 + i);
    1.53 +        glDisable(GL_TEXTURE_2D);
    1.54 +    }
    1.55 +}
    1.56 +
    1.57 +/*!
    1.58 + * \internal
    1.59 + * \brief Generate a hash number for a pointer
    1.60 + */
    1.61 +static M3Guint m3gGenPointerHash(const void *ptr)
    1.62 +{
    1.63 +    M3Guint p = ((M3Guint) ptr) >> 2;
    1.64 +    M3Guint key = p ^ (p >> 5) ^ (p >> 10) ^ (p >> 15) ^ (p >> 20) ^ (p >> 25);
    1.65 +    return key;
    1.66 +}
    1.67 +
    1.68 +/*!
    1.69 + * \internal
    1.70 + * \brief Generate a quick hash bit pattern for the textures of this
    1.71 + * appearance object
    1.72 + */
    1.73 +static M3Guint m3gGen12BitTextureHash(const Appearance *app)
    1.74 +{
    1.75 +    M3Guint key = 0; 
    1.76 +	
    1.77 +    int i;
    1.78 +    
    1.79 +    for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
    1.80 +        const Texture *tex = app->texture[i];
    1.81 +        if (tex) {
    1.82 +            key ^= (m3gGenPointerHash(m3gGetTextureImage((M3GTexture)tex)) >> i) << 6;
    1.83 +            key ^= (m3gGenPointerHash(tex) >> i) & 0x3Fu;
    1.84 +        }
    1.85 +    }
    1.86 +    return key & ((1u<<12)-1);
    1.87 +}
    1.88 +
    1.89 +/*!
    1.90 + * \internal
    1.91 + * \brief Generate the sorting key for render queue
    1.92 + *
    1.93 + * Sort key is a combination of user settable layer and
    1.94 + * blending mode. Blended objects are always drawn last.
    1.95 + *
    1.96 + * \param appearance    Appearance object
    1.97 + * \return              sort key
    1.98 + */
    1.99 +static void m3gRegenerateSortKey(Appearance *appearance)
   1.100 +{
   1.101 +	M3Guint key = 0;
   1.102 +    M3G_VALIDATE_OBJECT(appearance);
   1.103 +
   1.104 +    /*------------------------------------------------------------
   1.105 +     * First do the mandatory sorting by layer index and blending
   1.106 +     * state; this currently uses the top eight bits, 31..24
   1.107 +     *-----------------------------------------------------------*/
   1.108 +        
   1.109 +    key = (appearance->layer - M3G_APPEARANCE_MIN_LAYER)
   1.110 +        << (33 - M3G_APPEARANCE_HARD_SORT_BITS);
   1.111 +    
   1.112 +    /* NOTE the blending state bit is not set here, but dynamically in
   1.113 +     * m3gGetAppearanceSortKey; this way we do not need to implement
   1.114 +     * signaling from CompositingMode to Appearance when the blending
   1.115 +     * state changes */
   1.116 +
   1.117 +    /*-----------------------------------------------------------------
   1.118 +     * The rest of the bits, 23..0, affect performance only; ideally,
   1.119 +     * these should be sorted so that the more expensive state is in the
   1.120 +     * higher bits, but this is largely dependent on the hardware
   1.121 +     *----------------------------------------------------------------*/
   1.122 +
   1.123 +    /* Texturing changes are often expensive in graphics hardware, so
   1.124 +     * we put a hash of the texture objects into the top twelve
   1.125 +     * bits
   1.126 +     *
   1.127 +     * NOTE we do not currently update this if a texture image
   1.128 +     * changes, but that shouldn't happen too often and only has
   1.129 +     * relatively minor performance implications
   1.130 +     */
   1.131 +
   1.132 +    key |= m3gGen12BitTextureHash(appearance) << 12;
   1.133 +
   1.134 +    /* Use the rest of the bits for the various components; depth
   1.135 +     * function changes are another potentially costly operation, so
   1.136 +     * put that next */
   1.137 +
   1.138 +    key |= (m3gGenPointerHash(appearance->compositingMode) & 0x0Fu) << 8;
   1.139 +    key |= (m3gGenPointerHash(appearance->material) & 0x07u) << 5;
   1.140 +    key |= (m3gGenPointerHash(appearance->polygonMode) & 0x07u) << 2;
   1.141 +    key |= (m3gGenPointerHash(appearance->fog) & 0x03u);
   1.142 +    
   1.143 +    /* Store the final value */
   1.144 +    appearance->sortKey = key;
   1.145 +}
   1.146 +
   1.147 +/*----------------------------------------------------------------------
   1.148 + * Internal functions
   1.149 + *--------------------------------------------------------------------*/
   1.150 +
   1.151 +/*!
   1.152 + * \internal
   1.153 + * \brief Destroys this Appearance object.
   1.154 + *
   1.155 + * \param obj Appearance object
   1.156 + */
   1.157 +static void m3gDestroyAppearance(Object *obj)
   1.158 +{
   1.159 +    int i;
   1.160 +    Appearance *appearance = (Appearance *) obj;
   1.161 +    M3G_VALIDATE_OBJECT(appearance);
   1.162 +
   1.163 +    M3G_ASSIGN_REF(appearance->compositingMode, NULL);
   1.164 +    M3G_ASSIGN_REF(appearance->fog,             NULL);
   1.165 +    M3G_ASSIGN_REF(appearance->material,        NULL);
   1.166 +    M3G_ASSIGN_REF(appearance->polygonMode,     NULL);
   1.167 +    for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
   1.168 +        M3G_ASSIGN_REF(appearance->texture[i], NULL);
   1.169 +    }
   1.170 +    
   1.171 +    m3gDestroyObject(obj);
   1.172 +}
   1.173 +
   1.174 +/*!
   1.175 + * \internal
   1.176 + * \brief Applies Apperance settings to current OpenGL state
   1.177 + *
   1.178 + * \note m3gReleaseTextures must be called when no longer using this,
   1.179 + * to properly reset texture usage counters and unmap the texture
   1.180 + * images.
   1.181 + * 
   1.182 + * \param appearance    Appearance object
   1.183 + * \param alphaFactor   alpha factor as 1.16 fixed point
   1.184 + */
   1.185 +static void m3gApplyAppearance(const Appearance *appearance,
   1.186 +							   RenderContext *ctx,
   1.187 +                               M3Gint alphaFactor)
   1.188 +{
   1.189 +    M3G_ASSERT_GL;
   1.190 +
   1.191 +    if (appearance != NULL) {
   1.192 +        int i;
   1.193 +
   1.194 +#       if defined(M3G_NGL_TEXTURE_API)
   1.195 +        m3gLockMemory(M3G_INTERFACE(appearance)); /* for textures */
   1.196 +#       endif
   1.197 +    
   1.198 +        m3gApplyCompositingMode(appearance->compositingMode, ctx);
   1.199 +        m3gApplyPolygonMode(appearance->polygonMode);
   1.200 +        m3gApplyMaterial(appearance->material, alphaFactor);
   1.201 +        m3gApplyFog(appearance->fog);
   1.202 +
   1.203 +        for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
   1.204 +            Texture *tex = appearance->texture[i];
   1.205 +            glActiveTexture(GL_TEXTURE0 + i);
   1.206 +            if (tex != NULL) {
   1.207 +                glEnable(GL_TEXTURE_2D);
   1.208 +                m3gBindTexture(appearance->texture[i]);
   1.209 +            }
   1.210 +            else {
   1.211 +                glDisable(GL_TEXTURE_2D);
   1.212 +            }
   1.213 +        }
   1.214 +    }
   1.215 +    else {
   1.216 +        m3gApplyAppearanceDefaults(ctx);
   1.217 +    }
   1.218 +
   1.219 +    M3G_ASSERT_GL;
   1.220 +}
   1.221 +
   1.222 +/*!
   1.223 + * \internal
   1.224 + * \brief Release the textures bound for this appearance
   1.225 + */
   1.226 +static void m3gReleaseTextures(const Appearance *appearance)
   1.227 +{
   1.228 +    if (appearance != NULL) {
   1.229 +        int i;
   1.230 +
   1.231 +        for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
   1.232 +            Texture *tex = appearance->texture[i];
   1.233 +            if (tex != NULL) {
   1.234 +                m3gReleaseTexture(tex);
   1.235 +            }
   1.236 +        }
   1.237 +
   1.238 +#       if defined(M3G_NGL_TEXTURE_API)
   1.239 +        m3gUnlockMemory(M3G_INTERFACE(appearance));
   1.240 +#       endif
   1.241 +    }
   1.242 +}
   1.243 +
   1.244 +/*!
   1.245 + * \internal
   1.246 + * \brief Overloaded Object3D method.
   1.247 + *
   1.248 + * \param self Appearance object
   1.249 + * \param time current world time
   1.250 + * \return minimum validity
   1.251 + */
   1.252 +static M3Gint m3gAppearanceApplyAnimation(Object *self, M3Gint time) {
   1.253 +    M3Gint i, validity, minValidity = 0x7fffffff;
   1.254 +    Appearance *appearance = (Appearance *)self;
   1.255 +    M3G_VALIDATE_OBJECT(appearance);
   1.256 +
   1.257 +    if (appearance->compositingMode != NULL) {
   1.258 +        validity = M3G_VFUNC(Object, appearance->compositingMode, applyAnimation)((Object *)appearance->compositingMode, time);
   1.259 +        minValidity = (validity < minValidity ? validity : minValidity);
   1.260 +    }
   1.261 +    if (appearance->fog != NULL) {
   1.262 +        validity = M3G_VFUNC(Object, appearance->fog, applyAnimation)((Object *)appearance->fog, time);
   1.263 +        minValidity = (validity < minValidity ? validity : minValidity);
   1.264 +    }
   1.265 +    if (appearance->material != NULL) {
   1.266 +        validity = M3G_VFUNC(Object, appearance->material, applyAnimation)((Object *)appearance->material, time);
   1.267 +        minValidity = (validity < minValidity ? validity : minValidity);
   1.268 +    }
   1.269 +    for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
   1.270 +        if (appearance->texture[i] != NULL) {
   1.271 +            validity = M3G_VFUNC(Object, appearance->texture[i], applyAnimation)((Object *)appearance->texture[i], time);
   1.272 +            minValidity = (validity < minValidity ? validity : minValidity);
   1.273 +        }
   1.274 +    }
   1.275 +
   1.276 +    /* no animations can target an Appearance directly, so we need
   1.277 +       not call super.applyAnimation() here. */
   1.278 +    return minValidity;
   1.279 +}    
   1.280 +
   1.281 +/*!
   1.282 + * \internal
   1.283 + * \brief Overloaded Object3D method.
   1.284 + */
   1.285 +static Object *m3gAppearanceFindID(Object *self, M3Gint userID)
   1.286 +{
   1.287 +    int i;
   1.288 +    Appearance *app = (Appearance *)self;
   1.289 +    Object *found = m3gObjectFindID(self, userID);
   1.290 +    
   1.291 +    if (!found && app->compositingMode) {
   1.292 +        found = m3gFindID((Object*) app->compositingMode, userID);
   1.293 +    }
   1.294 +    if (!found && app->polygonMode) {
   1.295 +        found = m3gFindID((Object*) app->polygonMode, userID);
   1.296 +    }
   1.297 +    if (!found && app->fog) {
   1.298 +        found = m3gFindID((Object*) app->fog, userID);
   1.299 +    }
   1.300 +    if (!found && app->material) {
   1.301 +        found = m3gFindID((Object*) app->material, userID);
   1.302 +    }
   1.303 +    for (i = 0; !found && i < M3G_NUM_TEXTURE_UNITS; ++i) {
   1.304 +        if (app->texture[i]) {
   1.305 +            found = m3gFindID((Object*) app->texture[i], userID);
   1.306 +        }
   1.307 +    }
   1.308 +    return found;
   1.309 +}
   1.310 +
   1.311 +/*!
   1.312 + * \internal
   1.313 + * \brief Overloaded Object3D method.
   1.314 + *
   1.315 + * \param self Appearance object
   1.316 + * \param references array of reference objects
   1.317 + * \return number of references
   1.318 + */
   1.319 +static M3Gint m3gAppearanceDoGetReferences(Object *self, Object **references)
   1.320 +{
   1.321 +    Appearance *app = (Appearance *)self;
   1.322 +    M3Gint i, num = m3gObjectDoGetReferences(self, references);
   1.323 +    if (app->compositingMode != NULL) {
   1.324 +        if (references != NULL)
   1.325 +            references[num] = (Object *)app->compositingMode;
   1.326 +        num++;
   1.327 +    }
   1.328 +    if (app->polygonMode != NULL) {
   1.329 +        if (references != NULL)
   1.330 +            references[num] = (Object *)app->polygonMode;
   1.331 +        num++;
   1.332 +    }
   1.333 +    if (app->fog != NULL) {
   1.334 +        if (references != NULL)
   1.335 +            references[num] = (Object *)app->fog;
   1.336 +        num++;
   1.337 +    }
   1.338 +    if (app->material != NULL) {
   1.339 +        if (references != NULL)
   1.340 +            references[num] = (Object *)app->material;
   1.341 +        num++;
   1.342 +    }
   1.343 +    for (i = 0; i < M3G_NUM_TEXTURE_UNITS; i++) {
   1.344 +        if (app->texture[i] != NULL) {
   1.345 +            if (references != NULL)
   1.346 +                references[num] = (Object *)app->texture[i];
   1.347 +            num++;
   1.348 +        }
   1.349 +    }
   1.350 +    return num;
   1.351 +}
   1.352 +
   1.353 +
   1.354 +/*!
   1.355 + * \internal
   1.356 + * \brief Overloaded Object3D method.
   1.357 + *
   1.358 + * \param originalObj original Appearance object
   1.359 + * \param cloneObj pointer to cloned Appearance object
   1.360 + * \param pairs array for all object-duplicate pairs
   1.361 + * \param numPairs number of pairs
   1.362 + */
   1.363 +static M3Gbool m3gAppearanceDuplicate(const Object *originalObj,
   1.364 +                                      Object **cloneObj,
   1.365 +                                      Object **pairs,
   1.366 +                                      M3Gint *numPairs)
   1.367 +{
   1.368 +    M3Gint i;
   1.369 +    Appearance *original = (Appearance *)originalObj;
   1.370 +    Appearance *clone = (Appearance *)m3gCreateAppearance(originalObj->interface);
   1.371 +    *cloneObj = (Object *)clone;
   1.372 +    if (*cloneObj == NULL) {
   1.373 +        return M3G_FALSE;
   1.374 +    }
   1.375 +
   1.376 +    if (m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
   1.377 +        clone->layer = original->layer;
   1.378 +    
   1.379 +        M3G_ASSIGN_REF(clone->compositingMode, original->compositingMode);
   1.380 +        M3G_ASSIGN_REF(clone->fog, original->fog);
   1.381 +        M3G_ASSIGN_REF(clone->polygonMode, original->polygonMode);
   1.382 +        M3G_ASSIGN_REF(clone->material, original->material);
   1.383 +        for (i = 0; i < M3G_NUM_TEXTURE_UNITS; i++) {
   1.384 +            M3G_ASSIGN_REF(clone->texture[i], original->texture[i]);
   1.385 +        }
   1.386 +
   1.387 +        m3gRegenerateSortKey(clone);
   1.388 +        
   1.389 +        return M3G_TRUE;
   1.390 +    }
   1.391 +    else {
   1.392 +        return M3G_FALSE;
   1.393 +    }
   1.394 +}
   1.395 +
   1.396 +/*----------------------------------------------------------------------
   1.397 + * Virtual function table
   1.398 + *--------------------------------------------------------------------*/
   1.399 +
   1.400 +static const ObjectVFTable m3gvf_Appearance = {
   1.401 +    m3gAppearanceApplyAnimation,
   1.402 +    m3gObjectIsCompatible,
   1.403 +    m3gObjectUpdateProperty,
   1.404 +    m3gAppearanceDoGetReferences,
   1.405 +    m3gAppearanceFindID,
   1.406 +    m3gAppearanceDuplicate,
   1.407 +    m3gDestroyAppearance
   1.408 +};
   1.409 +
   1.410 +
   1.411 +/*----------------------------------------------------------------------
   1.412 + * Public API functions
   1.413 + *--------------------------------------------------------------------*/
   1.414 +
   1.415 +/*!
   1.416 + * \brief Creates a new Appearance with default values
   1.417 + *
   1.418 + * \param hInterface            M3G interface
   1.419 + * \retval Appearance new Appearance object
   1.420 + * \retval NULL Appearance creating failed
   1.421 + */
   1.422 +/*@access M3GInterface@*/
   1.423 +/*@access M3GAppearance@*/
   1.424 +M3G_API M3GAppearance m3gCreateAppearance(M3GInterface hInterface)
   1.425 +{
   1.426 +    Interface *m3g = (Interface *) hInterface;
   1.427 +    M3G_VALIDATE_INTERFACE(m3g);
   1.428 +    {
   1.429 +        Appearance *appearance = m3gAllocZ(m3g, sizeof(Appearance));
   1.430 +
   1.431 +        if (appearance != NULL) {
   1.432 +    		m3gInitObject(&appearance->object, m3g, M3G_CLASS_APPEARANCE);
   1.433 +            m3gRegenerateSortKey(appearance);
   1.434 +        }
   1.435 +        
   1.436 +        return (M3GAppearance) appearance;
   1.437 +    }
   1.438 +}
   1.439 +
   1.440 +/*!
   1.441 + * \brief Get compositing mode
   1.442 + *
   1.443 + * \param hAppearance Appearance object
   1.444 + * \return CompositingMode object
   1.445 + */
   1.446 +M3G_API M3GCompositingMode m3gGetCompositingMode(M3GAppearance hAppearance)
   1.447 +{
   1.448 +    const Appearance *appearance = (const Appearance *) hAppearance;
   1.449 +    M3G_VALIDATE_OBJECT(appearance);
   1.450 +    return (M3GCompositingMode)(appearance->compositingMode);
   1.451 +}
   1.452 +
   1.453 +/*!
   1.454 + * \brief Get fog
   1.455 + *
   1.456 + * \param hAppearance Appearance object
   1.457 + * \return Fog object
   1.458 + */
   1.459 +M3G_API M3GFog m3gGetFog(M3GAppearance hAppearance)
   1.460 +{
   1.461 +    const Appearance *appearance = (const Appearance *) hAppearance;
   1.462 +    M3G_VALIDATE_OBJECT(appearance);
   1.463 +    return (M3GFog)(appearance->fog);
   1.464 +}
   1.465 +
   1.466 +/*!
   1.467 + * \brief Get material
   1.468 + *
   1.469 + * \param hAppearance Appearance object
   1.470 + * \return Material object
   1.471 + */
   1.472 +M3G_API M3GMaterial m3gGetMaterial(M3GAppearance hAppearance)
   1.473 +{
   1.474 +    const Appearance *appearance = (const Appearance *) hAppearance;
   1.475 +    M3G_VALIDATE_OBJECT(appearance);
   1.476 +    return (M3GMaterial)(appearance->material);
   1.477 +}
   1.478 +
   1.479 +/*!
   1.480 + * \brief Get polygon mode
   1.481 + *
   1.482 + * \param hAppearance Appearance object
   1.483 + * \return PolygonMode object
   1.484 + */
   1.485 +M3G_API M3GPolygonMode m3gGetPolygonMode(M3GAppearance hAppearance)
   1.486 +{
   1.487 +    const Appearance *appearance = (const Appearance *) hAppearance;
   1.488 +    M3G_VALIDATE_OBJECT(appearance);
   1.489 +    return (M3GPolygonMode)(appearance->polygonMode);
   1.490 +}
   1.491 +
   1.492 +/*!
   1.493 + * \brief Get texture
   1.494 + *
   1.495 + * \param hAppearance Appearance object
   1.496 + * \param unit texturing unit
   1.497 + * \return Texture2D object
   1.498 + */
   1.499 +M3G_API M3GTexture m3gGetTexture(M3GAppearance hAppearance, M3Gint unit)
   1.500 +{
   1.501 +    const Appearance *appearance = (const Appearance *) hAppearance;
   1.502 +    M3G_VALIDATE_OBJECT(appearance);
   1.503 +    if (!m3gInRange(unit, 0, M3G_NUM_TEXTURE_UNITS - 1)) {
   1.504 +        m3gRaiseError(M3G_INTERFACE(appearance), M3G_INVALID_INDEX);
   1.505 +        return (M3GTexture) NULL;
   1.506 +    }
   1.507 +    return (M3GTexture)(appearance->texture[unit]);
   1.508 +}
   1.509 +
   1.510 +/*!
   1.511 + * \brief Get layer
   1.512 + *
   1.513 + * \param hAppearance Appearance object
   1.514 + * \return layer number
   1.515 + */
   1.516 +M3G_API M3Gint m3gGetLayer(M3GAppearance hAppearance)
   1.517 +{
   1.518 +    const Appearance *appearance = (const Appearance *) hAppearance;
   1.519 +    M3G_VALIDATE_OBJECT(appearance);
   1.520 +    return appearance->layer;
   1.521 +}
   1.522 +
   1.523 +/*!
   1.524 + * \brief Set compositing mode
   1.525 + *
   1.526 + * \param hAppearance Appearance object
   1.527 + * \param hMode CompositingMode object
   1.528 + */
   1.529 +M3G_API void m3gSetCompositingMode(M3GAppearance hAppearance,
   1.530 +                                   M3GCompositingMode hMode)
   1.531 +{
   1.532 +    Appearance *appearance = (Appearance *) hAppearance;
   1.533 +    CompositingMode *mode = (CompositingMode *) hMode;
   1.534 +    M3G_VALIDATE_OBJECT(appearance);
   1.535 +    
   1.536 +    M3G_ASSIGN_REF(appearance->compositingMode, mode);
   1.537 +
   1.538 +    m3gRegenerateSortKey(appearance);
   1.539 +}
   1.540 +
   1.541 +/*!
   1.542 + * \brief Set polygon mode
   1.543 + *
   1.544 + * \param hAppearance Appearance object
   1.545 + * \param hMode PolygonMode object
   1.546 + */
   1.547 +M3G_API void m3gSetPolygonMode(M3GAppearance hAppearance,
   1.548 +                               M3GPolygonMode hMode)
   1.549 +{
   1.550 +    Appearance *appearance = (Appearance *) hAppearance;
   1.551 +    PolygonMode *mode = (PolygonMode *) hMode;
   1.552 +    M3G_VALIDATE_OBJECT(appearance);
   1.553 +
   1.554 +    M3G_ASSIGN_REF(appearance->polygonMode, mode);
   1.555 +
   1.556 +    m3gRegenerateSortKey(appearance);
   1.557 +}
   1.558 +
   1.559 +/*!
   1.560 + * \brief Set layer
   1.561 + *
   1.562 + * \param hAppearance Appearance object
   1.563 + * \param layer layer number
   1.564 + */
   1.565 +M3G_API void m3gSetLayer(M3GAppearance hAppearance, M3Gint layer)
   1.566 +{
   1.567 +    Appearance *appearance = (Appearance *) hAppearance;
   1.568 +    M3G_VALIDATE_OBJECT(appearance);
   1.569 +
   1.570 +    /* Check for errors */
   1.571 +    if (!m3gInRange(layer, M3G_APPEARANCE_MIN_LAYER, M3G_APPEARANCE_MAX_LAYER)) {
   1.572 +        m3gRaiseError(M3G_INTERFACE(appearance), M3G_INVALID_INDEX);
   1.573 +        return;
   1.574 +    }
   1.575 +
   1.576 +    appearance->layer = (M3Gshort) layer;
   1.577 +    
   1.578 +    m3gRegenerateSortKey(appearance);
   1.579 +}
   1.580 +
   1.581 +/*!
   1.582 + * \brief Set material
   1.583 + *
   1.584 + * \param hAppearance Appearance object
   1.585 + * \param hMaterial Material object
   1.586 + */
   1.587 +M3G_API void m3gSetMaterial(M3GAppearance hAppearance,
   1.588 +                            M3GMaterial hMaterial)
   1.589 +{
   1.590 +    Appearance *appearance = (Appearance *) hAppearance;
   1.591 +    Material *material = (Material *) hMaterial;
   1.592 +    M3G_VALIDATE_OBJECT(appearance);
   1.593 +
   1.594 +    M3G_ASSIGN_REF(appearance->material, material);
   1.595 +    
   1.596 +    if (material != NULL) {
   1.597 +        appearance->vertexMask |= (M3Gushort)M3G_NORMAL_BIT;
   1.598 +    }
   1.599 +    else {
   1.600 +        appearance->vertexMask &= ~(M3Gushort)M3G_NORMAL_BIT;
   1.601 +    }
   1.602 +
   1.603 +    m3gRegenerateSortKey(appearance);
   1.604 +}
   1.605 +
   1.606 +/*!
   1.607 + * \brief Set texture
   1.608 + *
   1.609 + * \param hAppearance Appearance object
   1.610 + * \param unit texturing unit
   1.611 + * \param hTexture Texture2D object
   1.612 + */
   1.613 +M3G_API void m3gSetTexture(M3GAppearance hAppearance,
   1.614 +                           M3Gint unit, M3GTexture hTexture)
   1.615 +{
   1.616 +    Appearance *appearance = (Appearance *) hAppearance;
   1.617 +    Texture *texture = (Texture *) hTexture;
   1.618 +    M3G_VALIDATE_OBJECT(appearance);
   1.619 +    
   1.620 +    if (!m3gInRange(unit, 0, M3G_NUM_TEXTURE_UNITS - 1)) {
   1.621 +        m3gRaiseError(M3G_INTERFACE(appearance), M3G_INVALID_INDEX);
   1.622 +        return;
   1.623 +    }
   1.624 +    
   1.625 +    M3G_ASSIGN_REF(appearance->texture[unit], texture);
   1.626 +    
   1.627 +    if (texture != NULL) {
   1.628 +        appearance->vertexMask |= (M3Gushort) (M3G_TEXCOORD0_BIT << unit);
   1.629 +    }
   1.630 +    else {
   1.631 +        appearance->vertexMask &= (M3Gushort) ~(M3G_TEXCOORD0_BIT << unit);
   1.632 +    }
   1.633 +
   1.634 +    m3gRegenerateSortKey(appearance);
   1.635 +}
   1.636 +
   1.637 +/*!
   1.638 + * \brief Set fog
   1.639 + *
   1.640 + * \param hAppearance Appearance object
   1.641 + * \param hFog Fog object
   1.642 + */
   1.643 +M3G_API void m3gSetFog(M3GAppearance hAppearance, M3GFog hFog)
   1.644 +{
   1.645 +    Appearance *appearance = (Appearance *) hAppearance;
   1.646 +    M3G_VALIDATE_OBJECT(appearance);
   1.647 +	
   1.648 +	M3G_ASSIGN_REF(appearance->fog, hFog);
   1.649 +
   1.650 +    m3gRegenerateSortKey(appearance);
   1.651 +}
   1.652 +