#include <maya/MIOStream.h>
#include <math.h>
#include "pnTrianglesNode.h"
#include <maya/MFnPlugin.h>
#include <maya/MString.h>
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MFloatVector.h>
#include <maya/MGlobal.h>
#include <maya/M3dView.h>
#include <maya/MMaterial.h>
#include <maya/MDrawData.h>
#include <maya/MColor.h>
#include <maya/MDagPath.h>
#include <maya/MPoint.h>
#include <maya/MIOStream.h>
MTypeId     pnTriangles::id( 0x00105448 );
 
#define     pnDefaultMaxTessellation    0       // Default max tessellation
MObject     pnTriangles::attrSubdivisions;  
 
MObject     pnTriangles::attrWireframe;     
 
MObject     pnTriangles::attrNormalMode;    
 
MObject     pnTriangles::attrPointMode;     
 
MObject     pnTriangles::attrEnableVertexProgram; 
 
MObject     pnTriangles::attrEnablePixelProgram; 
 
pnTriangles::pnTriangles() 
:   fSubdivisions( 0 ),                                 
    fNumTextureCoords( 0 ),                             
    fNumNormals( 1 ),                                   
    fNumColors( 0 ),                                    
    fPointMode( kPointCubic ),                          
    fNormalMode( kNormalQuadratic ),                    
    fMaxTessellationLevel( pnDefaultMaxTessellation ),  
    fWireframe( false ),                                
    fInTexturedMode( false ),                           
    fTestVertexProgram( false ),
    fTestFragmentProgram( false ),
    fVertexShaderId( -1 ),
    fFragmentShaderId( -1 )
{
    fExtensionSupported[kPNTriangesEXT ] = false;
    fExtensionSupported[kVertexShaderEXT] = false;
    fExtensionSupported[kFragmentShaderEXT] = false;
    
    
    
    fExtensionSupported[kPNTriangesEXT] = initialize_ATI_Extension("GL_ATI_pn_triangles");
    
    
    if (fExtensionSupported[kPNTriangesEXT])
    {
        int val;
        glGetIntegerv( GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI, &val );
        fMaxTessellationLevel = val;
    }
    fExtensionSupported[kVertexShaderEXT] = initialize_ATI_Extension("GL_EXT_vertex_shader");
    fExtensionSupported[kFragmentShaderEXT] = initialize_ATI_Extension("GL_ATI_fragment_shader");
}
pnTriangles::~pnTriangles() 
{
    
    
    if (fExtensionSupported[kVertexShaderEXT])
    {
        if (fVertexShaderId != -1)
            glDeleteVertexShaderEXT(fVertexShaderId);
    }
}
{
    if( plug == pnTriangles::attrSubdivisions ) 
    {
        dh.
set( 
int(fSubdivisions) );
        return true;
    }
    else if ( plug == pnTriangles::attrColored)
    {
        dh.
set( (fNumColors > 0) );
        return true;
    }
    else if ( plug == pnTriangles::attrWireframe)
    {
        return true;
    }
    else if ( plug == pnTriangles::attrTextured)
    {
        dh.
set( (fNumTextureCoords > 0) );
        return true;
    }
    else if ( plug == pnTriangles::attrNormalMode )
    {
        if (fNormalMode == kNormalLinear)
        else
        return true;
    }
    else if ( plug == pnTriangles::attrPointMode )
    {
        if (fPointMode == kPointLinear)
        else
        return true;
    }
    else if ( plug == pnTriangles::attrEnableVertexProgram)
    {
        dh.
set( fTestVertexProgram );
        return true;
    }
    else if ( plug == pnTriangles::attrEnablePixelProgram)
    {
        dh.
set( fTestFragmentProgram );
        return true;
    }
    return false;
}
{
   if( plug == pnTriangles::attrSubdivisions ) 
    {
        fSubdivisions = dh.
asInt();
        
        
        if (fSubdivisions > fMaxTessellationLevel)
            fSubdivisions = fMaxTessellationLevel;
        return true;
    }
    else if ( plug == pnTriangles::attrColored)
    {
            fNumColors = 1;
        else
            fNumColors = 0;
        return true;
    }
    else if ( plug == pnTriangles::attrWireframe)
    {
            fWireframe = 1;
        else
            fWireframe = 0;
        return true;
    }
    else if ( plug == pnTriangles::attrTextured)
    {
            fNumTextureCoords = 1;
        else
            fNumTextureCoords = 0;
        return true;
    }
    else if ( plug == pnTriangles::attrNormalMode )
    {
            fNormalMode = kNormalLinear;
        else
            fNormalMode = kNormalQuadratic;
        return true;
    }
    else if ( plug == pnTriangles::attrPointMode )
    {
            fPointMode = kPointLinear;
        else
            fPointMode = kPointCubic;
        return true;
    }
    else if ( plug == pnTriangles::attrEnableVertexProgram )
    {
        {
            if (fExtensionSupported[kVertexShaderEXT])
                fTestVertexProgram = 1;
            else
                fTestVertexProgram = 0;
        }
        else
            fTestVertexProgram = 0;
        return true;
    }
    else if ( plug == pnTriangles::attrEnablePixelProgram )
    {
#ifdef _FRAGMENT_PROGRAM_READY_
            if (fExtensionSupported[kFragmentShaderEXT])
                fTestFragmentProgram = 1;
            else
                fTestFragmentProgram = 0;
        else
            fTestFragmentProgram = 0;
#else
        fTestFragmentProgram = 0;
#endif
        return true;
    }
    return false;
}
void* pnTriangles::creator()
{
    return new pnTriangles();
}
{
    
    
    
    
    
        
    
    
    
    stat = addAttribute( attrSubdivisions );
    if (!stat) { stat.
perror(
"addAttribute"); 
return stat;}
 
    stat = addAttribute( attrColored );
    if (!stat) { stat.
perror(
"addAttribute"); 
return stat;}
 
    stat = addAttribute( attrWireframe );
    if (!stat) { stat.
perror(
"addAttribute"); 
return stat;}
 
    stat = addAttribute( attrTextured );
    if (!stat) { stat.
perror(
"addAttribute"); 
return stat;}
 
    stat = addAttribute( attrNormalMode );
    if (!stat) { stat.
perror(
"addAttribute"); 
return stat;}
 
    stat = addAttribute( attrPointMode );
    if (!stat) { stat.
perror(
"addAttribute"); 
return stat;}
 
    stat = addAttribute( attrEnableVertexProgram );
    if (!stat) { stat.
perror(
"addAttribute"); 
return stat;}
 
    stat = addAttribute( attrEnablePixelProgram );
    if (!stat) { stat.
perror(
"addAttribute"); 
return stat;}
 
}
{
    
    
    MPlug   plug(thisMObject(), attr);
 
    if (!status)
    {
        status.
perror(
"pnTrianglesNode::bind plug.getValue.");
        return status;
    }
    if (!status)
    {
        status.
perror(
"pnTrianglesNode::bind construct data.");
        return status;
    }
    status = data.getData(value[0], value[1], value[2]);
    if (!status)
    {
        status.
perror(
"pnTrianglesNode::bind get values.");
        return status;
    }
}
#define DEG_TO_RAD(_x_) (3.14159265358979323846264338327950F / 180.0F * (_x_))
void pnTriangles::bindVertexProgram(
const MColor diffuse, 
 
{
    
    
    if (!fExtensionSupported[kVertexShaderEXT])
        return;
    
    glEnable(GL_VERTEX_SHADER_EXT);
    
    if (fVertexShaderId != -1)
    {
        glBindVertexShaderEXT (fVertexShaderId); 
        return;
    }
    fVertexShaderId = glGenVertexShadersEXT (1);
    
    GLuint Modelview = glBindParameterEXT (GL_MODELVIEW_MATRIX);
    GLuint Projection = glBindParameterEXT (GL_PROJECTION_MATRIX);
    
    
    
    GLuint Vertex = glBindParameterEXT (GL_CURRENT_VERTEX_EXT);
    
    GLuint Normal = glBindParameterEXT (GL_CURRENT_NORMAL); 
    
    
    
    glBindVertexShaderEXT (fVertexShaderId); 
    glBeginVertexShaderEXT ();
    {
        float direction[4] = { 0.57735f, 0.57735f, 0.57735f, 0.0f}; 
        GLuint lightDirection;
        GLuint diffMaterial;
        GLuint sceneAmbient;
        GLuint eyeVertex;
        GLuint clipVertex;
        GLuint eyeNormal;
        GLuint intensity;
        
        eyeVertex = glGenSymbolsEXT (GL_VECTOR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 1);
        clipVertex = glGenSymbolsEXT (GL_VECTOR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 1);
        eyeNormal = glGenSymbolsEXT (GL_VECTOR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 1);
        intensity = glGenSymbolsEXT (GL_VECTOR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 1);
        
        lightDirection = glGenSymbolsEXT (GL_VECTOR_EXT, GL_LOCAL_CONSTANT_EXT, GL_FULL_RANGE_EXT, 1);
        diffMaterial = glGenSymbolsEXT (GL_VECTOR_EXT, GL_LOCAL_CONSTANT_EXT, GL_FULL_RANGE_EXT, 1);
        sceneAmbient = glGenSymbolsEXT (GL_VECTOR_EXT, GL_LOCAL_CONSTANT_EXT, GL_FULL_RANGE_EXT, 1);
        glSetLocalConstantEXT (lightDirection, GL_FLOAT, direction);
        glSetLocalConstantEXT (diffMaterial, GL_FLOAT, (
void *)&(diffuse.
r));
        glSetLocalConstantEXT (sceneAmbient, GL_FLOAT, (
void *)&(ambient.
r));
        glShaderOp2EXT (GL_OP_MULTIPLY_MATRIX_EXT, eyeVertex, Modelview, Vertex);
        glShaderOp2EXT (GL_OP_MULTIPLY_MATRIX_EXT, GL_OUTPUT_VERTEX_EXT, Projection, eyeVertex);
        
        glShaderOp2EXT (GL_OP_MULTIPLY_MATRIX_EXT, eyeNormal, Modelview, Normal);
        glShaderOp2EXT (GL_OP_DOT3_EXT, intensity, lightDirection, eyeNormal);
        glShaderOp2EXT (GL_OP_ADD_EXT, intensity, sceneAmbient, intensity);
        glShaderOp2EXT (GL_OP_MUL_EXT, GL_OUTPUT_COLOR0_EXT, diffMaterial, intensity);
    }
    glEndVertexShaderEXT ();
}
void pnTriangles::bindFragmentProgram()
{
    
    
    if (!fExtensionSupported[kFragmentShaderEXT])
        return;
    
    glEnable(GL_FRAGMENT_SHADER_ATI);
    
    if (fFragmentShaderId != -1)
    {
        glBindFragmentShaderATI (fFragmentShaderId);
        return;
    }
    fFragmentShaderId = glGenFragmentShadersATI(1);
    glBindFragmentShaderATI (fFragmentShaderId);
    glBeginFragmentShaderATI();
    
    glEndFragmentShaderATI();
}
{
    
    glPushAttrib( GL_ALL_ATTRIB_BITS );
    glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
    MColor diffuse(1.0F, 1.0F, 0.0F, 1.0F);
 
    MColor specular(1.0F, 1.0F, 1.0F, 1.0F);
 
    MColor emission(0.0F, 0.0F, 0.0F, 1.0F);
 
    MColor ambient(0.2F, 0.2F, 0.2F, 1.0F);
 
    
    
    float shininess;
    bool hasTransparency = false;
    
    
    
    bool useInternalMaterialSetting = false;
    
    if (!useInternalMaterialSetting)
    {
        shininess = 13.0;
    }
    if (!fInTexturedMode)
    {
        if (!fTestVertexProgram && !useInternalMaterialSetting)
    }
    
    
    else
    {
        if (!useInternalMaterialSetting)
            diffuse.
r = diffuse.
g = diffuse.
b = diffuse.
a = 1.0;
    }
    
    
    if (fTestVertexProgram)
    {
        bindVertexProgram(diffuse, specular, emission, ambient);
    }
    else if (fTestFragmentProgram)
    {
        bindFragmentProgram();
    }
    
    
    else
    {
        
        
        glEnable(GL_COLOR_MATERIAL);
        glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
        if (fInTexturedMode)
        {
            glEnable( GL_TEXTURE_2D );
            float scaleS, scaleT, translateS, translateT, rotate;
                                              translateT, rotate);
            rotate = DEG_TO_RAD(-rotate);
            float c = cosf(rotate);
            float s = sinf(rotate);
            translateS += ((c+s)/2.0F);
            translateT += ((c-s)/2.0F);
            glMatrixMode(GL_TEXTURE);
            glPushMatrix();
            glLoadIdentity();
            if(scaleS != 1.0f || scaleT != 1.0f)
                glScalef(1.0f/scaleS, 1.0f/scaleT, 1.0f);
            if(translateS != 0.0f || translateT != 0.0f)
                glTranslatef(0.5f-translateS, 0.5f-translateT, 0.0f);
            else
                glTranslatef(0.5f, 0.5f, 0.0f);
            if(rotate != 0.0f)
                glRotatef(-rotate, 0.0f, 0.0f, 1.0f);
            glMatrixMode(GL_MODELVIEW);
        }
        if (!useInternalMaterialSetting)
        {
            glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
            glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
            glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
            glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
        }
        else
        {
        }
    }
    
    
    if (fExtensionSupported[kPNTriangesEXT] || (fSubdivisions == 0))
    {
        if (fSubdivisions != 0)
        {
            glEnable( GL_PN_TRIANGLES_ATI );
            
            
            if (fPointMode == kPointLinear)
                glPNTrianglesiATI( GL_PN_TRIANGLES_POINT_MODE_ATI, 
                                   GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI);
            else
                glPNTrianglesiATI( GL_PN_TRIANGLES_POINT_MODE_ATI, 
                                   GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI);
            
            
            if (fNormalMode == kNormalLinear)
                glPNTrianglesiATI( GL_PN_TRIANGLES_NORMAL_MODE_ATI, 
                                   GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI);
            else
                glPNTrianglesiATI( GL_PN_TRIANGLES_NORMAL_MODE_ATI, 
                                   GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI);
            
            
            glPNTrianglesiATI( GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI,
                              fSubdivisions );
        }
    }
}
{
    
    if (fTestVertexProgram)
    {
        glDisable(GL_VERTEX_SHADER_EXT);
    }
    
    else if (fTestFragmentProgram)
    {
        glDisable(GL_FRAGMENT_SHADER_ATI);
    }
    
    else
    {
        glDisable( GL_TEXTURE_2D );
        glDisable(GL_COLOR_MATERIAL);
        if (fInTexturedMode)
        {
            glMatrixMode(GL_TEXTURE);
            glPopMatrix();
            glMatrixMode(GL_MODELVIEW);
        }
    }
    
    
    if (fExtensionSupported[kPNTriangesEXT] || (fSubdivisions == 0))
    {
        if (fSubdivisions != 0)
            glDisable( GL_PN_TRIANGLES_ATI );
    }
    
    glPopClientAttrib();
    glPopAttrib();
}
unsigned int pnTriangles:: computePNTriangles(const float * vertexArray,
                                      const float * normalArray,
                                      const float * texCoordArray,
                                      float * pnVertexArray,
                                      float * pnNormalArray,
                                      float * pnTexCoordArray,
                                      float * pnColorArray)
{
    unsigned int triangleCount = 0;
    
    return triangleCount;
}
                                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)
{
    
    
    if (prim != GL_TRIANGLES)
    if (fWireframe)
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    bool needColors = (fNumColors && colorCount);
    bool needTexCoords = (fNumTextureCoords && texCoordCount);
    bool needNormals = (fNumNormals && normalCount);
    if (!fExtensionSupported[kPNTriangesEXT])
    {
        
    }
    glVertexPointer(3, GL_FLOAT, 0, vertexArray);
    glEnableClientState(GL_VERTEX_ARRAY);
    if (needNormals)
    {
        glNormalPointer(GL_FLOAT, 0, normalArrays[0]);
        glEnableClientState(GL_NORMAL_ARRAY);
    }
    if (needTexCoords)
    {
        glTexCoordPointer(2, GL_FLOAT, 0, texCoordArrays[0]);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    }
    if (needColors)
    {
        
        glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
        glColorPointer(4, GL_FLOAT, 0, colorArrays[0]);
        glEnableClientState(GL_COLOR_ARRAY);
    }
    glDrawElements(prim, indexCount, GL_UNSIGNED_INT, indexArray);
    if (fWireframe)
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
int pnTriangles::normalsPerVertex()
{
    return fNumNormals;
}
int pnTriangles::texCoordsPerVertex()
{
    if (fInTexturedMode)
        return fNumTextureCoords;
    else
        return 0;
}
int pnTriangles::colorsPerVertex()
{
    return fNumColors;
}
{ 
    const MString UserClassify( 
"shader/surface/utility" );
 
    
    MFnPlugin plugin( obj, PLUGIN_COMPANY, 
"4.5", 
"Any");
 
    status = plugin.registerNode( "pnTriangles", pnTriangles::id, pnTriangles::creator,
    if (!status) {
        status.
perror(
"registerNode");
        return status;
    }
    return status;
}
{
    status = plugin.deregisterNode( pnTriangles::id );
    if (!status) {
        status.
perror(
"deregisterNode");
        return status;
    }
    return status;
}