- Main Page
- Related Pages
- Modules
- Classes
- Examples

# hwManagedTextureShader.cpp

    //-
    // ==========================================================================
    // Copyright 1995,2006,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:
    //      This is an example of using the built in texture cache for drawing.
    //

    #ifdef WIN32
    #pragma warning( disable : 4786 )       // Disable STL warnings.
    #endif

    #include <maya/MIOStream.h>
    #include <maya/MString.h>
    #include <maya/MPlug.h>
    #include <maya/MFnPlugin.h>
    #include <maya/MPxHwShaderNode.h>
    #include <maya/MFnMesh.h>

    #if MAYA_API_VERSION >= 800
        #include <maya/MHwTextureManager.h>
        #include <maya/MImageFileInfo.h>
    #endif

    #if defined(OSMac_MachO_)
    #include <OpenGL/gl.h>
    #include <OpenGL/glu.h>
    #else
    #include <GL/gl.h>
    #include <GL/glu.h>
    #endif

    class hwManagedTextureShader : public MPxHwShaderNode
    {
        public:
                        hwManagedTextureShader();
        virtual         ~hwManagedTextureShader();

        virtual void    postConstructor();

        virtual MStatus glBind(const MDagPath& shapePath);
        virtual MStatus glUnbind(const MDagPath& shapePath);
        virtual MStatus glGeometry( const MDagPath&,
                                  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);

        virtual int     texCoordsPerVertex();
        virtual int     normalsPerVertex();
        virtual bool    supportsBatching() const;

        static  void *  creator();
        static  MStatus initialize();

        GLboolean lightingOn;
        bool boundTexture;

        static  MTypeId id;
    };

    // This ID provided by Maya. Do not change.
    MTypeId hwManagedTextureShader::id( 0x81033 );

    void hwManagedTextureShader::postConstructor( )
    {
        setMPSafe(false);
    }

    hwManagedTextureShader::hwManagedTextureShader()
    {
    }

    hwManagedTextureShader::~hwManagedTextureShader()
    {
    }

    void * hwManagedTextureShader::creator()
    {
        return new hwManagedTextureShader();
    }

    MStatus hwManagedTextureShader::initialize()
    {
        return MS::kSuccess;
    }

    /* virtual */
    MStatus
    hwManagedTextureShader::glBind(const MDagPath& path)
    {
        // ONLY push and pop required attributes performance reasons...
        //
        glPushAttrib(GL_LIGHTING_BIT);

        lightingOn = glIsEnabled(GL_LIGHTING);

        if (lightingOn)
        {
            glEnable(GL_COLOR_MATERIAL);
            glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
        }

        // Base colour is always white
        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

        // Bind texture
    #if MAYA_API_VERSION >= 800
        MObject object = path.node();
        MFnMesh mesh(object);
        MString uvSetName("map1");
        MObjectArray textures;

        boundTexture = false;
        MStatus status = mesh.getAssociatedUVSetTextures(uvSetName, textures);
        if (status == MS::kSuccess && textures.length())
        {
            MImageFileInfo::MHwTextureType hwType;
            if (MS::kSuccess == MHwTextureManager::glBind( textures[0], hwType ))
            {
                boundTexture = true;
            }
        }

        if( !boundTexture)
        {
            glDisable(GL_TEXTURE_2D);
            glBindTexture(GL_TEXTURE_2D, 0);
        }
    #else
        // To get this code branch to compile, replace <change file name here>
        // with an appropriate file name
        static GLuint id = 0;
        if (id == 0)
        {
            MImage fileImage;
            MStatus status = fileImage.readFromFile("<change file name here>");
            glGenTextures(1, &id);
            glEnable(GL_TEXTURE_2D);
            glBindTexture(GL_TEXTURE_2D, id);
            GLuint width, height;
            fileImage.getSize( width, height);
            glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, fileImage.pixels());
        }
        else
        {
            glEnable(GL_TEXTURE_2D);
            glBindTexture(GL_TEXTURE_2D, id);
        }
        boundTexture = true;

    #endif
        if( boundTexture)
        {
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        }
        glEnableClientState(GL_VERTEX_ARRAY);

        return MS::kSuccess;
    }

    /* virtual */
    MStatus
    hwManagedTextureShader::glUnbind(const MDagPath& shapePath)
    {
        // Cleanup GL state, without using pushing and popping attributes
        //
        glDisableClientState(GL_VERTEX_ARRAY);
        if (lightingOn)
        {
            glDisable(GL_COLOR_MATERIAL);
            glDisableClientState(GL_NORMAL_ARRAY);
        }
        if (boundTexture)
        {
            glDisableClientState( GL_TEXTURE_COORD_ARRAY );
            glDisable(GL_TEXTURE_2D);
            glBindTexture(GL_TEXTURE_2D, 0);
        }

        // ONLY push and pop required attributes performance reasons...
        //
        glPopAttrib();
        return MS::kSuccess;
    }

    bool
    hwManagedTextureShader::supportsBatching() const
    {
        return true;
    }

    /* virtual */
    MStatus hwManagedTextureShader::glGeometry( const MDagPath& path,
                                    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)
    {
        glVertexPointer ( 3, GL_FLOAT, 0, &vertexArray[0] );

        if (boundTexture && texCoordCount && texCoordArrays[0] != NULL)
        {
            glEnableClientState( GL_TEXTURE_COORD_ARRAY );
            glTexCoordPointer( 2, GL_FLOAT, 0, &texCoordArrays[0][0] );
        }
        else
        {
            glDisableClientState( GL_TEXTURE_COORD_ARRAY );
        }

        if (lightingOn && normalCount && normalArrays[0][0])
        {
            // Don't route normals if we don't need them
            glEnableClientState(GL_NORMAL_ARRAY);
            glNormalPointer ( GL_FLOAT, 0, &normalArrays[0][0] );
        }
        else
        {
            glDisableClientState( GL_NORMAL_ARRAY );
        }

        glDrawElements ( prim, indexCount, GL_UNSIGNED_INT, indexArray );

        return MS::kSuccess;
    }

    // virtual
    int hwManagedTextureShader::texCoordsPerVertex()
    {
        return 1;
    }

    // virtual
    int hwManagedTextureShader::normalsPerVertex()
    {
        return 1;
    }

    MStatus initializePlugin( MObject obj )
    {
        MStatus   status;

        const MString UserClassify( "shader/surface/utility/" );

        MFnPlugin plugin( obj, PLUGIN_COMPANY, "8.0", "Any");

        status = plugin.registerNode("hwManagedTextureShader",
                                     hwManagedTextureShader::id,
                                     hwManagedTextureShader::creator,
                                     hwManagedTextureShader::initialize,
                                     MPxNode::kHwShaderNode, &UserClassify );
        CHECK_MSTATUS(status);

        return status;
    }

    MStatus uninitializePlugin( MObject obj )
    {
        MStatus   status;
        MFnPlugin plugin( obj );

        status = plugin.deregisterNode( hwManagedTextureShader::id );
        CHECK_MSTATUS(status);

        return status;
    }