renderAccessNode/renderAccessNode.cpp
 
 
 
renderAccessNode/renderAccessNode.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.
// ==========================================================================
//+

// Install the plugin and create a renderAccessNode.  Set the
// ptWorld attribute to set the point to be converted from world
// space to screen space.

#include <maya/MIOStream.h> 
#include <stdlib.h> 

#include <maya/MString.h>
#include <maya/MTypeId.h>

#include <maya/MGlobal.h>
#include <maya/MFnPlugin.h>
#include <maya/MPxNode.h>

#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h> 

#include <maya/MFnNumericAttribute.h>

#include <maya/MFloatPoint.h>

#include <maya/MRenderData.h>
#include <maya/MRenderShadowData.h>
#include <maya/MRenderUtil.h>
#include <maya/MRenderCallback.h>

class myCallback2 : public MRenderCallback 
{
        public:
        myCallback2() {;}
        ~myCallback2() {;}
        void setObj(MObject &obj) { nodeObj = obj;}

        virtual bool shadowCastCallback( const MRenderShadowData &data );
        virtual bool renderCallback( const MRenderData &data );
        virtual bool postProcessCallback( const MRenderData &data );

        private:
        MObject nodeObj;
};

// Main Class //

class renderAccessNode : public MPxNode
{
        myCallback2 callback;

        public: // Methods

        renderAccessNode();
        virtual                 ~renderAccessNode();
        void                    postConstructor();


        virtual MStatus compute( const MPlug&, MDataBlock& );

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

        //  Id tag for use with binary file format
        //
        static MTypeId id;

        public:

        // Input
        static MObject     aSamples;
        static MObject     aDist;
        static MObject     aInColor;
        static MObject     aPointWorld;

        static MObject     aOutput;

};

// To get 3 float values from the node attribute
//
static void getFloat3(MObject node, MObject attr, MFloatPoint & val)
{
        // Get the attr to use
        //
        MObject object;
        MStatus status;
        MPlug   plug(node, attr);

        CHECK_MSTATUS(plug.getValue(object));

        MFnNumericData data(object, &status);
        CHECK_MSTATUS(status);

        CHECK_MSTATUS(data.getData(val[0], val[1], val[2]));
}


bool myCallback2::renderCallback( const MRenderData &data )
{
        MFloatPoint wp;
        getFloat3( nodeObj, renderAccessNode::aPointWorld, wp );

        fprintf( stderr, "\n*** Render Callback\n\n" );
        fprintf( stderr, "Image: %d %d\n", data.resX, data.resY );
        fprintf( stderr, "region rect: %d %d %d %d\n", 
                data.left, 
                data.bottom, 
                data.right, 
                data.top
        );
        return 0;
}

bool myCallback2::shadowCastCallback( const MRenderShadowData &data ) 
{
        MFloatPoint wp;
        getFloat3( nodeObj, renderAccessNode::aPointWorld, wp );

        fprintf( stderr, "\n*** Shadow cast Callback\n\n" );
        fprintf( stderr, "Light Position (%2.2f, %2.2f, %2.2f), size (%dx%d)\n", 
                data.lightPosition.x,
                data.lightPosition.y,
                data.lightPosition.z,
                data.shadowResX,
                data.shadowResY );

        fprintf( stderr, "Light type: %d, perspective: %d\n",
                data.lightType, data.perspective );

        MFloatPoint zp;
        data.worldToZbuffer( wp, zp );

        fprintf( stderr, "World Point( %g, %g, %g) = shadowmap (%g, %g, %g)\n\n",
                wp.x, wp.y, wp.z,
                zp.x, zp.y, zp.z );

        data.zbufferToWorld( zp, wp );

        fprintf( stderr, "shadowmap( %g, %g, %g ) = World Point( %g, %g, %g)\n\n",
                zp.x, zp.y, zp.z,
                wp.x, wp.y, wp.z );

        return 0;
}

bool myCallback2::postProcessCallback( const MRenderData &data ) 
{
        MFloatPoint wp;
        getFloat3( nodeObj, renderAccessNode::aPointWorld, wp );

        float screenZ;
        MPlug   plug(nodeObj, renderAccessNode::aDist );
        plug.getValue( screenZ );

        fprintf( stderr, "\n*** Post process Callback\n\n" );
        fprintf( stderr, "Image: %d %d\n", data.resX, data.resX );
        fprintf( stderr, "region rect: %d %d %d %d\n", 
                data.left, 
                data.bottom, 
                data.right, 
                data.top
        );
        fprintf( stderr, "Data size: %d x %d (%d)\n", data.xsize, data.ysize, data.bytesPerChannel );

        float r, g, b, a;

        r = 0.0;
        g = 255.0;
        b = 255.0;
        a = 255.0;

        //
        // modify rgba and depth values
        //

        short x, y;
        unsigned char *addr;

        for ( y = 0; y < data.ysize/2; y+= 3 )
        {
                for ( x = 0; x < data.xsize/2; x+= 3 )
                {
                        addr = data.rgbaArr + ((data.xsize*y+x)*4*data.bytesPerChannel);
                        if ( data.bytesPerChannel == 1 )
                        {
                                addr[0] = (char)a;      // a
                                addr[1] = (char)b;      // b
                                addr[2] = (char)g;      // g
                                addr[3] = (char)r;      // r
                        }
                        else
                        {
                                addr[0] = (char)a;
                                addr[1] = (char)(((a - (int)(a)) * 256.0));
                                addr[2] = (char)b;
                                addr[3] = (char)(((b - (int)(b)) * 256.0));
                                addr[4] = (char)g;
                                addr[5] = (char)(((g - (int)(g)) * 256.0));
                                addr[6] = (char)r;
                                addr[7] = (char)(((r - (int)(r)) * 256.0));

                        }
                        data.depthArr[ data.xsize*y+x ] = -0.25;
                }
        }
        MFloatPoint sp;
        
        data.worldToScreen( wp, sp );

        fprintf( stderr, "\nWorld point: ( %2.2f, %2.2f, %2.2f ) = Screen (%2.2f, %2.2f) depth: %2.2f\n\n",
                wp.x, wp.y, wp.z,
                sp.x, sp.y, sp.z );

        data.screenToWorld( sp, wp );

        fprintf( stderr, "Screen point: ( %2.2f, %2.2f, %2.2f ) = World (%2.2f, %2.2f, %2.2f)\n",
                sp.x, sp.y, sp.z,
                wp.x, wp.y, wp.z );

        fprintf( stderr, "\n" );
        return 0;
}


// attribute information

MTypeId renderAccessNode::id( 0x81018 );

// input

MObject     renderAccessNode::aSamples;
MObject     renderAccessNode::aDist;
MObject     renderAccessNode::aInColor;
MObject     renderAccessNode::aPointWorld;

MObject     renderAccessNode::aOutput;

renderAccessNode::renderAccessNode()
{}

renderAccessNode::~renderAccessNode()
{
        MRenderCallback::removeCallback( &callback );
}


void renderAccessNode::postConstructor()
{
        MObject obj = thisMObject();
        callback.setObj( obj );
        MRenderCallback::addCallback( &callback, 255 );
}

// creates an instance of the node
void * renderAccessNode::creator()
{
        return new renderAccessNode();
}

// initializes attribute information
MStatus renderAccessNode::initialize()
{
        MFnNumericAttribute nAttr; 

        // samples

        aSamples = nAttr.create( "samples", "spl", MFnNumericData::kShort, 0 );
        nAttr.setMin(0);
        CHECK_MSTATUS(addAttribute( aSamples ));

        // distance

        aDist = nAttr.create( "distance", "dis", MFnNumericData::kFloat, 0 );
        CHECK_MSTATUS(addAttribute( aDist ));

        // inColor

        aInColor = nAttr.createColor( "inColor", "ic" );
        nAttr.setStorable(false);
        CHECK_MSTATUS(addAttribute( aInColor ));

        // pointWorld

        aPointWorld = nAttr.createPoint( "worldPoint", "wp" );
        nAttr.setStorable(false);
        nAttr.setWritable(true);
        CHECK_MSTATUS(addAttribute( aPointWorld ));

        // Output

        aOutput = nAttr.create( "output", "out", MFnNumericData::kFloat, 1.0 );
        CHECK_MSTATUS(addAttribute( aOutput ));

        attributeAffects( aPointWorld, aOutput );
        attributeAffects( aInColor, aOutput );

        return MS::kSuccess;
}


MStatus renderAccessNode::compute( const MPlug& plug, MDataBlock& data)
{
        if ( plug == renderAccessNode::aOutput )
        {
                MDataHandle outHandle = data.outputValue( aOutput );
                float& of = outHandle.asFloat();
                of = 1.0f;

                outHandle.setClean();
        }

        return MS::kSuccess;
}


//
//
//

MStatus initializePlugin( MObject obj )
{ 
   const MString UserClassify( "utility/general" );

        MFnPlugin plugin( obj, PLUGIN_COMPANY, "4.5", "Any");
        plugin.registerNode( "renderAccessNode", renderAccessNode::id,
                         renderAccessNode::creator, renderAccessNode::initialize,
                         MPxNode::kDependNode, &UserClassify );

   return MS::kSuccess;

}

MStatus uninitializePlugin( MObject obj )
{
        MFnPlugin plugin( obj );
        plugin.deregisterNode( renderAccessNode::id );

        return MS::kSuccess;
}