#ifdef WIN32
#pragma warning( disable : 4786 )       // Disable STL warnings.
#endif
#include <maya/MIOStream.h>
#include <math.h>
#include <cstdlib>
#include <maya/MGlobal.h>
#include <maya/MString.h>
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnCompoundAttribute.h>
#include <maya/MFloatVector.h>
#include <maya/MFnPlugin.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MSceneMessage.h>
#include <maya/MUserData.h>
#include <maya/MUintArray.h>
#include <maya/MHWShaderSwatchGenerator.h>
#include <maya/MRenderUtilities.h>
#include <maya/MHardwareRenderer.h>
#include <maya/MGeometryData.h>
#include <maya/MImage.h>
#include <maya/MMatrix.h>
#include <maya/MDrawRegistry.h>
#include <maya/MPxShaderOverride.h>
#include <maya/MDrawContext.h>
#include <maya/MStateManager.h>
#include <maya/MViewport2Renderer.h>
#include <maya/MTextureManager.h>
#include <maya/MShaderManager.h>
#include <maya/MGLdefinitions.h>
#include <maya/MGLFunctionTable.h>
#undef ENABLE_TRACE_API_CALLS
#ifdef ENABLE_TRACE_API_CALLS
#define TRACE_API_CALLS(x) cerr << "hwPhongShader: "<<(x)<<"\n"
#else
#define TRACE_API_CALLS(x)
#endif
#ifndef GL_EXT_texture_cube_map
# define GL_NORMAL_MAP_EXT                   0x8511
# define GL_REFLECTION_MAP_EXT               0x8512
# define GL_TEXTURE_CUBE_MAP_EXT             0x8513
# define GL_TEXTURE_BINDING_CUBE_MAP_EXT     0x8514
# define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT  0x8515
# define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT  0x8516
# define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT  0x8517
# define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT  0x8518
# define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT  0x8519
# define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT  0x851A
# define GL_PROXY_TEXTURE_CUBE_MAP_EXT       0x851B
# define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT    0x851C
#endif
#include "hwPhongShader.h"
#include "hwPhongShaderBehavior.h"
static const bool sTestVertexIdAndFaceId = (getenv("MAYA_HWPHONG_TEST_VERTEXID_AND_FACEID") != NULL);
static const bool sDebugConsolidation = (getenv("MAYA_HWPHONG_TEST_DEBUG_CONSOLIDATION") != NULL);
static const bool sTestLocalUVCoord = (getenv("MAYA_HWPHONG_TEST_LOCALUVCOORD") != NULL);
static const bool sTestIndexing = (getenv("MAYA_HWPHONG_TEST_INDEXING") != NULL);
MTypeId hwPhongShader::id( 0x00105449 );
 
MObject  hwPhongShader::aTransparency;
 
MObject  hwPhongShader::aDiffuseColor;
 
MObject  hwPhongShader::aSpecularColor;
 
MObject  hwPhongShader::aShininessX;
 
MObject  hwPhongShader::aShininessY;
 
MObject  hwPhongShader::aShininessZ;
 
MObject  hwPhongShader::aGeometryShape;
 
void hwPhongShader::postConstructor( )
{
    TRACE_API_CALLS("postConstructor");
    setMPSafe(false);
}
void hwPhongShader::printGlError( const char *call )
{
    GLenum error;
    while( (error = glGetError()) != GL_NO_ERROR ) {
        cerr << call << ":" << error << " is " << (const char *)gluErrorString( error ) << "\n";
    }
}
{
    if ( cos_a < 0.0 ) cos_a = 0.0;
    p[0] = (float)(mSpecularColor[0]*pow(cos_a,double(mShininess[0])) +
                   mDiffuseColor[0]*cos_a + mAmbientColor[0]);
    p[1] = (float)(mSpecularColor[1]*pow(cos_a,double(mShininess[1])) +
                   mDiffuseColor[1]*cos_a + mAmbientColor[1]);
    p[2] = (float)(mSpecularColor[2]*pow(cos_a,double(mShininess[2])) +
                   mDiffuseColor[2]*cos_a + mAmbientColor[2]);
    if ( p[0] > 1.0f ) p[0] = 1.0f;
    if ( p[1] > 1.0f ) p[1] = 1.0f;
    if ( p[2] > 1.0f ) p[2] = 1.0f;
    return p;
}
#define PHONG_TEXTURE_RES 256
static const GLenum faceTarget[6] =
{
    GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT,
    GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT,
    GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT,
    GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT,
    GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT,
    GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT
};
class CubeMapTextureDrawUtility
{
public:
    static void bind( unsigned int phong_map_id )
    {
        
        {
            glPushAttrib ( GL_ENABLE_BIT | GL_LIGHTING_BIT | GL_TEXTURE_BIT | GL_TRANSFORM_BIT );
            glDisable ( GL_LIGHTING );
            glDisable ( GL_TEXTURE_1D );
            glDisable ( GL_TEXTURE_2D );
            
            glEnable ( GL_TEXTURE_CUBE_MAP_EXT );
            glBindTexture ( GL_TEXTURE_CUBE_MAP_EXT, phong_map_id );
            glEnable ( GL_TEXTURE_GEN_S );
            glEnable ( GL_TEXTURE_GEN_T );
            glEnable ( GL_TEXTURE_GEN_R );
            glTexGeni ( GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_EXT );
            glTexGeni ( GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_EXT );
            glTexGeni ( GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_EXT );
            glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP);
            glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP);
            glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
            
            glMatrixMode ( GL_TEXTURE );
            glPushMatrix ();
            glLoadIdentity ();
            glMatrixMode ( GL_MODELVIEW );
        }
    }
    static void unbind()
    {
        
        glMatrixMode ( GL_TEXTURE );
        glPopMatrix ();
        glMatrixMode ( GL_MODELVIEW );
        
        glBindTexture( GL_TEXTURE_CUBE_MAP_EXT, 0 );
        glDisable ( GL_TEXTURE_CUBE_MAP_EXT );
        glPopAttrib();
    }
};
static void cubeToDir ( int face, double s, double t,
                      double &x, double &y, double &z )
{
    switch ( face )
    {
        case 0:
            x = 1;
            y = -t;
            z = -s;
            break;
        case 1:
            x = -1;
            y = -t;
            z = s;
            break;
        case 2:
            x = s;
            y = 1;
            z = t;
            break;
        case 3:
            x = s;
            y = -1;
            z = -t;
            break;
        case 4:
            x = s;
            y = -t;
            z = 1;
            break;
        case 5:
            x = -s;
            y = -t;
            z = -1;
            break;
    }
    double invLen = 1.0 / sqrt ( x*x + y*y + z*z );
    x *= invLen;
    y *= invLen;
    z *= invLen;
}
void hwPhongShader::init_Phong_texture ( void )
{
    
    if ( !mAttributesChanged && (phong_map_id != 0))
    {
        return;
    }
    GLubyte * texture_data;
    
    
    if (phong_map_id != 0)
        glDeleteTextures( 1, &phong_map_id );
    glGenTextures ( 1, &phong_map_id );
    glEnable ( GL_TEXTURE_CUBE_MAP_EXT );
    glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
    glPixelStorei ( GL_UNPACK_ROW_LENGTH, 0 );
    glBindTexture ( GL_TEXTURE_CUBE_MAP_EXT, phong_map_id );
    texture_data = new GLubyte[3*PHONG_TEXTURE_RES*PHONG_TEXTURE_RES];
    for ( int face=0 ; face<6 ; face++ )
    {
        int index = 0;
        for ( int j=0 ; j<PHONG_TEXTURE_RES ; j++ )
        {
            double t = 2*double(j)/(PHONG_TEXTURE_RES - 1) - 1; 
            for ( int i=0 ; i<PHONG_TEXTURE_RES ; i++ )
            {
                double s = 2*double(i)/(PHONG_TEXTURE_RES - 1) - 1; 
                double x = 0.0, y = 0.0, z = 0.0;
                cubeToDir ( face, s, t, x, y, z );
                texture_data[index++] = (GLubyte)(255*intensity[0]);
                texture_data[index++] = (GLubyte)(255*intensity[1]);
                texture_data[index++] = (GLubyte)(255*intensity[2]);
            }
        }
        glTexImage2D ( faceTarget[face], 0, GL_RGB, PHONG_TEXTURE_RES, PHONG_TEXTURE_RES,
            0, GL_RGB, GL_UNSIGNED_BYTE, texture_data );
    }
    glDisable ( GL_TEXTURE_CUBE_MAP_EXT );
    delete [] texture_data;
    
    mAttributesChanged = false;
}
void hwPhongShader::setTransparency(const float fTransparency)
{
    mTransparency = fTransparency; 
    mAttributesChanged = true;
    mAttributesChangedVP2 = true;
}
void hwPhongShader::setAmbient(const float3 &fambient) 
{ 
    mAmbientColor[0] = fambient[0];
    mAmbientColor[1] = fambient[1];
    mAmbientColor[2] = fambient[2];
    mAttributesChanged = true;
    mAttributesChangedVP2 = true;
}
void hwPhongShader::setDiffuse(const float3 &fDiffuse)
{
    mDiffuseColor[0] = fDiffuse[0];
    mDiffuseColor[1] = fDiffuse[1];
    mDiffuseColor[2] = fDiffuse[2];
    mAttributesChanged = true;
    mAttributesChangedVP2 = true;
}
void hwPhongShader::setSpecular(const float3 &fSpecular)
{
    mSpecularColor[0] = fSpecular[0];
    mSpecularColor[1] = fSpecular[1];
    mSpecularColor[2] = fSpecular[2];
    mAttributesChanged = true;
    mAttributesChangedVP2 = true;
}
void hwPhongShader::setShininess(const float3 &fShininess)
{
    mShininess[0] = fShininess[0];
    mShininess[1] = fShininess[1];
    mShininess[2] = fShininess[2];
    mAttributesChanged = true;
    mAttributesChangedVP2 = true;
}
hwPhongShader::hwPhongShader()
{
    TRACE_API_CALLS("hwPhongShader");
    attachSceneCallbacks();
    mAmbientColor[0] = mAmbientColor[1] = mAmbientColor[2] = 0.1f;
    mDiffuseColor[0] = mDiffuseColor[1] = mDiffuseColor[2] = 0.5f;
    mSpecularColor[0] = mSpecularColor[1] = mSpecularColor[2] = 0.5f;
    mShininess[0] = mShininess[1] = mShininess[2] = 100.0f;
    mAttributesChanged = false;
    markAttributesChangedVP2();
    phong_map_id = 0;
    mGeometryShape = 0;
    mTransparency = 0.0f;
}
hwPhongShader::~hwPhongShader()
{
    TRACE_API_CALLS("~hwPhongShader");
    detachSceneCallbacks();
}
void hwPhongShader::releaseEverything()
{
    if (phong_map_id != 0) {
        
        
        
        
            glDeleteTextures( 1, &phong_map_id );
            phong_map_id = 0;
        }
    }
}
void hwPhongShader::attachSceneCallbacks()
{
                                                          releaseCallback, this);
}
void hwPhongShader::releaseCallback(void* clientData)
{
    hwPhongShader *pThis = (hwPhongShader*) clientData;
    pThis->releaseEverything();
}
void hwPhongShader::detachSceneCallbacks()
{
    if (fBeforeNewCB)
    if (fBeforeOpenCB)
    if (fBeforeRemoveReferenceCB)
    if (fMayaExitingCB)
    fBeforeNewCB = 0;
    fBeforeOpenCB = 0;
    fBeforeRemoveReferenceCB = 0;
    fMayaExitingCB = 0;
}
static const MString sHWPhongShaderRegistrantId(
"HWPhongShaderRegistrantId");
 
{
public:
    virtual ~hwPhongShaderData() {}
};
{
public:
    {
        return new hwPhongShaderOverride(obj);
    }
    virtual ~hwPhongShaderOverride()
    {
        delete[] fTextureData;
        fTextureData = NULL;
        
        
        
        
        if (fShaderNode) fShaderNode->markAttributesChangedVP2();
        fShaderNode = NULL;
        if (theRenderer)
        {
            if (theTextureManager)
            {
                if (fTexture)
                {
                }
            }
            if (shaderMgr)
            {
                if (fColorShaderInstance)
                {
                }
                if (fShadowShaderInstance)
                {
                }
                if (fNTColorShaderInstance)
                {
                }
            }
        }
        fTexture = NULL;
        fColorShaderInstance = NULL;
        fShadowShaderInstance = NULL;
        fNTColorShaderInstance = NULL;
    }
    
    
    {
        
        return fHandlesConsolidateGeometry;
    }
    
    
    {
        return sTestVertexIdAndFaceId || sTestLocalUVCoord || sTestIndexing;
    }
    
        const MInitContext& initContext,
        MInitFeedback& initFeedback)
    {
        TRACE_API_CALLS("hwPhongShaderOverride::initialize");
        bool setRequirementsFromShader = false;
        if (fColorShaderInstance)
        {
            
            
            
            
            
            
            
            if (setRequirementsFromShader)
            
            
            
            
            
            
            
        }
        if (!setRequirementsFromShader)
        {
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            static bool useCustomPrimitiveGenerator = (getenv("MAYA_USE_CUSTOMPRIMITIVEGENERATOR") != NULL);
            if(useCustomPrimitiveGenerator)
            {
                MString customPrimitiveName(
"customPrimitiveTest");
 
                    MHWRender::MIndexBufferDescriptor::kCustom,
                    customPrimitiveName,
                    empty,
                    3);
                positionDesc.setSemanticName("customPositionStream");
                    empty,
                    3);
                normalDesc.setSemanticName("customNormalStream");
            }
            else
            {
                    empty,
                    3);
                
                
                
                positionDesc.setSemanticName("swizzlePosition");
                    empty,
                    3);
                if (sTestVertexIdAndFaceId || sTestIndexing)
                {
                        empty,
                        1);
                    vertexIdDesc.setSemanticName("vertexid");
                        empty,
                        1);
                    faceIdDesc.setSemanticName("faceid");
                }
                if (sTestLocalUVCoord || sTestIndexing)
                {
                        empty,
                        2);
                    localUVCoordDesc.setSemanticName("localuvcoord");
                }
            }
        }
        
        
        
        
        
        
        
        
        {
            hwPhongShaderData* data = new hwPhongShaderData();
            data->fPath = initContext.dagPath.fullPathName();
            initFeedback.customData = data;
        }
        else
        {
            initFeedback.customData = NULL;
        }
        return MString(
"Autodesk Maya hwPhongShaderOverride");
 
    }
    
    {
        TRACE_API_CALLS("hwPhongShaderOverride::updateDG");
        {
            
            
            if (fShaderNode)
            {
                if (status)
                {
                    node.findPlug("transparency").getValue(fTransparency);
                    fShaderNode->setTransparency(fTransparency);
                    node.findPlug("colorR").getValue(fAmbient[0]);
                    node.findPlug("colorG").getValue(fAmbient[1]);
                    node.findPlug("colorB").getValue(fAmbient[2]);
                    fShaderNode->setAmbient(fAmbient);
                    node.findPlug("diffuseColorR").getValue(fDiffuse[0]);
                    node.findPlug("diffuseColorG").getValue(fDiffuse[1]);
                    node.findPlug("diffuseColorB").getValue(fDiffuse[2]);
                    float3 fDiffuse_RGB = {fDiffuse[0], fDiffuse[1], fDiffuse[2]};
                    fShaderNode->setDiffuse(fDiffuse_RGB);
                    fDiffuse[3] = 1.0f - fTransparency;
                    
                    node.findPlug("specularColorR").getValue(fSpecular[0]);
                    node.findPlug("specularColorG").getValue(fSpecular[1]);
                    node.findPlug("specularColorB").getValue(fSpecular[2]);
                    fShaderNode->setSpecular(fSpecular);
                    node.findPlug("shininessX").getValue(fShininess[0]);
                    node.findPlug("shininessY").getValue(fShininess[1]);
                    node.findPlug("shininessZ").getValue(fShininess[2]);
                    fShaderNode->setShininess(fShininess);
                }
            }
            else
            {
                fTransparency = 0.0f;
            }   
        }
    }
    {
        TRACE_API_CALLS("hwPhongShaderOverride::updateDevice");
        if (fDrawUsingShader)
            updateShaderInstance();
        if (!fColorShaderInstance)
            rebuildTexture();
    }
    {
        TRACE_API_CALLS("hwPhongShaderOverride::endUpdate");
    }
    
    {
        fInShadowPass = false;
        fInColorPass = false;
        
        
        bool debugHandlesDraw = false;
        if (debugHandlesDraw)
            printf(
"In hwPhong shader handlesDraw(). Pass Identifier = %s\n", passId.
asChar());
        bool handlePass = false;
        for (
unsigned int i=0; i<passSem.
length(); i++)
 
        {
            {
                if (!hasOverrideShader)
                {
                    if (debugHandlesDraw)
                        printf("-> handle semantic[%d][%s]\n", i, passSem[i].asChar());
                    handlePass = true;
                    fInColorPass = true;
                }
            }
            {
                
                
                
                if (fShadowShaderInstance)
                    handlePass = true;
                if (debugHandlesDraw)
                    printf("-> handle semantic[%d][%s] = %d\n", i, passSem[i].asChar(), handlePass);
                
                fInShadowPass = true;
            }
            {
                if (debugHandlesDraw)
                    printf("-> don't handle semantic[%d][%s]\n", i, passSem[i].asChar());
                handlePass = false;
            }
            {
                if (debugHandlesDraw)
                    printf("-> don't handle semantic[%d][%s]\n", i, passSem[i].asChar());
                handlePass = false;
            }
            else
            {
                if (debugHandlesDraw)
                    printf("-> additional semantic[%d][%s]\n", i, passSem[i].asChar());
            }
        }
        
        
        return handlePass;
    }
    {
        if (fDrawUsingShader)
        {
            if (fInColorPass)
            {
                
                if (fColorShaderInstance)
                    return fColorShaderInstance;
            }
            else if (fInShadowPass)
            {
                
                if (fShadowShaderInstance)
                    return fShadowShaderInstance;
            }
        }
        return NULL;
    }
    
    
    
    {
        TRACE_API_CALLS("hwPhongShaderOverride::activateKey");
        fShaderBound = false;
        if (fDrawUsingShader)
        {
            if (fInColorPass && fColorShaderInstance)
            {
                fColorShaderInstance->bind( context );
                fShaderBound = true;
            }
            else if (fInShadowPass && fShadowShaderInstance)
            {
                
                fShadowShaderInstance->setParameter("shadowViewProj", viewProj );
                fShadowShaderInstance->bind( context );
                fShaderBound = true;
            }
        }
    }
    
    
    {
        TRACE_API_CALLS("hwPhongShaderOverride::terminateKey");
        if (fShaderBound)
        {
            if (fInColorPass && fColorShaderInstance)
            {
                fColorShaderInstance->unbind( context );
            }
            else if (fInShadowPass && fShadowShaderInstance)
            {
                fShadowShaderInstance->unbind( context );
            }
        }
        fShaderBound = false;
    }
    
    
    {
        if (!renderItem)
            return;
        {
            
            {
                int indexStart = geometryIndexMapping.
indexStart(i);
 
                
                    indexRange.
append(indexStart);
                indexRange.
append(indexStart+indexLength);
                fprintf(stderr, "Have consolidated geometry[%d]. Path=%s, index start=%d, index length=%d\n",
            }
        }
        else
        {
            unsigned int indexCount = buffer ? buffer->
size() : 0;
 
            indexRange.
append(indexCount);
            fprintf(stderr, "Have unconsolidated geometry. Path=%s. index size=%d\n",
        }
        
        
        
        
        
        
        if (!geometry) 
            return;
        if (sTestIndexing)
        {
            unsigned int indexBufferCount = 0;
            GLuint *indexBufferId = NULL;
            if (indexHandle)
            {
                indexBufferId = (GLuint *)(indexHandle);
                indexBufferCount = buffer->
size();
                {
                    fprintf(stderr, "IndexingPrimType(%s), IndexType(%s), IndexCount(%d), Handle(%d)\n",
                        indexBufferCount,
                        *indexBufferId);
                }
            }
            {
                const unsigned int *ptr = (
const unsigned int*)nonConstIB->
map();
 
                for (
unsigned int r=0; r<indexRange.
length()-1; r++)
 
                {
                    unsigned start = indexRange[r];
                    unsigned end = indexRange[r+1];
                    for (unsigned int i=start; i<end; i++)
                    {
                        const unsigned int index = ptr[i];
                        fprintf(stderr, "object[%d], triangle[%d], index[%d] = %d\n", r, (i-start)/3, i, index);
                    }
                }
            }
            else
            {
                const unsigned short *ptr = (
const unsigned short*)nonConstIB->
map();
 
                for (
unsigned int r=0; r<indexRange.
length()-1; r++)
 
                {
                    unsigned start = indexRange[r];
                    unsigned end = indexRange[r+1];
                    for (unsigned int i=start; i<end; i++)
                    {
                        const unsigned short index = ptr[i];
                        fprintf(stderr, "object[%d], triangle[%d], index[%d] = %d\n", r, (i-start)/3, i, index);
                    }
                }
            }
        }
    }
    
    
    {
        if (!geometry) 
            return;
        
        if (sTestVertexIdAndFaceId)
        {
            {
                if (!vb) continue;
                if (semanticName != "vertexid" && semanticName != "faceid") continue;
                
                const float *ptr = (
const float*)nonConstVB->
map();
 
                {
                    fprintf(stderr, 
"%s[%d] = %f\n", semanticName.
asChar(), k, ptr[k] );
                }
            }
        }
        
        if (sTestLocalUVCoord)
        {
            {
                if (!vb) continue;
                if (semanticName != "localuvcoord") continue;
                
                const float *ptr = (
const float*)nonConstVB->
map();
 
                {
                    fprintf(stderr, 
"%s[%d] = (%g, %g)\n", semanticName.
asChar(), k, ptr[2*k], ptr[2*k + 1]);
                }
            }
        }
    }
    {
        TRACE_API_CALLS("hwPhongShaderOverride::draw");
        
        
        if ((fDebugConsolidation && !fUseCustomDraw) || sTestVertexIdAndFaceId || sTestLocalUVCoord || sTestIndexing)
        {
            int numRenderItems = renderItemList.
length();
 
            for (int renderItemIdx=0; renderItemIdx<numRenderItems; renderItemIdx++)
            {
                if (!renderItem) continue;
                if ((fDebugConsolidation || sTestIndexing) && !fUseCustomDraw)
                {
                    hwPhongShaderOverride::dumpIndexing(renderItem);
                }
                if (sTestVertexIdAndFaceId || sTestLocalUVCoord || sTestIndexing)
                {
                    hwPhongShaderOverride::dumpAttributeInformation(renderItem);
                }
            }
        }
        
        if(sBlendState == NULL)
        {
            
            {
            }
        }
        int val = 0;
        bool debugDrawContext = false;
        {
            debugDrawContext = (val > 0);
        }
        if (debugDrawContext)
            printContextInformation(context);
        bool debugPassInformation = false;
        if (debugPassInformation)
        {
            printf(
"hwPhong node drawing in pass[%s], semantic[", passId.
asChar());
            for (
unsigned int i=0; i<passSem.
length(); i++)
 
                printf(" %s", passSem[i].asChar());
            printf(" ]\n");
        }
        
        
        
        if (fShaderBound)
        {
            
            if (fInColorPass)
            {
                bool needBlending = false;
                if (fTransparency > 0.0f)
                {
                    needBlending = true;
                }
                unsigned int passCount = fColorShaderInstance->getPassCount( context );
                if (passCount)
                {
                    for (unsigned int i=0; i<passCount; i++)
                    {
                        fColorShaderInstance->activatePass( context, i );
                        
                        if (fUseCustomDraw)
                        {
                            
                            
                            
                            
                            
                            customDraw(context, renderItemList);
                        }
                        else
                        {
                            
                            
                        }
                    }
                }
                if (needBlending)
                {
                }
            }
            
            else if (fInShadowPass)
            {
                unsigned int passCount = fShadowShaderInstance->getPassCount( context );
                if (passCount)
                {
                    for (unsigned int i=0; i<passCount; i++)
                    {
                        fShadowShaderInstance->activatePass( context, i );
                        if (fUseCustomDraw)
                        {
                            customDraw(context, renderItemList);
                        }
                        else
                        {
                        }
                    }
                }
            }
        }
        
        
        else
        {
            int phongTextureId = 0;
            if (theRenderer)
            {
                if(theTextureManager)
                {
                    if(fTexture)
                    {
                        void *idPtr = fTexture->resourceHandle();
                        if (idPtr)
                        {
                            phongTextureId = *((int *)idPtr);
                        }
                    }
                }
            }
            if (phongTextureId == 0)
            {
                return false;
            }
            
            glMatrixMode(GL_MODELVIEW);
            glPushMatrix();
            if (status)
            {
                glLoadMatrixd(transform.
matrix[0]);
            }
            
            glMatrixMode(GL_PROJECTION);
            glPushMatrix();
            if (status)
            {
                glLoadMatrixd(projection.
matrix[0]);
            }
            bool needBlending = false;
            if (fTransparency > 0.0f)
            {
                needBlending = true;
                glColor4f(1.0, 1.0, 1.0, 1.0f-fTransparency );
            }
            else
                glColor4f(1.0, 1.0, 1.0, 1.0f);
            
            CubeMapTextureDrawUtility::bind( phongTextureId );
            
            if (fUseCustomDraw)
            {
                
                
                
                
                
                customDraw(context, renderItemList);
            }
            else
            {
                
                
            }
            
            CubeMapTextureDrawUtility::unbind();
            if (needBlending)
            {
                glColor4f(1.0, 1.0, 1.0, 1.0 );
                
            }
            glPopMatrix();
            glMatrixMode(GL_MODELVIEW);
            glPopMatrix();
        }
        return true;
    }
    
    
    void customDraw(
    {
        if ( 0 == gGLFT )
        MGLenum currentError = 0;
        glPushClientAttrib ( GL_CLIENT_ALL_ATTRIB_BITS );
        {
            int numRenderItems = renderItemList.
length();
 
            for (int renderItemIdx=0; renderItemIdx<numRenderItems; renderItemIdx++)
            {
                if (!renderItem) continue;
                if (!geometry) continue;
                fprintf(stderr, 
"MRenderItem source object path=%s\n", sourceDagPath.
fullPathName().
asChar());
                {
                    
                    if (sDebugConsolidation || sTestIndexing)
                    {
                        hwPhongShaderOverride::dumpIndexing(renderItem);
                    }
                }
                
                
                hwPhongShaderData* phongData = 
dynamic_cast<hwPhongShaderData*
>(renderItem->
customData());
                if (phongData)
                {
                    if (sDebugConsolidation)
                        fprintf(stderr, "Source object path=%s\n", phongData->fPath.asChar());
                }
                
                
                #define GLOBJECT_BUFFER_OFFSET(i) ((char *)NULL + (i)) // For GLObject offsets
                bool boundData = true;
                for (int i=0; i<bufferCount && boundData; i++)
                {
                    if (!buffer)
                    {
                        boundData = false;
                        continue;
                    }
                    GLuint * dataBufferId = NULL;
                    if (!dataHandle)
                    {
                        boundData = false;
                        continue;
                    }
                    dataBufferId = (GLuint *)(dataHandle);
                    unsigned int fieldOffset = desc.
offset();
 
                    unsigned int fieldStride = desc.
stride();
 
                    if (sDebugConsolidation)
                    {
                        fprintf(stderr, "Buffer(%d), Name(%s), BufferType(%s), BufferDimension(%d), BufferSemantic(%s), Offset(%d), Stride(%d), Handle(%d)\n",
                            i,
                            fieldOffset,
                            fieldStride,
                            *dataBufferId);
                    }
                    
                    if (*dataBufferId > 0)
                    {
                        gGLFT->
glBindBufferARB(MGL_ARRAY_BUFFER_ARB, *dataBufferId);
                        currentError = gGLFT->
glGetError();
                        if (currentError != MGL_NO_ERROR)
                            boundData = false;
                    }
                    else
                        boundData = false;
                    if (boundData)
                    {
                        
                        {
                            glEnableClientState(GL_VERTEX_ARRAY);
                            glVertexPointer(3, GL_FLOAT, fieldStride*4, GLOBJECT_BUFFER_OFFSET(fieldOffset));
                            currentError = gGLFT->glGetError();
                            if (currentError != MGL_NO_ERROR)
                                boundData = false;
                        }
                        {
                            glEnableClientState(GL_NORMAL_ARRAY);
                            glNormalPointer(GL_FLOAT, fieldStride*4, GLOBJECT_BUFFER_OFFSET(fieldOffset));
                            currentError = gGLFT->glGetError();
                            if (currentError != MGL_NO_ERROR)
                                boundData = false;
                        }
                    }
                }
                {
                    unsigned int indexBufferCount = 0;
                    GLuint *indexBufferId = NULL;
                    
                    if (indexBufferId  && (*indexBufferId > 0))
                    {
                        gGLFT->glBindBufferARB(MGL_ELEMENT_ARRAY_BUFFER_ARB, *indexBufferId);
                        currentError = gGLFT->glGetError();
                        if (currentError == MGL_NO_ERROR)
                        {
                            GLenum indexPrimTypeGL = GL_TRIANGLES;
                            switch (indexPrimType) {
                                indexPrimTypeGL = GL_POINTS; break;
                                indexPrimTypeGL = GL_LINES; break;
                                indexPrimTypeGL = GL_LINE_STRIP; break;
                                indexPrimTypeGL = GL_TRIANGLES; break;
                                indexPrimTypeGL = GL_TRIANGLE_STRIP; break;
                            default:
                                boundData = false;
                                break;
                            };
                            if (boundData)
                            {
                                
                                GLenum indexType =
                                glDrawElements(indexPrimTypeGL, indexBufferCount, indexType, GLOBJECT_BUFFER_OFFSET(0));
                            }
                        }
                    }
                }
            }
        }
        glPopClientAttrib();
    }
    {
        
        
        if (fDrawUsingShader)
        else
    }
    {
        TRACE_API_CALLS("hwPhongShaderOverride::isTransparent");
        if (fShaderNode)
        {
            return (fTransparency > 0.0f);
        }
        return false;
    }
    
    {
        if (fNTColorShaderInstance)
        {
            monitor = false;
            return fNTColorShaderInstance;
        }
        return NULL;
    }
    {
        return true;
    }
    {
        unsigned int numParams = params.
length();
 
        printf("DEBUGGING SHADER, BEGIN PARAM LIST OF LENGTH %d\n", numParams);
        for (unsigned int i=0; i<numParams; i++)
        {
            printf("ParamName='%s', ParamType=", params[i].asChar());
            {
                printf("'Invalid', ");
                break;
                printf("'Boolean', ");
                break;
                printf("'Integer', ");
                break;
                printf("'Float', ");
                break;
                printf("'Float2', ");
                break;
                printf("'Float3', ");
                break;
                printf("'Float4', ");
                break;
                printf("'Float4x4Row', ");
                break;
                printf("'Float4x4Col', ");
                break;
                printf("'1D Texture', ");
                break;
                printf("'2D Texture', ");
                break;
                printf("'3D Texture', ");
                break;
                printf("'Cube Texture', ");
                break;
                printf("'Sampler', ");
                break;
            default:
                printf("'Unknown', ");
                break;
            }
            printf(
"IsArrayParameter='%s'\n", shaderInstance->
isArrayParameter(params[i]) ? 
"YES" : 
"NO");
        }
        printf("END PARAM LIST\n");
    }
    
    void createShaderInstance()
    {
        TRACE_API_CALLS("hwPhongShaderOverride::createShaderInstance");
        if (!renderer)
            return;
        if (!shaderMgr)
            return;
        bool debugShader = false;
        
        
        
        if (!fShadowShaderInstance)
        {
            
            if (fShadowShaderInstance)
            {
                if (debugShader)
                    debugShaderParameters( fShadowShaderInstance );
            }
            else
            {
                fprintf(stderr, "Failed to load shadower shader for hwPhong\n");
            }
        }
        
        
        
        if (!fColorShaderInstance)
        {
            
            if (fColorShaderInstance && debugShader)
            {
                debugShaderParameters( fColorShaderInstance );
            }
        }
        if (!fNTColorShaderInstance)
        {
            if (fNTColorShaderInstance)
            {
                float val[4] = { 0.3f, 0.5f, 1.0f, 1.0f };
                fNTColorShaderInstance->
setParameter(
"diffuseColor", &val[0]);
            }
        }
    }
    
    
    void updateShaderInstance()
    {
        TRACE_API_CALLS("hwPhongShaderOverride::updateShaderInstance");
        if (!renderer)
            return;
        
        
        if (fColorShaderInstance)
        {
            
            if (fShaderNode && fShaderNode->attributesChangedVP2())
            {
                fColorShaderInstance->setParameter("emissionColor", &fAmbient[0] );
                fColorShaderInstance->setParameter("diffuseColor", &fDiffuse[0] );
                fColorShaderInstance->setParameter("specularColor", &fSpecular[0] );
                
                float specPower = fShininess[0];
                fColorShaderInstance->setParameter("specularPower", specPower );
                fShaderNode->markAttributesCleanVP2();
            }
        }
    }
    
    
    void rebuildTexture()
    {
        TRACE_API_CALLS("hwPhongShaderOverride::rebuildTexture");
        
        if (fShaderNode && fShaderNode->attributesChangedVP2())
        {
            if (theRenderer)
            {
                
                
                
                
                const float3 * amb = fShaderNode->Ambient();
                const float3 * diff = fShaderNode->Diffuse();
                const float3 * spec= fShaderNode->Specular();
                const float3 * shininess = fShaderNode->Shininess();
                newTextureName += (*amb)[0]; newTextureName += 
MString(
"_");
                newTextureName += (*amb)[1]; newTextureName += 
MString(
"_");
                newTextureName += (*amb)[2]; newTextureName += 
MString(
"_");
                newTextureName += (*diff)[0]; newTextureName += 
MString(
"_");
                newTextureName += (*diff)[1]; newTextureName += 
MString(
"_");
                newTextureName += (*diff)[2]; newTextureName += 
MString(
"_");
                newTextureName += (*spec)[0]; newTextureName += 
MString(
"_");
                newTextureName += (*spec)[1]; newTextureName += 
MString(
"_");
                newTextureName += (*spec)[2]; newTextureName += 
MString(
"_");
                newTextureName += (*shininess)[0]; newTextureName += 
MString(
"_");
                newTextureName += (*shininess)[1]; newTextureName += 
MString(
"_");
                newTextureName += (*shininess)[2];
                
                
                if(fTexture)
                {
                    if (theTextureManager)
                    {
                    }
                    fTexture = NULL;
                }
                
                
                if (!fTextureData)
                {
                    fTextureData =
                        new unsigned char[4*PHONG_TEXTURE_RES*PHONG_TEXTURE_RES*6];
                }
                if (fTextureData)
                {
                    int index = 0;
                    for ( int face=0 ; face<6 ; face++ )
                    {
                        for ( int j=0 ; j<PHONG_TEXTURE_RES ; j++ )
                        {
                            double t = 2*double(j)/(PHONG_TEXTURE_RES - 1) - 1; 
                            for ( int i=0 ; i<PHONG_TEXTURE_RES ; i++ )
                            {
                                double s = 2*double(i)/(PHONG_TEXTURE_RES - 1) - 1; 
                                double x = 0.0, y = 0.0, z = 0.0;
                                cubeToDir ( face, s, t, x, y, z );
                                fTextureData[index++] = (unsigned char)(255*intensity[0]);
                                fTextureData[index++] = (unsigned char)(255*intensity[1]);
                                fTextureData[index++] = (unsigned char)(255*intensity[2]);
                                fTextureData[index++] = 255;
                            }
                        }
                    }
                    {
                        desc.
fWidth = PHONG_TEXTURE_RES;
                    }
                    if (theTextureManager)
                    {
                        fTexture = theTextureManager->
acquireTexture( newTextureName, desc, fTextureData );
                    }
                }
                
                fShaderNode->markAttributesCleanVP2();
            }
        }
    }
    
    
    {
        TRACE_API_CALLS("hwPhongShaderOverride::printContextInformation");
        
        
        printf("Draw Context Diagnostics {\n");
        {
            printf("\tView position: %f, %f, %f\n", dtuple[0], dtuple[1], dtuple[2]);
            printf("\tView dir : %f, %f, %f\n", dtuple[0], dtuple[1], dtuple[2]);
            printf("\tView up : %f, %f, %f\n", dtuple[0], dtuple[1], dtuple[2]);
            printf("\tView right : %f, %f, %f\n", dtuple[0], dtuple[1], dtuple[2]);
            printf("\n");
            printf("\tScene bounding box = %g,%g,%g -> %g,%g,%g\n",
                bmin[0],bmin[1],bmin[2],
                bmax[0],bmax[1],bmax[2]);
            int originX; int originY; int width; int height;
            printf("\tRender target size: %d x %d\n", width, height);
            printf("\tViewport dimensions: %d, %d, -> %d, %d\n", originX, originY, width, height);
            
            
            else
            printf("\tLight Information for %s\n",
                ? "only lights clamped to light limit." : "lights not clamped to light limit.");
                
            float intensity = 1.0f;
            bool hasDirection = false;
            bool hasPosition = false;
            bool visualizeLighting = false;
            
            if (visualizeLighting )
            {
                for (unsigned int i=0; i<8; i++)
                {
                    GLenum light = GL_LIGHT0+i;
                    glDisable(light);
                }
                if (!lightCount)
                    glDisable(GL_LIGHTING);
                else
                    glEnable(GL_LIGHTING);
            }
            for (unsigned int i=0; i<lightCount; i++)
            {
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                bool getCommonParametersOnly = false;
                
                
                if (getCommonParametersOnly)
                {
                                     positions, direction,
                                     intensity, color, hasDirection,
                                     hasPosition,
                                     considerAllSceneLights);
                    printf("\tLight %d {\n", i);
                    printf("\t\tDirectional %d, Positional %d\n", hasDirection, hasPosition);
                    printf("\t\tDirection = %g, %g, %g\n", direction[0],direction[1],direction[2]);
                    unsigned int positionCount = positions.
length();
 
                    if (hasPosition && positionCount)
                    {
                        for (
unsigned int p=0; p<positions.
length(); p++)
 
                        {
                            printf("\t\tPosition[%d] = %g, %g, %g\n", p, positions[p][0], positions[p][1], positions[p][2]);
                            position += positions[p];
                        }
                        position[0] /= (float)positionCount;
                        position[1] /= (float)positionCount;
                        position[2] /= (float)positionCount;
                    }
                    printf("\t\tColor = %g, %g, %g\n", color[0], color[1], color[2]);
                    printf("\t\tIntensity = %g\n", intensity);
                    printf("\t}\n");
                }
                
                
                else
                {
                    unsigned int positionCount = 0;
                    position[0] = position[1] = position[2] = 0.0f;
                    if (lightParam)
                    {
                        printf("\tLight %d {\n", i);
                        for (
unsigned int p=0; p<params.
length(); p++)
 
                        {
                            switch (ptype)
                            {
                                printf(
"\t\tLight parameter %s. Bool[%d]\n", pname.
asChar(),
                                    intVals[0]);
                                break;
                                printf(
"\t\tLight parameter %s. Integer[%d]\n", pname.
asChar(),
                                    intVals[0]);
                                break;
                                printf(
"\t\tLight parameter %s. Float[%g]\n", pname.
asChar(),
                                    floatVals[0]);
                                break;
                                printf(
"\t\tLight parameter %s. Float[%g,%g]\n", pname.
asChar(),
                                    floatVals[0], floatVals[1]);
                                break;
                                printf(
"\t\tLight parameter %s. Float3[%g,%g,%g]\n", pname.
asChar(),
                                    floatVals[0], floatVals[1], floatVals[2]);
                                break;
                                printf(
"\t\tLight parameter %s. Float4[%g,%g,%g,%g]\n", pname.
asChar(),
                                    floatVals[0], floatVals[1], floatVals[2], floatVals[3]);
                                break;
                                printf("\t\tLight parameter %s. Float4x4Row [%g,%g,%g,%g]\n\t\t[%g,%g,%g,%g]\n\t\t[%g,%g,%g,%g]\n\t\t[%g,%g,%g,%g]\n",
                                    matrixVal[0][0], matrixVal[0][1], matrixVal[0][2], matrixVal[0][3],
                                    matrixVal[1][0], matrixVal[1][1], matrixVal[1][2], matrixVal[1][3],
                                    matrixVal[2][0], matrixVal[2][1], matrixVal[2][2], matrixVal[2][3],
                                    matrixVal[3][0], matrixVal[3][1], matrixVal[3][2], matrixVal[3][3]
                                    );
                                break;
                                printf(
"\t\tLight parameter %s. Float4x4Row\n", pname.
asChar() );
                                break;
                            {
                                printf(
"\t\tLight texture parameter %s. OpenGL texture id = %d\n", pname.
asChar(),
                                    *((int *)handle));
                                break;
                            }
                                printf(
"\t\tLight sampler parameter %s. filter = %d\n", pname.
asChar(),
                                break;
                            default:
                                break;
                            }
                            
                            
                            
                            switch (semantic)
                            {
                                printf("\t\t- Parameter semantic : light enabled\n");
                                break;
                                printf("\t\t- Parameter semantic : world position\n");
                                position += 
MFloatPoint( floatVals[0], floatVals[1], floatVals[2] );
                                positionCount++;
                                hasPosition = true;
                                break;
                                printf("\t\t- Parameter semantic : world direction\n");
                                direction = 
MFloatVector( floatVals[0], floatVals[1], floatVals[2] );
                                hasDirection = true;
                                break;
                                printf("\t\t- Parameter semantic : intensity\n");
                                intensity = floatVals[0];
                                break;
                                printf("\t\t- Parameter semantic : color\n");
                                color = 
MColor( floatVals[0], floatVals[1], floatVals[2] );
                                break;
                                printf("\t\t- Parameter semantic : emits-diffuse\n");
                                break;
                                printf("\t\t- Parameter semantic : emits-specular\n");
                                break;
                                printf("\t\t- Parameter semantic : decay rate\n");
                                break;
                                printf("\t\t- Parameter semantic : drop-off\n");
                                break;
                                printf("\t\t- Parameter semantic : cosine cone angle\n");
                                break;
                                printf("\t\t- Parameter semantic : shadow map\n");
                                break;
                                printf("\t\t- Parameter semantic : shadow map sampler\n");
                                break;
                                printf("\t\t- Parameter semantic : shadow map bias\n");
                                break;
                                printf("\t\t- Parameter semantic : shadow map size\n");
                                break;
                                printf("\t\t- Parameter semantic : shadow map view projection matrix\n");
                                break;
                                printf("\t\t- Parameter semantic : shadow color\n");
                                break;
                                printf("\t\t- Parameter semantic : global shadows on \n");
                                break;
                                printf("\t\t- Parameter semantic : local shadows on\n");
                                break;
                            default:
                                break;
                            }
                        }
                        
                        if (positionCount > 1)
                        {
                            position[0] /= (float)positionCount;
                            position[1] /= (float)positionCount;
                            position[2] /= (float)positionCount;
                            printf("\t\tCompute average position [%g,%g,%g]\n", position[0],
                                position[1], position[2]);
                        }
                        
                        printf("\t}\n");
                    }
                }
                    && lightCount < 8)
                {
                    GLenum light = GL_LIGHT0+i;
                    
                    float ambient[3] = { 0.0f, 0.0f, 0.0f };
                    float specular[3] = { 1.0f, 1.0f, 1.0f };
                    glLightfv(light, GL_AMBIENT, &ambient[0]);
                    color[0] *= intensity;
                    color[1] *= intensity;
                    color[2] *= intensity;
                    glLightfv(light, GL_DIFFUSE, &color[0]);
                    glLightfv(light, GL_SPECULAR, &specular[0]);
                    glLightf(light,  GL_CONSTANT_ATTENUATION, 1.0f);
                    glLightf(light,  GL_LINEAR_ATTENUATION, 0.0f);
                    glLightf(light,  GL_QUADRATIC_ATTENUATION, 0.0f);
                    glPushMatrix();
                    glLoadMatrixd( identity.
matrix[0] );
                    
                    if (hasPosition)
                        glLightfv(light, GL_POSITION, &position[0]);
                    else {
                        position[0] = position[1] = position[2] = 0.0f;
                        glLightfv(light, GL_POSITION, &position[0]);
                    }
                    
                    if (hasDirection)
                    {
                        glLightf(light,  GL_SPOT_CUTOFF, 90.0f);
                        glLightf(light,  GL_SPOT_EXPONENT, 64.0f);
                        glLightfv(light, GL_SPOT_DIRECTION, &direction[0]);
                    }
                    else
                    {
                        glLightf(light, GL_SPOT_CUTOFF, 180.0f);
                        glLightf(light, GL_SPOT_EXPONENT, 0.0f);
                    }
                    glEnable(light);
                    glPopMatrix();
                }
            }
        }
        printf("}\n");
    }
protected:
    hwPhongShaderOverride(
const MObject& obj)
    , fShaderNode(NULL)
    , fTextureData(NULL)
    , fDrawUsingShader(true) 
    , fUseCustomDraw(false) 
    , fDebugConsolidation(sDebugConsolidation) 
    , fHandlesConsolidateGeometry(true) 
    , fUseCustomData(false) 
    , fShaderBound(false)
    , fTexture(NULL)
    , fInColorPass(false)
    , fColorShaderInstance(NULL)
    , fNTColorShaderInstance(NULL)
    , fInShadowPass(false)
    , fShadowShaderInstance(NULL)
    , fTransparency(0.0f)
    {
#if MAYA_API_VERSION < 201650 
        
        fHandlesConsolidateGeometry = true;
#endif
        
        
        if (fDrawUsingShader)
        {
            createShaderInstance();
        }
        fAmbient[0] = fAmbient[1] = fAmbient[2] = 0.0f;
        fDiffuse[0] = fDiffuse[1] = fDiffuse[2] = fDiffuse[3] = 0.0f;
        fSpecular[0] = fSpecular[1] = fSpecular[2] = 0.0f;
        fShininess[0] = fShininess[1] = fShininess[2] = 500.0f;
    }
    
    
    
    hwPhongShader *fShaderNode;
    
    float fTransparency;
    float fAmbient[3];
    float fDiffuse[4];
    float fSpecular[3];
    float fShininess[3];
    
    unsigned char* fTextureData;
    
    bool fInColorPass;
    bool fInShadowPass;
    
    bool fDrawUsingShader;
    
    bool fUseCustomDraw;
    
    bool fDebugConsolidation;
    
    bool fUseCustomData;
    
    bool fHandlesConsolidateGeometry;
    
    
    
    
    mutable bool fShaderBound;
};
{
    TRACE_API_CALLS("initializePlugin");
    const MString UserClassify( 
"shader/surface/utility/:drawdb/shader/surface/hwPhongShader:swatch/"+swatchName );
 
    MFnPlugin plugin( obj, PLUGIN_COMPANY, 
"4.5", 
"Any");
 
    status = plugin.registerNode( "hwPhongShader", hwPhongShader::id,
                                  hwPhongShader::creator, hwPhongShader::initialize,
    if (!status) {
        status.
perror(
"registerNode");
        return status;
    }
    plugin.registerDragAndDropBehavior("hwPhongShaderBehavior",
                                       hwPhongShaderBehavior::creator);
    
        "drawdb/shader/surface/hwPhongShader",
        sHWPhongShaderRegistrantId,
        hwPhongShaderOverride::Creator);
}
{
    TRACE_API_CALLS("uninitializePlugin");
    
    plugin.deregisterNode( hwPhongShader::id );
    if (!status) {
        status.
perror(
"deregisterNode");
        return status;
    }
    plugin.deregisterDragAndDropBehavior("hwPhongShaderBehavior");
    
        "drawdb/shader/surface/hwPhongShader", sHWPhongShaderRegistrantId);
}
void * hwPhongShader::creator()
{
    TRACE_API_CALLS("creator");
    return new hwPhongShader();
}
MStatus hwPhongShader::initialize()
 
{
    
    
    TRACE_API_CALLS("initialize");
    
    
    aDiffuseColor = nAttr.
createColor( 
"diffuseColor", 
"dc" );
    aSpecularColor = nAttr.
createColor( 
"specularColor", 
"sc" );
    
    
    aShininess = cAttr.
create( 
"shininess", 
"sh" );
    
    
    
    
    
    
    addAttribute(aColor);
    addAttribute(aTransparency);
    addAttribute(aDiffuseColor);
    addAttribute(aSpecularColor);
    addAttribute(aShininess);
    addAttribute(aGeometryShape);
    attributeAffects (aColor,           outColor);
    attributeAffects (aTransparency,    outColor);
    attributeAffects (aDiffuseColor,    outColor);
    attributeAffects (aSpecularColor,   outColor);
    attributeAffects (aShininessX,      outColor);
    attributeAffects (aShininessY,      outColor);
    attributeAffects (aShininessZ,      outColor);
    attributeAffects (aShininess,       outColor);
}
{
    TRACE_API_CALLS("compute");
    if ((plug != outColor) && (plug.
parent() != outColor))
 
    
    outColor = color;
}
bool hwPhongShader::setInternalValueInContext( 
const MPlug &plug,
 
{
    if (plug == aColor)
    {
        if (val[0] != mAmbientColor[0] ||
            val[1] != mAmbientColor[1] ||
            val[2] != mAmbientColor[2])
        {
            mAmbientColor[0] = val[0];
            mAmbientColor[1] = val[1];
            mAmbientColor[2] = val[2];
            mAttributesChanged = true;
            mAttributesChangedVP2 = true;
        }
    }
    else if (plug == aTransparency)
    {
        if (val != mTransparency)
        {
            mTransparency = val;
            mAttributesChanged = true;
            mAttributesChangedVP2 = true;
        }
    }
    else if (plug == aDiffuseColor)
    {
        if (val[0] != mDiffuseColor[0] ||
            val[1] != mDiffuseColor[1] ||
            val[2] != mDiffuseColor[2])
        {
            mDiffuseColor[0] = val[0];
            mDiffuseColor[1] = val[1];
            mDiffuseColor[2] = val[2];
            mAttributesChanged = true;
            mAttributesChangedVP2 = true;
        }
    }
    else if (plug == aSpecularColor)
    {
        if (val[0] != mSpecularColor[0] ||
            val[1] != mSpecularColor[1] ||
            val[2] != mSpecularColor[2])
        {
            mSpecularColor[0] = val[0];
            mSpecularColor[1] = val[1];
            mSpecularColor[2] = val[2];
            mAttributesChanged = true;
            mAttributesChangedVP2 = true;
        }
    }
    else if (plug == aShininessX)
    {
        if (val != mShininess[0])
        {
            mShininess[0] = val; 
            mAttributesChanged = true;
            mAttributesChangedVP2 = true;
        }
    }
    else if (plug == aShininessY)
    {
        if (val != mShininess[1])
        {
            mShininess[1] = val; 
            mAttributesChanged = true;
            mAttributesChangedVP2 = true;
        }
    }
    else if (plug == aShininessZ)
    {
        if (val != mShininess[2])
        {
            mShininess[2] = val; 
            mAttributesChanged = true;
            mAttributesChangedVP2 = true;
        }
    }
    else if (plug == aGeometryShape)
    {
        mGeometryShape = handle.
asInt();
    }
    return false;
}
bool
hwPhongShader::getInternalValueInContext( 
const MPlug& plug,
{
    if (plug == aColor)
    {
        handle.
set( mAmbientColor[0], mAmbientColor[1], mAmbientColor[2] );
    }
    if (plug == aTransparency)
    {
        handle.
set( mTransparency );
    }
    else if (plug == aDiffuseColor)
    {
        handle.
set( mDiffuseColor[0], mDiffuseColor[1], mDiffuseColor[2] );
    }
    else if (plug == aSpecularColor)
    {
        handle.
set( mSpecularColor[0], mSpecularColor[1], mSpecularColor[2] );
    }
    else if (plug == aShininessX)
    {
        handle.
set( mShininess[0] );
    }
    else if (plug == aShininessY)
    {
        handle.
set( mShininess[1] );
    }
    else if (plug == aShininessZ)
    {
        handle.
set( mShininess[2] );
    }
    else if (plug == aGeometryShape)
    {
        handle.
set( (
int) mGeometryShape );
    }
    return false;
}
{
    TRACE_API_CALLS("bind");
    init_Phong_texture ();
}
{
    TRACE_API_CALLS("glBind");
    init_Phong_texture ();
}
{
    TRACE_API_CALLS("unbind");
    
    
    
}
{
    TRACE_API_CALLS("glUnbind");
    
    
    
}
                                int prim,
                                unsigned int writable,
                                int indexCount,
                                const unsigned int * indexArray,
                                int vertexCount,
                                const int * vertexIDs,
                                const float * vertexArray,
                                int normalCount,
                                const float ** normalArrays,
                                int colorCount,
                                const float ** colorArrays,
                                int texCoordCount,
                                const float ** texCoordArrays,
                                const int *faceIDs, 
                                const float * localUVCoord)
{
    TRACE_API_CALLS("geometry");
    if (mGeometryShape != 0)
        drawDefaultGeometry();
    else
        stat = draw( prim, writable, indexCount, indexArray, vertexCount,
                vertexIDs, vertexArray, normalCount, normalArrays, colorCount,
                colorArrays, texCoordCount, texCoordArrays, faceIDs, localUVCoord);
    return stat;
}
                                int prim,
                                unsigned int writable,
                                int indexCount,
                                const unsigned int * indexArray,
                                int vertexCount,
                                const int * vertexIDs,
                                const float * vertexArray,
                                int normalCount,
                                const float ** normalArrays,
                                int colorCount,
                                const float ** colorArrays,
                                int texCoordCount,
                                const float ** texCoordArrays,
                                const int *faceIDs, 
                                const float * localUVCoord)
{
    TRACE_API_CALLS("glGeometry");
    if (mGeometryShape != 0)
        drawDefaultGeometry();
    else
        stat = draw( prim, writable, indexCount, indexArray, vertexCount,
                    vertexIDs, vertexArray, normalCount, normalArrays, colorCount,
                    colorArrays, texCoordCount, texCoordArrays, faceIDs, localUVCoord);
    return stat;
}
hwPhongShader::renderSwatchImage( 
MImage & outImage )
{
    
    {
        MString meshShaderball(
"meshShaderball");
 
        unsigned int targetW, targetH;
        outImage.
getSize(targetW, targetH);
                                                                        thisMObject(), 
                                                                        outImage, 
    }
    
    if (pRenderer)
    {
        
        
        unsigned int* pIndexing = 0;
        unsigned int  numberOfData = 0;
        unsigned int  indexCount = 0;
        if (mGeometryShape == 2)
        {
        }
        else if (mGeometryShape == 3)
        {
        }
        if( !pGeomData )
        {
        }
        
        
        
        unsigned int width, height;
        unsigned int origWidth = width;
        unsigned int origHeight = height;
        {
            glPushAttrib ( GL_ALL_ATTRIB_BITS );
            
            
            {
                
                double l, r, b, t, n, f;
                glMatrixMode(GL_PROJECTION);
                glLoadIdentity();
                glOrtho( l, r, b, t, n, f );
                glMatrixMode(GL_MODELVIEW);
                glLoadIdentity();
                
                    glRotatef( 45, 1.0, 1.0, 1.0 );
                    glScalef( 1.5, 1.5, 1.5 );
                else
                    glScalef( 1.0, 1.0, 1.0 );
            }
            
            
            drawTheSwatch( pGeomData, pIndexing, numberOfData, indexCount );
            
            
            
            
            if (width != origWidth || height != origHeight)
            {
            }
            else
            {
            }
            glPopAttrib();
        }
        else
        {
        }
    }
    return status;
}
void
                                   unsigned int* pIndexing,
                                   unsigned int  numberOfData,
                                   unsigned int  indexCount )
{
    TRACE_API_CALLS("drwaTheSwatch");
    if( !pRenderer )    return;
    if ( mAttributesChanged || (phong_map_id == 0))
    {
        init_Phong_texture ();
    }
    
    float r, g, b, a;
    glClearColor( r, g, b, a );
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glShadeModel(GL_SMOOTH);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    CubeMapTextureDrawUtility::bind( phong_map_id );
    
    {
        if (pGeomData)
        {
            glPushClientAttrib ( GL_CLIENT_VERTEX_ARRAY_BIT );
            float *vertexData = (float *)( pGeomData[0].data() );
            if (vertexData)
            {
                glEnableClientState( GL_VERTEX_ARRAY );
                glVertexPointer ( 3, GL_FLOAT, 0, vertexData );
            }
            float *normalData = (float *)( pGeomData[1].data() );
            if (normalData)
            {
                glEnableClientState( GL_NORMAL_ARRAY );
                glNormalPointer (    GL_FLOAT, 0, normalData );
            }
            if (vertexData && normalData && pIndexing )
                glDrawElements ( GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, pIndexing );
            glPopClientAttrib();
            
        }
    }
    CubeMapTextureDrawUtility::unbind();
}
void hwPhongShader::drawDefaultGeometry()
{
    TRACE_API_CALLS("drawDefaultGeometry");
    if (!pRenderer)
        return;
    CubeMapTextureDrawUtility::bind( phong_map_id );
    
    {
        unsigned int numberOfData = 0;
        unsigned int *pIndexing = 0;
        unsigned int indexCount = 0;
        if (mGeometryShape == 2)
        {
        }
        else if (mGeometryShape == 3)
        {
        }
        
        if (pGeomData)
        {
            glPushClientAttrib ( GL_CLIENT_VERTEX_ARRAY_BIT );
            float *vertexData = (float *)( pGeomData[0].data() );
            if (vertexData)
            {
                glEnableClientState( GL_VERTEX_ARRAY );
                glVertexPointer ( 3, GL_FLOAT, 0, vertexData );
            }
            float *normalData = (float *)( pGeomData[1].data() );
            if (normalData)
            {
                glEnableClientState( GL_NORMAL_ARRAY );
                glNormalPointer (    GL_FLOAT, 0, normalData );
            }
            if (vertexData && normalData && pIndexing )
                glDrawElements ( GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, pIndexing );
            glPopClientAttrib();
            
        }
    }
    CubeMapTextureDrawUtility::unbind();
}
MStatus hwPhongShader::draw(
int prim,
 
                            unsigned int writable,
                            int indexCount,
                            const unsigned int * indexArray,
                            int vertexCount,
                            const int * vertexIDs,
                            const float * vertexArray,
                            int normalCount,
                            const float ** normalArrays,
                            int colorCount,
                            const float ** colorArrays,
                            int texCoordCount,
                            const float ** texCoordArrays,
                            const int *faceIDs, 
                            const float * localUVCoord)
{
    TRACE_API_CALLS("draw");
    if ( prim != GL_TRIANGLES && prim != GL_TRIANGLE_STRIP) {
    }
    if (sTestVertexIdAndFaceId || sTestIndexing)
    {
        if (vertexIDs)
        {
            for (int i=0; i<vertexCount; i++)
            {
                printf("VP1: vertexIDs[%d] = %d\n", i, vertexIDs[i]);
            }
        }
        if (faceIDs)
        {
            for (int i=0; i<vertexCount; i++)
            {
                printf("VP1: faceIDs[%d] = %d\n", i, faceIDs[i]);
            }
        }
    }
    if (sTestLocalUVCoord || sTestIndexing)
    {
        if (localUVCoord)
        {
            for (int i = 0; i < vertexCount; i++)
            {
                printf("VP1: localUVCoord[%d] = (%g, %g)\n", i, localUVCoord[i*2], localUVCoord[i*2 + 1]);
            }
        }
    }
    if (sTestIndexing)
    {
        unsigned int triangle = 0;
        for (int i=0; i<indexCount; i++)
        {
            triangle = i / 3;
            unsigned int location = indexArray[i];
            printf("Triangle[%d]. Face id = %d. vertex id=%d. localUV=%g,%g\n", triangle, 
                faceIDs[location], vertexIDs[location],
                localUVCoord[location * 2], localUVCoord[location * 2 + 1]);
        }
    }
    CubeMapTextureDrawUtility::bind( phong_map_id );
    
    
    {
        bool needBlending = false;
        if (mTransparency > 0.0f)
        {
            needBlending = true;
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            glColor4f(1.0f, 1.0f, 1.0f, 1.0f-mTransparency );
        }
        else
            glColor4f(1.0, 1.0, 1.0, 1.0f);
        glPushClientAttrib ( GL_CLIENT_VERTEX_ARRAY_BIT );
        
        
        
        glEnableClientState( GL_VERTEX_ARRAY );
        glEnableClientState( GL_NORMAL_ARRAY );
        glVertexPointer ( 3, GL_FLOAT, 0, &vertexArray[0] );
        glNormalPointer (    GL_FLOAT, 0, &normalArrays[0][0] );
        glDrawElements ( prim, indexCount, GL_UNSIGNED_INT, indexArray );
        
        
        
        
        glPopClientAttrib();
        if (needBlending)
        {
            glColor4f(1.0, 1.0, 1.0, 1.0f);
            glDisable(GL_BLEND);
        }
    }
    CubeMapTextureDrawUtility::unbind();
}
int hwPhongShader::normalsPerVertex()
{
    TRACE_API_CALLS("normalsPerVertex");
    return 1;
}
int hwPhongShader::texCoordsPerVertex()
{
    TRACE_API_CALLS("texCoordsPerVertex");
    return 0;
}
{
    return 0;
}
bool hwPhongShader::hasTransparency()
{
    return (mTransparency > 0.0f);
}
bool hwPhongShader::provideVertexIDs()
{
    return sTestVertexIdAndFaceId || sTestIndexing;
}
bool hwPhongShader::provideFaceIDs()
{
    return sTestVertexIdAndFaceId || sTestIndexing;
}
bool hwPhongShader::provideLocalUVCoord()
{
    return sTestLocalUVCoord || sTestIndexing;
}