#include <math.h>
#include <maya/MFnPlugin.h>
#include <maya/MPxNode.h>
#include <maya/MString.h>
#include <maya/MTypeId.h>
#include <maya/MIOStream.h>
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MArrayDataHandle.h>
#include <maya/MFnMatrixAttribute.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnLightDataAttribute.h>
#include <maya/MFloatPoint.h>
#include <maya/MFloatVector.h>
#include <maya/MFloatMatrix.h>
class anisotropicShaderNode : 
public MPxNode 
{
    public:
    anisotropicShaderNode();
    virtual ~anisotropicShaderNode();
    static  void *  creator();
    
    private:
    static void setAttribute( void );
    
    static MObject aDiffuseReflectivity;    
 
    
    static MObject aLightShadowFraction;
 
    static MObject aPreShadowIntensity;
 
    
    
    
};
const MTypeId anisotropicShaderNode::id( 0x81014 );
 
MObject    anisotropicShaderNode::aDiffuseReflectivity;
 
MObject    anisotropicShaderNode::aColor;
 
MObject    anisotropicShaderNode::aInTransparency;
 
MObject    anisotropicShaderNode::aNormalCamera;
 
MObject    anisotropicShaderNode::aLightData;
 
MObject    anisotropicShaderNode::aLightDirection;
 
MObject    anisotropicShaderNode::aLightIntensity; 
 
MObject    anisotropicShaderNode::aLightAmbient;
 
MObject    anisotropicShaderNode::aLightDiffuse;
 
MObject    anisotropicShaderNode::aLightSpecular;
 
MObject    anisotropicShaderNode::aLightShadowFraction;
 
MObject    anisotropicShaderNode::aPreShadowIntensity;
 
MObject    anisotropicShaderNode::aLightBlindData;
 
MObject    anisotropicShaderNode::aSpecularCoeff;
 
MObject    anisotropicShaderNode::aPointCamera;
 
MObject    anisotropicShaderNode::aSpecColor;
 
MObject    anisotropicShaderNode::aRoughness1;
 
MObject    anisotropicShaderNode::aRoughness2;
 
MObject    anisotropicShaderNode::aRayDirection;
 
MObject    anisotropicShaderNode::aAxesVector;
 
MObject    anisotropicShaderNode::aMatrixOToW;
 
MObject    anisotropicShaderNode::aMatrixWToC;
 
MObject    anisotropicShaderNode::aOutColor;
 
MObject    anisotropicShaderNode::aOutTransparency;
 
#define MAKE_INPUT(attr)                        \
    CHECK_MSTATUS( attr.setKeyable(true) );     \
    CHECK_MSTATUS( attr.setStorable(true) );    \
    CHECK_MSTATUS( attr.setReadable(true) );    \
    CHECK_MSTATUS( attr.setWritable(true) );
#define MAKE_OUTPUT(attr)                       \
    CHECK_MSTATUS(attr.setKeyable(false) );     \
    CHECK_MSTATUS(attr.setStorable(false) );    \
    CHECK_MSTATUS(attr.setReadable(true) );     \
    CHECK_MSTATUS(attr.setWritable(false) );
void anisotropicShaderNode::postConstructor( )
{
    setMPSafe(true);
}
anisotropicShaderNode::anisotropicShaderNode()
{
}
anisotropicShaderNode::~anisotropicShaderNode()
{
}
void* anisotropicShaderNode::creator()
{
    return new anisotropicShaderNode;
}
MStatus anisotropicShaderNode::initialize()
 
{
    aMatrixOToW = mAttr.
create( 
"matrixObjectToWorld", 
"mow",
 
    aMatrixWToC = mAttr.
create( 
"matrixWorldToEye", 
"mwc", 
    aDiffuseReflectivity = nAttr.
create( 
"diffuseReflectivity", 
"drfl",
    MAKE_INPUT(nAttr);
    MAKE_INPUT(nAttr);
    aNormalCamera = nAttr.
createPoint( 
"normalCamera", 
"n" );
    MAKE_INPUT(nAttr);
    aLightDirection = nAttr.
createPoint( 
"lightDirection", 
"ld");
    aLightIntensity = nAttr.
createColor( 
"lightIntensity", 
"li" );
    aLightAmbient = nAttr.
create( 
"lightAmbient", 
"la",
    aLightDiffuse = nAttr.
create( 
"lightDiffuse", 
"ldf", 
    aLightSpecular = nAttr.
create( 
"lightSpecular", 
"ls",
    aLightShadowFraction = nAttr.
create( 
"lightShadowFraction", 
"lsf",
    aPreShadowIntensity = nAttr.
create( 
"preShadowIntensity", 
"psi",
    aLightBlindData = nAttr.
createAddr( 
"lightBlindData", 
"lbld");
    aLightData = lAttr.
create( 
"lightDataArray", 
"ltd",
                aLightDirection, 
                aLightIntensity, 
                aLightAmbient, 
                aLightDiffuse, 
                aLightSpecular,
                aLightShadowFraction,
                aPreShadowIntensity,
                aLightBlindData);
                     false, 0.0f, 1.0f, NULL) );
    aSpecularCoeff = nAttr.
create( 
"specularCoeff", 
"scf", 
    MAKE_INPUT(nAttr);
    aPointCamera = nAttr.
createPoint( 
"pointCamera", 
"pc" );
    MAKE_INPUT(nAttr);
    
    aInTransparency = nAttr.
createColor( 
"transparency", 
"it" );
    MAKE_INPUT(nAttr);
    
    aRayDirection = nAttr.
createPoint( 
"rayDirection", 
"rd" );
    MAKE_INPUT(nAttr);
    
    aSpecColor = nAttr.
createColor( 
"specularColor",
"sc" );
    MAKE_INPUT(nAttr);
    
    
    MAKE_INPUT(nAttr);
    MAKE_INPUT(nAttr);
    
    MAKE_OUTPUT(nAttr);
    
    aOutTransparency = nAttr.
createColor( 
"outTransparency", 
"ot" );
    MAKE_OUTPUT(nAttr);
    setAttribute();
}
void anisotropicShaderNode::setAttribute( void )
{
        
    
    
    CHECK_MSTATUS( attributeAffects( aDiffuseReflectivity, aOutColor) );
 
    CHECK_MSTATUS( attributeAffects( aLightShadowFraction, aOutColor) );
 
    CHECK_MSTATUS( attributeAffects( aPreShadowIntensity, aOutColor) );
 
    CHECK_MSTATUS( attributeAffects( aInTransparency,  aOutTransparency ) );
 
}
#ifndef MIN
#define MIN(a,b) ( a<b?a:b )
#endif
{
    if ((plug == aOutColor) || (plug.
parent() == aOutColor))
 
    {
        
        
        
        
        
        
        
        for( int count=0; count < numLights; count++ ) {
            
                ambientColor[0] += lightIntensity[0] * surfaceColor[0];
                ambientColor[1] += lightIntensity[1] * surfaceColor[1];
                ambientColor[2] += lightIntensity[2] * surfaceColor[2];
            }
            float cosln = lightDirection * N;
            if( cosln > 0.0f ){ 
                
                
                    float cosDif = cosln * diffuseReflectivity;
                    diffuseColor[0] += lightIntensity[0] * cosDif * surfaceColor[0];
                    diffuseColor[1] += lightIntensity[1] * cosDif * surfaceColor[1];
                    diffuseColor[2] += lightIntensity[2] * cosDif * surfaceColor[2];
                }
                
                    MFloatVector half = calcHalfVector( viewDirection, lightDirection );
 
                    
                    if( fabs(1.0-fabs(N*ca)) <= 0.0001f ){
                        nA = origin - surfacePoint;
                    }else{
                        nA = ca;
                    }
                    azimuthH = N ^ azimuthH;
                    float cos_phai = x * azimuthH;
                    float sin_phai = 0.0;
                    if( fabs(1 - cos_phai*cos_phai) < 0.0001 ){
                        sin_phai = 0.0;
                    }else{
                        sin_phai = sqrtf( 1.0f - cos_phai*cos_phai );
                    }
                    double co = pow( (half * N), 4.0f );
                    double t = tan( acos(half*N) );
                    t *= -t;
                    double aaa = cos_phai / rough1;
                    double bbb = sin_phai / rough2;
                    t = t * ( aaa*aaa + bbb*bbb );
                    double D = pow( (1.0/((double)rough1*(double)rough2 * co)), t );
                    double aa = (2.0 * (N*half) * (N*viewDirection) ) / (viewDirection*half);
                    double bb = (2.0 * (N*half) * (N*lightDirection) ) / (viewDirection*half);
                    double cc = 1.0;
                    double G = 0.0;
                    G = MIN( aa, bb );
                    G = MIN( G, cc );
                    float s = (float) (D * G /
                            (double)((N*lightDirection) * (N*viewDirection)));
                    specularColor[0] += lightIntensity[0] * specColor[0] * 
                                            s * specularCoeff;
                    specularColor[1] += lightIntensity[1] * specColor[1] * 
                                            s * specularCoeff;
                    specularColor[2] += lightIntensity[2] * specColor[2] * 
                                            s * specularCoeff;
                }
            }
                break;
            }
        }
        
        resultColor = diffuseColor + specularColor + ambientColor;
        resultColor[0] *= ( 1.0f - transparency[0] );
        resultColor[1] *= ( 1.0f - transparency[1] );
        resultColor[2] *= ( 1.0f - transparency[2] );
        
        outColor = resultColor;
    }
    else if ((plug == aOutTransparency) || (plug.
parent() == aOutTransparency))
 
    {
        
        outTrans = tr;
    } else
}
{
    return H;
}
{
   const MString UserClassify( 
"shader/surface" );
 
   MFnPlugin plugin( obj, 
"Tadashi Endo", 
"4.5", 
"Any");
 
   CHECK_MSTATUS( plugin.registerNode( 
"anisotropicShader", anisotropicShaderNode::id,
 
                         anisotropicShaderNode::creator, 
                         anisotropicShaderNode::initialize, 
}
{
   CHECK_MSTATUS( plugin.deregisterNode( anisotropicShaderNode::id ) );
 
}