m3g/m3gcore11/src/m3g_polygonmode.c
author hgs
Fri, 24 Sep 2010 16:14:28 +0300
changeset 187 9f66f99ee56f
parent 0 5d03bc08d59c
permissions -rw-r--r--
201026

/*
* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: PolygonMode implementation
*
*/


/*!
 * \internal
 * \file
 * \brief PolygonMode implementation
 */

#ifndef M3G_CORE_INCLUDE
#   error included by m3g_core.c; do not compile separately.
#endif

/*
 * Uncomment this line to switch tracing on for this file's functions
 */
/* #define M3G_LOCAL_TRACEF_ON */

#include "m3g_polygonmode.h"

/*----------------------------------------------------------------------
 * Internal functions
 *--------------------------------------------------------------------*/

/*!
 * \internal
 * \brief Applies default polygon mode to OpenGL.
 */
static void m3gApplyDefaultPolygonMode()
{
    /* cull = BACK */
    glCullFace(GL_BACK);
    glEnable(GL_CULL_FACE);

    /* shading = M3G_SHADE_SMOOTH */
    glShadeModel(GL_SMOOTH);

    /*  winding = M3G_WINDING_CCW */
    glFrontFace(GL_CCW);

    /* perspective correction = false */
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

    /* lighting = ONE_SIDED */
    glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
}

/*!
 * \internal
 * \brief Applies polygon mode to OpenGL.
 *
 * \param polygonMode   PolygonMode object
 */
static void m3gApplyPolygonMode(PolygonMode *polygonMode)
{
    if (polygonMode != NULL) {
        if (polygonMode->cullingMode == M3G_CULL_NONE) {
            glDisable(GL_CULL_FACE);
        }
        else {
            if (polygonMode->cullingMode == M3G_CULL_BACK) {
                glCullFace(GL_BACK);
            }
            else {
                glCullFace(GL_FRONT);
            }
            glEnable(GL_CULL_FACE);
        }

        if (m3gGetTwoSidedLightingWorkaround(M3G_INTERFACE(polygonMode))) {
            glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
        }
        else {
            glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, polygonMode->enableTwoSidedLighting);
        }

        if (polygonMode->shadingMode == M3G_SHADE_FLAT) {
            glShadeModel(GL_FLAT);
        }
        else {
            glShadeModel(GL_SMOOTH);
        }

        if (polygonMode->windingMode == M3G_WINDING_CW) {
            glFrontFace(GL_CW);
        }
        else {
            glFrontFace(GL_CCW);
        }

        if (polygonMode->enablePerspectiveCorrection == GL_TRUE) {
            glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
        }
        else {
            glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
        }
    }
    else {
        m3gApplyDefaultPolygonMode();
    }
    M3G_ASSERT_GL;

}

/*!
 * \internal
 * \brief Overloaded Object3D method
 *
 * \param originalObj original PolygonMode object
 * \param cloneObj pointer to cloned PolygonMode object
 * \param pairs array for all object-duplicate pairs
 * \param numPairs number of pairs
 */
static M3Gbool m3gPolygonModeDuplicate(const Object *originalObj,
                                       Object **cloneObj,
                                       Object **pairs,
                                       M3Gint *numPairs)
{
    PolygonMode *original = (PolygonMode *)originalObj;
    PolygonMode *clone;
    M3G_ASSERT(*cloneObj == NULL); /* no derived classes */

    /* Create the clone object */
    
    clone = (PolygonMode *)m3gCreatePolygonMode(originalObj->interface);
    if (!clone) {
        return M3G_FALSE;
    }
    *cloneObj = (Object *)clone;

    /* Duplicate base class data */
    
    if (!m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
        return M3G_FALSE;
    }

    /* Duplicate our own data */
    
    clone->enableLocalCameraLighting = original->enableLocalCameraLighting;
    clone->enablePerspectiveCorrection = original->enablePerspectiveCorrection;
    clone->cullingMode = original->cullingMode;
    clone->windingMode = original->windingMode;
    clone->shadingMode = original->shadingMode;
    clone->enableTwoSidedLighting = original->enableTwoSidedLighting;

    return M3G_TRUE;
}

/*----------------------------------------------------------------------
 * Virtual function table
 *--------------------------------------------------------------------*/

static const ObjectVFTable m3gvf_PolygonMode = {
    m3gObjectApplyAnimation,
    m3gObjectIsCompatible,
    m3gObjectUpdateProperty,
    m3gObjectDoGetReferences,
    m3gObjectFindID,
    m3gPolygonModeDuplicate,
    m3gDestroyObject
};


/*----------------------------------------------------------------------
 * Public API functions
 *--------------------------------------------------------------------*/

/*!
 * \brief Creates a new PolygonMode object.
 *
 * \param interface     M3G interface object
 * \retval PolygonMode new PolygonMode object
 * \retval NULL PolygonMode creating failed
 */
M3G_API M3GPolygonMode m3gCreatePolygonMode(M3GInterface interface)
{
    Interface *m3g = (Interface *) interface;
    M3G_VALIDATE_INTERFACE(m3g);

    {
        PolygonMode *polygonMode = m3gAllocZ(m3g, sizeof(PolygonMode));

        if (polygonMode != NULL) {
            m3gInitObject(&polygonMode->object, m3g, M3G_CLASS_POLYGON_MODE);
            polygonMode->enableLocalCameraLighting = GL_FALSE;
            polygonMode->enablePerspectiveCorrection = GL_FALSE;
            polygonMode->cullingMode = M3G_CULL_BACK;
            polygonMode->windingMode = M3G_WINDING_CCW;
            polygonMode->shadingMode = M3G_SHADE_SMOOTH;
            polygonMode->enableTwoSidedLighting = GL_FALSE;
        }

        return (M3GPolygonMode)polygonMode;
    }
}

/*!
 * \brief Set local camera lightning.
 *
 * \param handle        PolygonMode object
 * \param enable        enable flag
 */
M3G_API void m3gSetLocalCameraLightingEnable(M3GPolygonMode handle,
                                             M3Gbool enable)
{
    PolygonMode *polygonMode = (PolygonMode*)handle;
    M3G_VALIDATE_OBJECT(polygonMode);
    polygonMode->enableLocalCameraLighting = (GLboolean) enable;
}

/*!
 * \brief Set perspective correction.
 *
 * \param handle        PolygonMode object
 * \param enable        enable flag
 */
void m3gSetPerspectiveCorrectionEnable(M3GPolygonMode handle, M3Gbool enable)
{
    PolygonMode *polygonMode = (PolygonMode*)handle;
    M3G_VALIDATE_OBJECT(polygonMode);
    polygonMode->enablePerspectiveCorrection = (GLboolean) enable;
}

/*!
 * \brief Set culling mode.
 *
 * \param handle        PolygonMode object
 * \param mode          culling mode
 */
void m3gSetCulling(M3GPolygonMode handle, M3Gint mode)
{
    PolygonMode *polygonMode = (PolygonMode*)handle;
    M3G_VALIDATE_OBJECT(polygonMode);

    switch (mode) {
    case M3G_CULL_BACK:
    case M3G_CULL_FRONT:
    case M3G_CULL_NONE:
        polygonMode->cullingMode = mode;
        break;
    default:
        m3gRaiseError(M3G_INTERFACE(polygonMode), M3G_INVALID_VALUE);
        break;
    }
}

/*!
 * \brief Get culling mode.
 *
 * \param handle        PolygonMode object
 * \return              culling mode
 */
M3G_API M3Gint m3gGetCulling(M3GPolygonMode handle)
{
    PolygonMode *polygonMode = (PolygonMode*)handle;
    M3G_VALIDATE_OBJECT(polygonMode);
    return polygonMode->cullingMode;
}

/*!
 * \brief Set winding mode.
 *
 * \param handle        PolygonMode object
 * \param mode          winding mode
 */
M3G_API void m3gSetWinding(M3GPolygonMode handle, M3Gint mode)
{
    PolygonMode *polygonMode = (PolygonMode*)handle;
    M3G_VALIDATE_OBJECT(polygonMode);

    if (mode != M3G_WINDING_CCW && mode != M3G_WINDING_CW) {
        m3gRaiseError(M3G_INTERFACE(polygonMode), M3G_INVALID_VALUE);
    }
    else {
        polygonMode->windingMode = mode;
    }
}

/*!
 * \brief Get winding mode.
 *
 * \param handle        PolygonMode object
 * \return              winding mode
 */
M3G_API M3Gint m3gGetWinding(M3GPolygonMode handle)
{
    PolygonMode *polygonMode = (PolygonMode*)handle;
    M3G_VALIDATE_OBJECT(polygonMode);
    return polygonMode->windingMode;
}

/*!
 * \brief Set shading mode.
 *
 * \param handle        PolygonMode object
 * \param mode          shading mode
 */
M3G_API void m3gSetShading(M3GPolygonMode handle, M3Gint mode)
{
    PolygonMode *polygonMode = (PolygonMode*)handle;
    M3G_VALIDATE_OBJECT(polygonMode);

    if (mode != M3G_SHADE_FLAT && mode != M3G_SHADE_SMOOTH) {
        m3gRaiseError(M3G_INTERFACE(polygonMode), M3G_INVALID_VALUE);
    }
    else {
        polygonMode->shadingMode = mode;
    }
}

/*!
 * \brief Get shading mode.
 *
 * \param handle        PolygonMode object
 * \return              shading mode
 */
M3G_API M3Gint m3gGetShading(M3GPolygonMode handle)
{
    PolygonMode *polygonMode = (PolygonMode*)handle;
    M3G_VALIDATE_OBJECT(polygonMode);
    return polygonMode->shadingMode;
}

/*!
 * \brief Set two sided lighting.
 *
 * \param handle        PolygonMode object
 * \param enable        enable flag
 */
M3G_API void m3gSetTwoSidedLightingEnable(M3GPolygonMode handle,
                                          M3Gbool enable)
{
    PolygonMode *polygonMode = (PolygonMode*)handle;
    M3G_VALIDATE_OBJECT(polygonMode);
    polygonMode->enableTwoSidedLighting = (GLboolean) enable;
}

/*!
 * \brief Get two sided lighting.
 *
 * \param handle        PolygonMode object
 * \retval M3G_TRUE     enabled
 * \retval M3G_FALSE    disabled
 */
M3G_API M3Gbool m3gIsTwoSidedLightingEnabled(M3GPolygonMode handle)
{
    PolygonMode *polygonMode = (PolygonMode*)handle;
    M3G_VALIDATE_OBJECT(polygonMode);
    return (M3Gbool) polygonMode->enableTwoSidedLighting;
}

/*!
 * \brief Get local camera lighting.
 *
 * \param handle        PolygonMode object
 * \retval M3G_TRUE     enabled
 * \retval M3G_FALSE    disabled
 */

M3G_API M3Gbool m3gIsLocalCameraLightingEnabled(M3GPolygonMode handle)
{
    PolygonMode *polygonMode = (PolygonMode*)handle;
    M3G_VALIDATE_OBJECT(polygonMode);
    return (M3Gbool) polygonMode->enableLocalCameraLighting;
}

/*!
 * \brief Get perspective correction.
 *
 * \param handle        PolygonMode object
 * \retval M3G_TRUE     enabled
 * \retval M3G_FALSE    disabled
 */
M3G_API M3Gbool m3gIsPerspectiveCorrectionEnabled(M3GPolygonMode handle)
{
    PolygonMode *polygonMode = (PolygonMode*)handle;
    M3G_VALIDATE_OBJECT(polygonMode);
    return (M3Gbool) polygonMode->enablePerspectiveCorrection;
}

/*
 * Uncomment these lines' opening pair at the begining of the file
 * if you want to switch tracing on for this file.
 */
#ifdef M3G_LOCAL_TRACEF_ON
#undef M3G_LOCAL_TRACEF_ON
#endif