ImmediateModeRenderer/ImmediateModeRenderer.cpp

//**************************************************************************/
// Copyright (c) 2008 Autodesk, Inc.
// All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk license
// agreement provided at the time of installation or download, or which
// otherwise accompanies this software in either electronic or hard copy form.
//
//**************************************************************************/
// DESCRIPTION:
// CREATED: April 2010
//**************************************************************************/
#include "ImmediateModeRenderer.h"
#include "math.h"

#if defined(WIN32) || defined(WIN64)
#include <omp.h>
#endif

#if defined(JAMBUILD)
#include <Mudbox/mudbox.h>
#include <Mudbox/MudBoxGL.h>
#else
#include "../../include/Mudbox/mudbox.h"
#include "../../include/Mudbox/MudBoxGL.h"
#endif

MB_PLUGIN( "ImmediateModeRenderer", "Immediate Mode Renderer", "Autodesk", "http://www.mudbox3d.com", 0 );

IMPLEMENT_CLASS( ImmediateModeRenderer, MeshRenderer, "Immediate Mode Renderer" );

ImmediateModeRenderer::ImmediateModeRenderer( void ) :
    m_pMesh(NULL),
    m_fPointSize(2.0f),
    m_fLineWidth(2.0f),
    m_ePolygonMode(GL_FILL),
    m_bTCMode(FALSE),
    m_iRedBits(0),
    m_iGreenBits(0),
    m_iBlueBits(0),
    m_bFacetedMode(false)
{
}

ImmediateModeRenderer::~ImmediateModeRenderer( void )
{
}

void ImmediateModeRenderer::Serialize( Stream &s )
{
    MeshRenderer::Serialize( s );
}

void ImmediateModeRenderer::SetTextureCoordinateMode( bool bMode ) 
{
    m_bTCMode = bMode;
}

void ImmediateModeRenderer::SetMesh( Mesh *pMesh )
{
    m_pMesh = pMesh;
    OnMeshChange();
}

void ImmediateModeRenderer::Render( const Selector *pSelector, bool bSkipMaterial, const Camera *pCamera, const AxisAlignedBoundingBox &bUV )
{
    if (!m_pMesh)
        return;

    if (!bSkipMaterial && m_pMesh->Geometry()->Material())
    {
        m_pMesh->Geometry()->Material()->Activate(m_pMesh, AxisAlignedBoundingBox(), Color::white );
    }

    glPolygonMode(GL_FRONT, m_ePolygonMode);
    glShadeModel( GL_SMOOTH );
    glEnable(GL_NORMALIZE);

    if (m_pMesh->Type() == Mesh::typeTriangular)
    {
        glBegin(GL_TRIANGLES);
        for (unsigned int ii=0; ii<m_pMesh->FaceCount(); ii++)
        {
            renderTriangle(ii);
        }
        glEnd();
    }
    else if (m_pMesh->Type() == Mesh::typeQuadric)
    {
        glBegin(GL_QUADS);
        for (unsigned int ii=0; ii<m_pMesh->FaceCount(); ii++)
        {
            renderQuad(ii);
        }
        glEnd();
    }

    if (!bSkipMaterial && m_pMesh->Geometry()->Material())
    {
        m_pMesh->Geometry()->Material()->Deactivate();
    }

    // Render auxilary data for debugging purposes
#ifdef AUX_DATA
    glColor3f(0,0,0);
    if (m_pMesh->Type() == Mesh::typeTriangular)
    {
        renderTriangleNormals();
    }
    else if (m_pMesh->Type() == Mesh::typeQuadric)
    {
        renderQuadNormals();
    }
#endif
}
unsigned int encode(unsigned int faceIndex, unsigned int vertexIndex)
{
    unsigned int value = faceIndex;
    value = value << 2;
    value = value | vertexIndex;

    return value;
}

void decode(unsigned int value, unsigned int &faceIndex, unsigned int &vertexIndex)
{
    vertexIndex = 3 & value;

    faceIndex = 0xfffffffc & value;
    faceIndex = faceIndex >> 2;
}

void ImmediateModeRenderer::DecodeData( unsigned int iData, unsigned int &iFaceIndex, unsigned int &iVertexIndex )
{
    unsigned int iFaceVertex = 0;
    decode(iData, iFaceIndex, iFaceVertex);

    if (m_pMesh->Type() == Mesh::typeTriangular)
    {
        iVertexIndex = m_pMesh->TriangleIndex(iFaceIndex, iFaceVertex);
    }
    else if (m_pMesh->Type() == Mesh::typeQuadric)
    {
        iVertexIndex = m_pMesh->QuadIndex(iFaceIndex, iFaceVertex);
    }
}

unsigned int ImmediateModeRenderer::RenderData(const Selector *pSelector, unsigned int iStart, const Camera *pCamera)
{
    glDisable(GL_BLEND);
    glDisable(GL_DITHER);
    glDisable(GL_FOG);
    glDisable(GL_LIGHTING);
    glDisable(GL_TEXTURE_1D);
    glDisable (GL_TEXTURE_2D); 
    glShadeModel( GL_FLAT );

    glEnable(GL_COLOR_MATERIAL);
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

    if( !m_pMesh->Visible() || (m_pMesh->Geometry() && m_pMesh->Geometry()->ActiveLevel()->ID() != m_pMesh->ID()) )
        return iStart;

    unsigned int iColorCount = 0;
    if (m_pMesh->Type() == Mesh::typeTriangular)
    {
        glBegin(GL_TRIANGLES);
        for (unsigned long ii=0; ii<m_pMesh->FaceCount(); ii++)
        {
            iColorCount = encode(ii, 0);
            glColor4ubv( (unsigned char*) &iColorCount );
            glVertex3fv(m_pMesh->TriangleVertexPosition(ii, 0));

            iColorCount = encode(ii, 1);
            glColor4ubv( (unsigned char*) &iColorCount );
            glVertex3fv(m_pMesh->TriangleVertexPosition(ii, 1));

            iColorCount = encode(ii, 2);
            glColor4ubv( (unsigned char*) &iColorCount );
            glVertex3fv(m_pMesh->TriangleVertexPosition(ii, 2));
        }
        glEnd();
    }
    else if (m_pMesh->Type() == Mesh::typeQuadric)
    {
        glBegin(GL_QUADS);
        for (unsigned long ii=0; ii<m_pMesh->FaceCount(); ii++)
        {
            iColorCount = encode(ii, 0);
            glColor4ubv( (unsigned char*) &iColorCount );
            glVertex3fv(m_pMesh->QuadVertexPosition(ii, 0));

            iColorCount = encode(ii, 1);
            glColor4ubv( (unsigned char*) &iColorCount );
            glVertex3fv(m_pMesh->QuadVertexPosition(ii, 1));

            iColorCount = encode(ii, 2);
            glColor4ubv( (unsigned char*) &iColorCount );
            glVertex3fv(m_pMesh->QuadVertexPosition(ii, 2));

            iColorCount = encode(ii, 3);
            glColor4ubv( (unsigned char*) &iColorCount );
            glVertex3fv(m_pMesh->QuadVertexPosition(ii, 3));
        }
        glEnd();
    }

    glShadeModel( GL_SMOOTH );

    return iColorCount;
}

void ImmediateModeRenderer::renderTriangle(unsigned int index)
{
    if( m_bFacetedMode )
        glNormal3fv( m_pMesh->FaceNormal(index) );

    if( !m_bFacetedMode )
        glNormal3fv(m_pMesh->TriangleVertexNormal(index,0));
    if (m_bTCMode)
        glTexCoord2f(m_pMesh->TriangleVertexTC(index,0).u, m_pMesh->TriangleVertexTC(index,0).v);
    glVertex3fv(m_pMesh->TriangleVertexPosition(index, 0));

    if( !m_bFacetedMode )
        glNormal3fv(m_pMesh->TriangleVertexNormal(index,1));
    if (m_bTCMode)
        glTexCoord2f(m_pMesh->TriangleVertexTC(index,1).u, m_pMesh->TriangleVertexTC(index,1).v);
    glVertex3fv(m_pMesh->TriangleVertexPosition(index, 1));
    
    if( !m_bFacetedMode )
        glNormal3fv(m_pMesh->TriangleVertexNormal(index,2));
    if (m_bTCMode)
        glTexCoord2f(m_pMesh->TriangleVertexTC(index,2).u, m_pMesh->TriangleVertexTC(index,2).v);
    glVertex3fv(m_pMesh->TriangleVertexPosition(index, 2));
}

void ImmediateModeRenderer::renderTriangleNormals()
{
    Vector point, normal;

    glLineWidth(2.0f);

    glBegin(GL_LINES);

    float s = 2.0f;

    for (unsigned int ii=0; ii<m_pMesh->FaceCount(); ii++)
    {
        point = m_pMesh->TriangleVertexPosition(ii, 0);
        normal = m_pMesh->TriangleVertexNormal(ii,0)*s;

        glVertex3fv(point);
        glVertex3fv((point + normal));

        point = m_pMesh->TriangleVertexPosition(ii, 1);
        normal = m_pMesh->TriangleVertexNormal(ii, 1)*s;

        glVertex3fv(point);
        glVertex3fv((point + normal));
        
        point = m_pMesh->TriangleVertexPosition(ii, 2);
        normal = m_pMesh->TriangleVertexNormal(ii, 2)*s;

        glVertex3fv(point);
        glVertex3fv((point + normal));
    }
    glEnd();
}

void ImmediateModeRenderer::renderQuad(unsigned int index)
{
    if( m_bFacetedMode )
        glNormal3fv( m_pMesh->FaceNormal(index) );

    if( !m_bFacetedMode )
        glNormal3fv(m_pMesh->QuadVertexNormal(index, 0));
    if (m_bTCMode)
        glTexCoord2f(m_pMesh->QuadVertexTC(index,0).u, m_pMesh->QuadVertexTC(index,0).v);
    glVertex3fv(m_pMesh->QuadVertexPosition(index, 0));

    if( !m_bFacetedMode )
        glNormal3fv(m_pMesh->QuadVertexNormal(index, 1));
    if (m_bTCMode)
        glTexCoord2f(m_pMesh->QuadVertexTC(index,1).u, m_pMesh->QuadVertexTC(index,1).v);
    glVertex3fv(m_pMesh->QuadVertexPosition(index, 1));


    if( !m_bFacetedMode )
        glNormal3fv(m_pMesh->QuadVertexNormal(index, 2));
    if (m_bTCMode)
        glTexCoord2f(m_pMesh->QuadVertexTC(index,2).u, m_pMesh->QuadVertexTC(index,2).v);
    glVertex3fv(m_pMesh->QuadVertexPosition(index, 2));

    if( !m_bFacetedMode )
        glNormal3fv(m_pMesh->QuadVertexNormal(index, 3));
    if (m_bTCMode)
        glTexCoord2f(m_pMesh->QuadVertexTC(index,3).u, m_pMesh->QuadVertexTC(index,3).v);
    glVertex3fv(m_pMesh->QuadVertexPosition(index, 3));
}

void ImmediateModeRenderer::renderQuadNormals()
{
    Vector point, normal;

    glLineWidth(2.0f);

    glBegin(GL_LINES);

    float s = 2.0f;

    for (unsigned int ii=0; ii<m_pMesh->FaceCount(); ii++)
    {
        point = m_pMesh->QuadVertexPosition(ii, 0);
        normal = m_pMesh->QuadVertexNormal(ii,0)*s;

        glVertex3fv(point);
        glVertex3fv((point + normal));

        point = m_pMesh->QuadVertexPosition(ii, 1);
        normal = m_pMesh->QuadVertexNormal(ii, 1)*s;

        glVertex3fv(point);
        glVertex3fv((point + normal));

        point = m_pMesh->QuadVertexPosition(ii, 2);
        normal = m_pMesh->QuadVertexNormal(ii, 2)*s;

        glVertex3fv(point);
        glVertex3fv((point + normal));

        point = m_pMesh->QuadVertexPosition(ii, 3);
        normal = m_pMesh->QuadVertexNormal(ii, 3)*s;

        glVertex3fv(point);
        glVertex3fv((point + normal));
    }
    glEnd();
}

void ImmediateModeRenderer::OnVertexPositionChange( unsigned int iVertexIndex, unsigned int iFaceIndex )
{
}

void ImmediateModeRenderer::OnVertexStateChange( unsigned int iVertexIndex, unsigned int iFaceIndex )
{
}

void ImmediateModeRenderer::OnMeshChange( void )
{
}

void ImmediateModeRenderer::SetLODLevel(float fLevel)
{
}

float ImmediateModeRenderer::LODLevel() const
{
    return 0;
}

const AxisAlignedBoundingBox &ImmediateModeRenderer::ActiveUVArea() const
{
    return m_ActiveUVArea;
}

void ImmediateModeRenderer::SetWireFrameMode(bool bMode)
{
}

bool ImmediateModeRenderer::WireFrameMode() const
{
    return false;
}

void ImmediateModeRenderer::SetColorMode(bool bMode)
{
}

bool ImmediateModeRenderer::ColorMode() const
{
    return false;
}

void ImmediateModeRenderer::SetWireLevel(unsigned int)
{
}

unsigned int ImmediateModeRenderer::WireLevel() const
{
    return 0;
}

bool ImmediateModeRenderer::TextureCoordinateMode() const
{
    return false;
}

void ImmediateModeRenderer::SetTangentMode(bool bMode)
{
}

bool ImmediateModeRenderer::TangentMode() const
{
    return false;
}

void ImmediateModeRenderer::SetFacetedMode( bool bMode )
{
    m_bFacetedMode = bMode;
}

bool ImmediateModeRenderer::FacetedMode() const
{
    return m_bFacetedMode;
}

void ImmediateModeRenderer::OnNodeEvent(const Attribute &, NodeEventType)
{
}

void ImmediateModeRenderer::Initialize()
{
}