#include <maya/MPxLocatorNode.h>
#include <maya/MString.h>
#include <maya/MDagPath.h>
#include <maya/MTypeId.h>
#include <maya/MPlug.h>
#include <maya/MVector.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MColor.h>
#include <maya/M3dView.h>
#include <maya/MFnPlugin.h>
#include <maya/MDistance.h>
#include <maya/MMatrix.h>
#include <maya/MFnUnitAttribute.h>
#include <maya/MDrawRegistry.h>
#include <maya/MPxDrawOverride.h>
#include <maya/MUserData.h>
#include <maya/MDrawContext.h>
#include <maya/MGlobal.h>
#include <maya/MSelectionList.h>
#include <maya/MViewport2Renderer.h>
#include <maya/MHWGeometryUtilities.h>
#include <maya/MStateManager.h>
#include <maya/MShaderManager.h>
#include <assert.h>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dcompiler.h>
#ifndef D3DCOMPILE_ENABLE_STRICTNESS
#define D3DCOMPILE_ENABLE_STRICTNESS D3D10_SHADER_ENABLE_STRICTNESS
#define D3DCOMPILE_DEBUG D3D10_SHADER_DEBUG
#endif
#include <xnamath.h>
#endif //_WIN32
static float sole[][3] = { { 0.00f, 0.0f, -0.70f },
{ 0.04f, 0.0f, -0.69f },
{ 0.09f, 0.0f, -0.65f },
{ 0.13f, 0.0f, -0.61f },
{ 0.16f, 0.0f, -0.54f },
{ 0.17f, 0.0f, -0.46f },
{ 0.17f, 0.0f, -0.35f },
{ 0.16f, 0.0f, -0.25f },
{ 0.15f, 0.0f, -0.14f },
{ 0.13f, 0.0f, 0.00f },
{ 0.00f, 0.0f, 0.00f },
{ -0.13f, 0.0f, 0.00f },
{ -0.15f, 0.0f, -0.14f },
{ -0.16f, 0.0f, -0.25f },
{ -0.17f, 0.0f, -0.35f },
{ -0.17f, 0.0f, -0.46f },
{ -0.16f, 0.0f, -0.54f },
{ -0.13f, 0.0f, -0.61f },
{ -0.09f, 0.0f, -0.65f },
{ -0.04f, 0.0f, -0.69f },
{ -0.00f, 0.0f, -0.70f } };
static float heel[][3] = { { 0.00f, 0.0f, 0.06f },
{ 0.13f, 0.0f, 0.06f },
{ 0.14f, 0.0f, 0.15f },
{ 0.14f, 0.0f, 0.21f },
{ 0.13f, 0.0f, 0.25f },
{ 0.11f, 0.0f, 0.28f },
{ 0.09f, 0.0f, 0.29f },
{ 0.04f, 0.0f, 0.30f },
{ 0.00f, 0.0f, 0.30f },
{ -0.04f, 0.0f, 0.30f },
{ -0.09f, 0.0f, 0.29f },
{ -0.11f, 0.0f, 0.28f },
{ -0.13f, 0.0f, 0.25f },
{ -0.14f, 0.0f, 0.21f },
{ -0.14f, 0.0f, 0.15f },
{ -0.13f, 0.0f, 0.06f },
{ -0.00f, 0.0f, 0.06f } };
static int soleCount = 21;
static int heelCount = 17;
class footPrint : public MPxLocatorNode
{
public:
footPrint();
virtual ~footPrint();
virtual MStatus compute( const MPlug& plug, MDataBlock& data );
virtual void draw( M3dView & view, const MDagPath & path,
M3dView::DisplayStyle style,
M3dView::DisplayStatus status );
virtual bool isBounded() const;
virtual MBoundingBox boundingBox() const;
static void * creator();
static MStatus initialize();
static MObject size;
public:
static MTypeId id;
static MString drawDbClassification;
static MString drawRegistrantId;
};
MObject footPrint::size;
MTypeId footPrint::id( 0x80007 );
MString footPrint::drawDbClassification("drawdb/geometry/footPrint");
MString footPrint::drawRegistrantId("FootprintNodePlugin");
footPrint::footPrint() {}
footPrint::~footPrint() {}
MStatus footPrint::compute( const MPlug& , MDataBlock& )
{
return MS::kUnknownParameter;
}
void footPrint::draw( M3dView & view, const MDagPath & ,
M3dView::DisplayStyle style,
M3dView::DisplayStatus status )
{
MObject thisNode = thisMObject();
MPlug plug( thisNode, size );
MDistance sizeVal;
plug.getValue( sizeVal );
float multiplier = (float) sizeVal.asCentimeters();
view.beginGL();
if ( ( style == M3dView::kFlatShaded ) ||
( style == M3dView::kGouraudShaded ) )
{
glPushAttrib( GL_CURRENT_BIT );
if ( status == M3dView::kActive ) {
view.setDrawColor( 13, M3dView::kActiveColors );
} else {
view.setDrawColor( 13, M3dView::kDormantColors );
}
glBegin( GL_TRIANGLE_FAN );
int i;
int last = soleCount - 1;
for ( i = 0; i < last; ++i ) {
glVertex3f( sole[i][0] * multiplier,
sole[i][1] * multiplier,
sole[i][2] * multiplier );
}
glEnd();
glBegin( GL_TRIANGLE_FAN );
last = heelCount - 1;
for ( i = 0; i < last; ++i ) {
glVertex3f( heel[i][0] * multiplier,
heel[i][1] * multiplier,
heel[i][2] * multiplier );
}
glEnd();
glPopAttrib();
}
glBegin( GL_LINES );
int i;
int last = soleCount - 1;
for ( i = 0; i < last; ++i ) {
glVertex3f( sole[i][0] * multiplier,
sole[i][1] * multiplier,
sole[i][2] * multiplier );
glVertex3f( sole[i+1][0] * multiplier,
sole[i+1][1] * multiplier,
sole[i+1][2] * multiplier );
}
last = heelCount - 1;
for ( i = 0; i < last; ++i ) {
glVertex3f( heel[i][0] * multiplier,
heel[i][1] * multiplier,
heel[i][2] * multiplier );
glVertex3f( heel[i+1][0] * multiplier,
heel[i+1][1] * multiplier,
heel[i+1][2] * multiplier );
}
glEnd();
view.endGL();
view.setDrawColor( MColor( 0.1f, 0.8f, 0.8f, 1.0f ) );
view.drawText( MString("Footprint"), MPoint( 0.0, 0.0, 0.0 ), M3dView::kCenter );
}
bool footPrint::isBounded() const
{
return true;
}
MBoundingBox footPrint::boundingBox() const
{
MObject thisNode = thisMObject();
MPlug plug( thisNode, size );
MDistance sizeVal;
plug.getValue( sizeVal );
double multiplier = sizeVal.asCentimeters();
MPoint corner1( -0.17, 0.0, -0.7 );
MPoint corner2( 0.17, 0.0, 0.3 );
corner1 = corner1 * multiplier;
corner2 = corner2 * multiplier;
return MBoundingBox( corner1, corner2 );
}
void* footPrint::creator()
{
return new footPrint();
}
class FootPrintData : public MUserData
{
public:
FootPrintData() : MUserData(false) {}
virtual ~FootPrintData() {}
float fMultiplier;
float fColor[3];
bool fCustomBoxDraw;
MBoundingBox fCurrentBoundingBox;
MDAGDrawOverrideInfo fDrawOV;
};
class FootPrintDrawAgent
{
public:
FootPrintDrawAgent(){}
virtual ~FootPrintDrawAgent(){}
virtual void drawShaded( float multiplier ) = 0;
virtual void drawBoundingBox( const MPoint&, const MPoint&) = 0;
virtual void drawWireframe( float multiplier ) = 0;
virtual void beginDraw() = 0;
virtual void endDraw() = 0;
void setMatrix( const MMatrix& wvMatrix, const MMatrix& projMatrix ){
mWorldViewMatrix = wvMatrix;
mProjectionMatrix = projMatrix;
}
void setColor( const MColor& color){
mColor = color;
}
protected:
MMatrix mWorldViewMatrix;
MMatrix mProjectionMatrix;
MColor mColor;
};
class FootPrintDrawAgentGL : public FootPrintDrawAgent
{
public:
static FootPrintDrawAgentGL& getDrawAgent(){
static FootPrintDrawAgentGL obj;
return obj;
}
virtual void drawShaded( float multiplier );
virtual void drawBoundingBox( const MPoint& min, const MPoint& max );
virtual void drawWireframe( float multiplier );
virtual void beginDraw();
virtual void endDraw();
private:
FootPrintDrawAgentGL(){}
~FootPrintDrawAgentGL(){}
FootPrintDrawAgentGL( const FootPrintDrawAgentGL& v ){}
FootPrintDrawAgentGL operator = (const FootPrintDrawAgentGL& v){ return *this; }
};
#ifdef _WIN32
class FootPrintDrawAgentDX : public FootPrintDrawAgent
{
public:
static FootPrintDrawAgentDX& getDrawAgent(){
static FootPrintDrawAgentDX obj;
return obj;
}
virtual void drawShaded( float multiplier );
virtual void drawBoundingBox( const MPoint& min, const MPoint& max );
virtual void drawWireframe( float multiplier );
virtual void beginDraw();
virtual void endDraw();
bool releaseDXResources();
private:
ID3D11Device* mDevicePtr;
ID3D11DeviceContext* mDeviceContextPtr;
ID3D11Buffer* mBoundingboxVertexBufferPtr;
ID3D11Buffer* mBoundingboxIndexBufferPtr;
ID3D11Buffer* mSoleVertexBufferPtr;
ID3D11Buffer* mHeelVertexBufferPtr;
ID3D11Buffer* mSoleWireIndexBufferPtr;
ID3D11Buffer* mSoleShadedIndexBufferPtr;
ID3D11Buffer* mHeelWireIndexBufferPtr;
ID3D11Buffer* mHeelShadedIndexBufferPtr;
ID3D11Buffer* mConstantBufferPtr;
ID3D11VertexShader* mVertexShaderPtr;
ID3D11PixelShader* mPixelShaderPtr;
ID3D11InputLayout* mVertexLayoutPtr;
unsigned int mStride;
unsigned int mOffset;
struct ConstantBufferDef
{
XMMATRIX fWVP;
XMFLOAT4 fMatColor;
};
bool initShadersDX();
bool initBuffersDX();
void setupConstantBuffer( const XMMATRIX& scale );
private:
FootPrintDrawAgentDX():
mDevicePtr(NULL), mDeviceContextPtr(NULL), mStride(sizeof(float)*3), mOffset(0),
mBoundingboxVertexBufferPtr(NULL),
mBoundingboxIndexBufferPtr(NULL),
mSoleVertexBufferPtr(NULL),
mHeelVertexBufferPtr(NULL),
mSoleWireIndexBufferPtr(NULL),
mSoleShadedIndexBufferPtr(NULL),
mHeelWireIndexBufferPtr(NULL),
mHeelShadedIndexBufferPtr(NULL),
mConstantBufferPtr(NULL),
mVertexShaderPtr(NULL),
mPixelShaderPtr(NULL),
mVertexLayoutPtr(NULL)
{}
~FootPrintDrawAgentDX(){}
FootPrintDrawAgentDX( const FootPrintDrawAgentDX& v ){}
FootPrintDrawAgentDX operator = (const FootPrintDrawAgentDX& v){ return *this; }
};
#endif // _WIN32
void FootPrintDrawAgentGL::beginDraw()
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixd(mWorldViewMatrix.matrix[0]);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadMatrixd(mProjectionMatrix.matrix[0]);
glPushAttrib( GL_CURRENT_BIT );
}
void FootPrintDrawAgentGL::endDraw()
{
glPopAttrib();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
void FootPrintDrawAgentGL::drawShaded( float multiplier )
{
glColor4fv( &(mColor.r) );
glBegin( GL_TRIANGLE_FAN );
int i;
int last = soleCount - 1;
for ( i = 0; i < last; ++i ) {
glVertex3f( sole[i][0] * multiplier,
sole[i][1] * multiplier,
sole[i][2] * multiplier );
}
glEnd();
glBegin( GL_TRIANGLE_FAN );
last = heelCount - 1;
for ( i = 0; i < last; ++i ) {
glVertex3f( heel[i][0] * multiplier,
heel[i][1] * multiplier,
heel[i][2] * multiplier );
}
glEnd();
}
void FootPrintDrawAgentGL::drawBoundingBox( const MPoint& min, const MPoint& max )
{
glColor4fv( &(mColor.r) );
float bottomLeftFront[3] = { (float)min[0], (float)min[1], (float)min[2] };
float topLeftFront[3] = { (float)min[0], (float)max[1], (float)min[2] };
float bottomRightFront[3] = { (float)max[0], (float)min[1], (float)min[2] };
float topRightFront[3] = { (float)max[0], (float)max[1], (float)min[2] };
float bottomLeftBack[3] = { (float)min[0], (float)min[1], (float)max[2] };
float topLeftBack[3] = { (float)min[0], (float)max[1], (float)max[2] };
float bottomRightBack[3] = { (float)max[0], (float)min[1], (float)max[2] };
float topRightBack[3] = { (float)max[0], (float)max[1], (float)max[2] };
glBegin( GL_LINES );
glVertex3fv( bottomLeftFront );
glVertex3fv( bottomRightFront );
glVertex3fv( bottomRightFront );
glVertex3fv( bottomRightBack );
glVertex3fv( bottomRightBack );
glVertex3fv( bottomLeftBack );
glVertex3fv( bottomLeftBack );
glVertex3fv( bottomLeftFront );
glVertex3fv( topLeftFront );
glVertex3fv( topRightFront );
glVertex3fv( topRightFront );
glVertex3fv( topRightBack );
glVertex3fv( topRightBack );
glVertex3fv( topLeftBack );
glVertex3fv( topLeftBack );
glVertex3fv( topLeftFront );
glVertex3fv( bottomLeftFront );
glVertex3fv( topLeftFront );
glVertex3fv( bottomRightFront );
glVertex3fv( topRightFront );
glVertex3fv( bottomRightBack );
glVertex3fv( topRightBack );
glVertex3fv( bottomLeftBack );
glVertex3fv( topLeftBack );
glEnd();
}
void FootPrintDrawAgentGL::drawWireframe( float multiplier )
{
glColor4fv( &(mColor.r) );
glBegin( GL_LINES );
int i;
int last = soleCount - 1;
for ( i = 0; i < last; ++i ) {
glVertex3f( sole[i][0] * multiplier,
sole[i][1] * multiplier,
sole[i][2] * multiplier );
glVertex3f( sole[i+1][0] * multiplier,
sole[i+1][1] * multiplier,
sole[i+1][2] * multiplier );
}
last = heelCount - 1;
for ( i = 0; i < last; ++i ) {
glVertex3f( heel[i][0] * multiplier,
heel[i][1] * multiplier,
heel[i][2] * multiplier );
glVertex3f( heel[i+1][0] * multiplier,
heel[i+1][1] * multiplier,
heel[i+1][2] * multiplier );
}
glEnd();
}
#ifdef _WIN32
void FootPrintDrawAgentDX::beginDraw()
{
if( !mDevicePtr || !mDeviceContextPtr ){
MHWRender::MRenderer* theRenderer = MHWRender::MRenderer::theRenderer();
if ( theRenderer ){
mDevicePtr = (ID3D11Device*)theRenderer->GPUDeviceHandle();
if ( mDevicePtr ){
mDevicePtr->GetImmediateContext( &mDeviceContextPtr );
}
}
}
assert( mDevicePtr );
assert( mDeviceContextPtr );
if ( mDevicePtr && mDeviceContextPtr ){
if ( initShadersDX() ){
mDeviceContextPtr->VSSetShader(mVertexShaderPtr, NULL, 0);
mDeviceContextPtr->IASetInputLayout(mVertexLayoutPtr);
mDeviceContextPtr->PSSetShader(mPixelShaderPtr, NULL, 0);
}
initBuffersDX();
}
}
void FootPrintDrawAgentDX::endDraw()
{}
void FootPrintDrawAgentDX::setupConstantBuffer( const XMMATRIX& scale )
{
assert( mDeviceContextPtr );
if ( !mDeviceContextPtr )
return;
XMMATRIX dxTransform = XMMATRIX(
(float)mWorldViewMatrix.matrix[0][0], (float)mWorldViewMatrix.matrix[0][1], (float)mWorldViewMatrix.matrix[0][2], (float)mWorldViewMatrix.matrix[0][3],
(float)mWorldViewMatrix.matrix[1][0], (float)mWorldViewMatrix.matrix[1][1], (float)mWorldViewMatrix.matrix[1][2], (float)mWorldViewMatrix.matrix[1][3],
(float)mWorldViewMatrix.matrix[2][0], (float)mWorldViewMatrix.matrix[2][1], (float)mWorldViewMatrix.matrix[2][2], (float)mWorldViewMatrix.matrix[2][3],
(float)mWorldViewMatrix.matrix[3][0], (float)mWorldViewMatrix.matrix[3][1], (float)mWorldViewMatrix.matrix[3][2], (float)mWorldViewMatrix.matrix[3][3]);
XMMATRIX dxProjection = XMMATRIX(
(float)mProjectionMatrix.matrix[0][0], (float)mProjectionMatrix.matrix[0][1], (float)mProjectionMatrix.matrix[0][2], (float)mProjectionMatrix.matrix[0][3],
(float)mProjectionMatrix.matrix[1][0], (float)mProjectionMatrix.matrix[1][1], (float)mProjectionMatrix.matrix[1][2], (float)mProjectionMatrix.matrix[1][3],
(float)mProjectionMatrix.matrix[2][0], (float)mProjectionMatrix.matrix[2][1], (float)mProjectionMatrix.matrix[2][2], (float)mProjectionMatrix.matrix[2][3],
(float)mProjectionMatrix.matrix[3][0], (float)mProjectionMatrix.matrix[3][1], (float)mProjectionMatrix.matrix[3][2], (float)mProjectionMatrix.matrix[3][3]);
ConstantBufferDef cb;
cb.fWVP = XMMatrixTranspose(scale * dxTransform * dxProjection);
cb.fMatColor = XMFLOAT4( mColor.r, mColor.g, mColor.b, mColor.a);
mDeviceContextPtr->UpdateSubresource(mConstantBufferPtr, 0, NULL, &cb, 0, 0);
mDeviceContextPtr->VSSetConstantBuffers(0, 1, &mConstantBufferPtr);
mDeviceContextPtr->PSSetConstantBuffers(0, 1, &mConstantBufferPtr);
}
void FootPrintDrawAgentDX::drawShaded( float multiplier )
{
assert( mDeviceContextPtr );
if ( !mDeviceContextPtr )
return;
XMMATRIX scale(
multiplier, 0.0f, 0.0f, 0.0f,
0.0f, multiplier, 0.0f, 0.0f,
0.0f, 0.0f, multiplier, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
setupConstantBuffer( scale );
mDeviceContextPtr->IASetVertexBuffers(0, 1, &mSoleVertexBufferPtr, &mStride, &mOffset);
mDeviceContextPtr->IASetIndexBuffer(mSoleShadedIndexBufferPtr, DXGI_FORMAT_R16_UINT, 0);
mDeviceContextPtr->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
mDeviceContextPtr->DrawIndexed(3 * (soleCount-2), 0, 0);
mDeviceContextPtr->IASetVertexBuffers(0, 1, &mHeelVertexBufferPtr, &mStride, &mOffset);
mDeviceContextPtr->IASetIndexBuffer(mHeelShadedIndexBufferPtr, DXGI_FORMAT_R16_UINT, 0);
mDeviceContextPtr->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
mDeviceContextPtr->DrawIndexed(3 * (heelCount-2), 0, 0);
}
void FootPrintDrawAgentDX::drawBoundingBox( const MPoint& min, const MPoint& max )
{
assert( mDeviceContextPtr );
if ( !mDeviceContextPtr )
return;
XMMATRIX scale(
static_cast<float>(max[0]- min[0]), 0.0f, 0.0f, 0.0f,
0.0f, static_cast<float>(max[1]-min[1]), 0.0f, 0.0f,
0.0f, 0.0f, static_cast<float>(max[2]-min[2]), 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
setupConstantBuffer( scale );
mDeviceContextPtr->IASetVertexBuffers(0, 1, &mBoundingboxVertexBufferPtr, &mStride, &mOffset);
mDeviceContextPtr->IASetIndexBuffer(mBoundingboxIndexBufferPtr, DXGI_FORMAT_R16_UINT, 0);
mDeviceContextPtr->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
mDeviceContextPtr->DrawIndexed(2 * 12, 0, 0);
}
void FootPrintDrawAgentDX::drawWireframe( float multiplier )
{
assert( mDeviceContextPtr );
if ( !mDeviceContextPtr )
return;
XMMATRIX scale(
multiplier, 0.0f, 0.0f, 0.0f,
0.0f, multiplier, 0.0f, 0.0f,
0.0f, 0.0f, multiplier, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
setupConstantBuffer( scale );
mDeviceContextPtr->IASetVertexBuffers(0, 1, &mSoleVertexBufferPtr, &mStride, &mOffset);
mDeviceContextPtr->IASetIndexBuffer(mSoleWireIndexBufferPtr, DXGI_FORMAT_R16_UINT, 0);
mDeviceContextPtr->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
mDeviceContextPtr->DrawIndexed(2 * (soleCount-1), 0, 0);
mDeviceContextPtr->IASetVertexBuffers(0, 1, &mHeelVertexBufferPtr, &mStride, &mOffset);
mDeviceContextPtr->IASetIndexBuffer(mHeelWireIndexBufferPtr, DXGI_FORMAT_R16_UINT, 0);
mDeviceContextPtr->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
mDeviceContextPtr->DrawIndexed(2 * (heelCount-1), 0, 0);
}
#endif // _WIN32
class FootPrintDrawOverride : public MHWRender::MPxDrawOverride
{
public:
static MHWRender::MPxDrawOverride* Creator(const MObject& obj)
{
return new FootPrintDrawOverride(obj);
}
virtual ~FootPrintDrawOverride();
virtual MHWRender::DrawAPI supportedDrawAPIs() const;
virtual bool isBounded(
const MDagPath& objPath,
const MDagPath& cameraPath) const;
virtual MBoundingBox boundingBox(
const MDagPath& objPath,
const MDagPath& cameraPath) const;
virtual bool disableInternalBoundingBoxDraw() const;
virtual MUserData* prepareForDraw(
const MDagPath& objPath,
const MDagPath& cameraPath,
const MHWRender::MFrameContext& frameContext,
MUserData* oldData);
virtual bool hasUIDrawables() const { return true; }
virtual void addUIDrawables(
const MDagPath& objPath,
MHWRender::MUIDrawManager& drawManager,
const MHWRender::MFrameContext& frameContext,
const MUserData* data);
static void draw(const MHWRender::MDrawContext& context, const MUserData* data);
protected:
MBoundingBox mCurrentBoundingBox;
bool mCustomBoxDraw;
private:
FootPrintDrawOverride(const MObject& obj);
float getMultiplier(const MDagPath& objPath) const;
};
FootPrintDrawOverride::FootPrintDrawOverride(const MObject& obj)
: MHWRender::MPxDrawOverride(obj, FootPrintDrawOverride::draw)
, mCustomBoxDraw(true)
{
}
FootPrintDrawOverride::~FootPrintDrawOverride()
{
}
MHWRender::DrawAPI FootPrintDrawOverride::supportedDrawAPIs() const
{
return (MHWRender::kOpenGL | MHWRender::kDirectX11);
}
float FootPrintDrawOverride::getMultiplier(const MDagPath& objPath) const
{
MStatus status;
MObject footprintNode = objPath.node(&status);
if (status)
{
MPlug plug(footprintNode, footPrint::size);
if (!plug.isNull())
{
MDistance sizeVal;
if (plug.getValue(sizeVal))
{
return (float)sizeVal.asCentimeters();
}
}
}
return 1.0f;
}
bool FootPrintDrawOverride::isBounded(const MDagPath& ,
const MDagPath& ) const
{
return true;
}
MBoundingBox FootPrintDrawOverride::boundingBox(
const MDagPath& objPath,
const MDagPath& cameraPath) const
{
MPoint corner1( -0.17, 0.0, -0.7 );
MPoint corner2( 0.17, 0.0, 0.3 );
float multiplier = getMultiplier(objPath);
corner1 = corner1 * multiplier;
corner2 = corner2 * multiplier;
FootPrintDrawOverride *nonConstThis = (FootPrintDrawOverride *)this;
nonConstThis->mCurrentBoundingBox.clear();
nonConstThis->mCurrentBoundingBox.expand( corner1 );
nonConstThis->mCurrentBoundingBox.expand( corner2 );
return mCurrentBoundingBox;
}
bool FootPrintDrawOverride::disableInternalBoundingBoxDraw() const
{
return mCustomBoxDraw;
}
MUserData* FootPrintDrawOverride::prepareForDraw(
const MDagPath& objPath,
const MDagPath& cameraPath,
const MHWRender::MFrameContext& frameContext,
MUserData* oldData)
{
FootPrintData* data = dynamic_cast<FootPrintData*>(oldData);
if (!data)
{
data = new FootPrintData();
}
data->fMultiplier = getMultiplier(objPath);
MColor color = MHWRender::MGeometryUtilities::wireframeColor(objPath);
data->fColor[0] = color.r;
data->fColor[1] = color.g;
data->fColor[2] = color.b;
data->fCustomBoxDraw = mCustomBoxDraw;
data->fCurrentBoundingBox = mCurrentBoundingBox;
data->fDrawOV = objPath.getDrawOverrideInfo();
return data;
}
void FootPrintDrawOverride::addUIDrawables(
const MDagPath& objPath,
MHWRender::MUIDrawManager& drawManager,
const MHWRender::MFrameContext& frameContext,
const MUserData* data)
{
MPoint pos( 0.0, 0.0, 0.0 );
MColor textColor( 0.1f, 0.8f, 0.8f, 1.0f );
drawManager.beginDrawable();
drawManager.setColor( textColor );
drawManager.setFontSize( MHWRender::MUIDrawManager::kSmallFontSize );
drawManager.text( pos, MString("Footprint"), MHWRender::MUIDrawManager::kCenter );
drawManager.endDrawable();
}
void FootPrintDrawOverride::draw(const MHWRender::MDrawContext& context, const MUserData* data)
{
const FootPrintData* footData = dynamic_cast<const FootPrintData*>(data);
if (!footData)
return;
const MDAGDrawOverrideInfo& objectOverrideInfo = footData->fDrawOV;
if ( objectOverrideInfo.fOverrideEnabled && !objectOverrideInfo.fEnableVisible )
return;
const unsigned int displayStyle = context.getDisplayStyle();
const bool drawAsBoundingbox =
(displayStyle & MHWRender::MFrameContext::kBoundingBox) ||
(footData->fDrawOV.fLOD == MDAGDrawOverrideInfo::kLODBoundingBox);
if ( drawAsBoundingbox && !footData->fCustomBoxDraw )
{
return;
}
MHWRender::MRenderer* theRenderer = MHWRender::MRenderer::theRenderer();
if (!theRenderer)
return;
MStatus status;
const MMatrix transform =
context.getMatrix(MHWRender::MFrameContext::kWorldViewMtx, &status);
if (status != MStatus::kSuccess) return;
const MMatrix projection =
context.getMatrix(MHWRender::MFrameContext::kProjectionMtx, &status);
if (status != MStatus::kSuccess) return;
const MHWRender::MPassContext & passCtx = context.getPassContext();
const MStringArray & passSem = passCtx.passSemantics();
bool castingShadows = false;
for (unsigned int i=0; i<passSem.length(); i++)
{
if (passSem[i] == MHWRender::MPassContext::kShadowPassSemantic)
castingShadows = true;
}
bool debugPassInformation = false;
if (debugPassInformation)
{
const MString & passId = passCtx.passIdentifier();
printf("footprint node drawing in pass[%s], semantic[", passId.asChar());
for (unsigned int i=0; i<passSem.length(); i++)
printf(" %s", passSem[i].asChar());
printf("\n");
}
float multiplier = footData->fMultiplier;
float color[4] = {
footData->fColor[0],
footData->fColor[1],
footData->fColor[2],
1.0f
};
bool requireBlending = false;
if (!castingShadows)
{
if (displayStyle & MHWRender::MFrameContext::kDefaultMaterial)
{
color[0] = color[1] = color[2] = (color[0] + color[1] + color[2]) / 3.0f;
}
else if (displayStyle & MHWRender::MFrameContext::kXray)
{
requireBlending = true;
color[3] = 0.3f;
}
}
MHWRender::MStateManager* stateMgr = context.getStateManager();
const MHWRender::MBlendState* pOldBlendState = NULL;
const MHWRender::MRasterizerState* pOldRasterState = NULL;
bool rasterStateModified = false;
if(stateMgr && (displayStyle & MHWRender::MFrameContext::kGouraudShaded))
{
if (stateMgr && requireBlending)
{
static const MHWRender::MBlendState* blendState = NULL;
if (!blendState)
{
MHWRender::MBlendStateDesc desc;
desc.targetBlends[0].blendEnable = true;
desc.targetBlends[0].destinationBlend = MHWRender::MBlendState::kInvSourceAlpha;
desc.targetBlends[0].alphaDestinationBlend = MHWRender::MBlendState::kInvSourceAlpha;
blendState = stateMgr->acquireBlendState(desc);
}
if (blendState)
{
pOldBlendState = stateMgr->getBlendState();
stateMgr->setBlendState(blendState);
}
}
pOldRasterState = stateMgr ? stateMgr->getRasterizerState() : NULL;
if (pOldRasterState)
{
MHWRender::MRasterizerStateDesc desc( pOldRasterState->desc() );
MHWRender::MRasterizerState::CullMode cullMode = MHWRender::MRasterizerState::kCullNone;
if (desc.cullMode != cullMode)
{
static const MHWRender::MRasterizerState *rasterState = NULL;
if (!rasterState)
{
desc.cullMode = cullMode;
rasterState = stateMgr->acquireRasterizerState(desc);
}
if (rasterState)
{
rasterStateModified = true;
stateMgr->setRasterizerState(rasterState);
}
}
}
}
FootPrintDrawAgentGL& drawAgentRef = FootPrintDrawAgentGL::getDrawAgent();
FootPrintDrawAgent* drawAgentPtr = &drawAgentRef;
#ifdef _WIN32
if ( !theRenderer->drawAPIIsOpenGL() )
{
FootPrintDrawAgentDX& drawAgentRef = FootPrintDrawAgentDX::getDrawAgent();
drawAgentPtr = &drawAgentRef;
}
#endif
assert( drawAgentPtr );
if ( drawAgentPtr ){
drawAgentPtr->setColor( MColor(color[0],color[1],color[2],color[3]) );
drawAgentPtr->setMatrix( transform, projection );
drawAgentPtr->beginDraw();
if ( drawAsBoundingbox )
{
MPoint min = footData->fCurrentBoundingBox.min();
MPoint max = footData->fCurrentBoundingBox.max();
drawAgentPtr->drawBoundingBox( min, max );
} else {
const bool overideTemplated = objectOverrideInfo.fOverrideEnabled &&
(objectOverrideInfo.fDisplayType == MDAGDrawOverrideInfo::kDisplayTypeTemplate);
const bool overrideNoShaded = objectOverrideInfo.fOverrideEnabled && !objectOverrideInfo.fEnableShading;
if ( overideTemplated || overrideNoShaded ){
drawAgentPtr->drawWireframe( multiplier );
} else {
if( (displayStyle & MHWRender::MFrameContext::kGouraudShaded) ||
(displayStyle & MHWRender::MFrameContext::kTextured))
{
drawAgentPtr->drawShaded( multiplier );
}
if(displayStyle & MHWRender::MFrameContext::kWireFrame)
{
drawAgentPtr->drawWireframe( multiplier );
}
}
}
drawAgentPtr->endDraw();
}
if(stateMgr && (displayStyle & MHWRender::MFrameContext::kGouraudShaded))
{
if (stateMgr && pOldBlendState)
{
stateMgr->setBlendState(pOldBlendState);
}
if (rasterStateModified && pOldRasterState)
{
stateMgr->setRasterizerState(pOldRasterState);
}
}
}
#ifdef _WIN32
bool FootPrintDrawAgentDX::initShadersDX()
{
assert( mDevicePtr );
if ( !mDevicePtr )
return false;
HRESULT hr;
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
ID3DBlob* vsBlob = NULL;
ID3DBlob* psBlob = NULL;
ID3DBlob* pErrorBlob;
MString effectLocation(
MString(getenv("MAYA_LOCATION")) +
MString("\\devkit\\plug-ins") +
MString("\\footprint.hlsl"));
if (!mVertexShaderPtr)
{
hr = D3DX11CompileFromFile(
effectLocation.asChar(),
NULL,
NULL,
"mainVS",
"vs_5_0",
dwShaderFlags,
0,
NULL,
&vsBlob,
&pErrorBlob,
NULL);
if (FAILED(hr))
{
printf("Failed to compile vertex shader\n");
if (pErrorBlob) pErrorBlob->Release();
return false;
}
if (pErrorBlob) pErrorBlob->Release();
hr = mDevicePtr->CreateVertexShader(
vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), NULL, &mVertexShaderPtr);
if (FAILED(hr))
{
printf("Failed to create vertex shader\n");
vsBlob->Release();
return false;
}
}
if (!mVertexLayoutPtr)
{
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
int numLayoutElements = sizeof layout/sizeof layout[0];
hr = mDevicePtr->CreateInputLayout(
layout, numLayoutElements, vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), &mVertexLayoutPtr);
vsBlob->Release();
if (FAILED(hr))
{
printf("Failed to create input layout\n");
return false;
}
}
if (!mPixelShaderPtr)
{
hr = D3DX11CompileFromFile(
effectLocation.asChar(),
NULL,
NULL,
"mainPS",
"ps_5_0",
dwShaderFlags,
0,
NULL,
&psBlob,
&pErrorBlob,
NULL);
if (FAILED(hr))
{
printf("Failed to compile vertex shader\n");
mVertexShaderPtr->Release();
mVertexLayoutPtr->Release();
if (pErrorBlob) pErrorBlob->Release();
return false;
}
if (pErrorBlob) pErrorBlob->Release();
hr = mDevicePtr->CreatePixelShader(
psBlob->GetBufferPointer(), psBlob->GetBufferSize(), NULL, &mPixelShaderPtr);
psBlob->Release();
if (FAILED(hr))
{
printf("Failed to create pixel shader\n");
mVertexShaderPtr->Release();
mVertexLayoutPtr->Release();
return false;
}
}
return true;
}
bool FootPrintDrawAgentDX::initBuffersDX()
{
assert( mDevicePtr );
if ( !mDevicePtr )
return false;
HRESULT hr;
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
D3D11_SUBRESOURCE_DATA InitData;
ZeroMemory(&InitData, sizeof(InitData));
if (!mBoundingboxVertexBufferPtr)
{
float bbData[][3] = {
{ -0.5, -0.5f, -0.5f},
{ 0.5, -0.5f, -0.5f},
{ 0.5, -0.5f, 0.5f},
{ -0.5, -0.5f, 0.5f},
{ -0.5, 0.5f, -0.5f},
{ 0.5, 0.5f, -0.5f},
{ 0.5, 0.5f, 0.5f},
{ -0.5, 0.5f, 0.5f}};
bd.Usage = D3D11_USAGE_IMMUTABLE;
bd.ByteWidth = sizeof(float) * 3 * 8;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
InitData.pSysMem = bbData;
hr = mDevicePtr->CreateBuffer(&bd, &InitData, &mBoundingboxVertexBufferPtr);
if (FAILED(hr)) return false;
}
if( !mBoundingboxIndexBufferPtr ){
unsigned short bbWireIndices[] =
{
0,1,
1,2,
2,3,
3,0,
4,5,
5,6,
6,7,
7,4,
0,4,
1,5,
2,6,
3,7
};
bd.Usage = D3D11_USAGE_IMMUTABLE;
bd.ByteWidth = sizeof(unsigned short) * 2 * 12;
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = 0;
InitData.pSysMem = bbWireIndices;
hr = mDevicePtr->CreateBuffer(&bd, &InitData, &mBoundingboxIndexBufferPtr);
if (FAILED(hr)) return false;
}
if (!mSoleVertexBufferPtr)
{
bd.Usage = D3D11_USAGE_IMMUTABLE;
bd.ByteWidth = sizeof(float) * 3 * soleCount;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
InitData.pSysMem = sole;
hr = mDevicePtr->CreateBuffer(&bd, &InitData, &mSoleVertexBufferPtr);
if (FAILED(hr)) return false;
}
if (!mHeelVertexBufferPtr)
{
bd.Usage = D3D11_USAGE_IMMUTABLE;
bd.ByteWidth = sizeof(float) * 3 * heelCount;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
InitData.pSysMem = heel;
hr = mDevicePtr->CreateBuffer(&bd, &InitData, &mHeelVertexBufferPtr);
if (FAILED(hr)) return false;
}
if (!mSoleWireIndexBufferPtr)
{
unsigned short soleWireIndices[] =
{
0, 1,
1, 2,
2, 3,
3, 4,
4, 5,
5, 6,
6, 7,
7, 8,
8, 9,
9, 10,
10, 11,
11, 12,
12, 13,
13, 14,
14, 15,
15, 16,
16, 17,
17, 18,
18, 19,
19, 20
};
bd.Usage = D3D11_USAGE_IMMUTABLE;
bd.ByteWidth = sizeof(unsigned short) * 2 * (soleCount-1);
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = 0;
InitData.pSysMem = soleWireIndices;
hr = mDevicePtr->CreateBuffer(&bd, &InitData, &mSoleWireIndexBufferPtr);
if (FAILED(hr)) return false;
}
if (!mHeelWireIndexBufferPtr)
{
unsigned short heelWireIndices[] =
{
0, 1,
1, 2,
2, 3,
3, 4,
4, 5,
5, 6,
6, 7,
7, 8,
8, 9,
9, 10,
10, 11,
11, 12,
12, 13,
13, 14,
14, 15,
15, 16
};
bd.Usage = D3D11_USAGE_IMMUTABLE;
bd.ByteWidth = sizeof(unsigned short) * 2 * (heelCount-1);
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = 0;
InitData.pSysMem = heelWireIndices;
hr = mDevicePtr->CreateBuffer(&bd, &InitData, &mHeelWireIndexBufferPtr);
if (FAILED(hr)) return false;
}
if (!mSoleShadedIndexBufferPtr)
{
unsigned short soleShadedIndices[] =
{
0, 1, 2,
0, 2, 3,
0, 3, 4,
0, 4, 5,
0, 5, 6,
0, 6, 7,
0, 7, 8,
0, 8, 9,
0, 9, 10,
0, 10, 11,
0, 11, 12,
0, 12, 13,
0, 13, 14,
0, 14, 15,
0, 15, 16,
0, 16, 17,
0, 17, 18,
0, 18, 19,
0, 19, 20
};
bd.Usage = D3D11_USAGE_IMMUTABLE;
bd.ByteWidth = sizeof(unsigned short) * 3 * (soleCount-2);
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = 0;
InitData.pSysMem = soleShadedIndices;
hr = mDevicePtr->CreateBuffer(&bd, &InitData, &mSoleShadedIndexBufferPtr);
if (FAILED(hr)) return false;
}
if (!mHeelShadedIndexBufferPtr)
{
unsigned short heelShadedIndices[] =
{
0, 1, 2,
0, 2, 3,
0, 3, 4,
0, 4, 5,
0, 5, 6,
0, 6, 7,
0, 7, 8,
0, 8, 9,
0, 9, 10,
0, 10, 11,
0, 11, 12,
0, 12, 13,
0, 13, 14,
0, 14, 15,
0, 15, 16
};
bd.Usage = D3D11_USAGE_IMMUTABLE;
bd.ByteWidth = sizeof(unsigned short) * 3 * (heelCount-2);
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = 0;
InitData.pSysMem = heelShadedIndices;
hr = mDevicePtr->CreateBuffer(&bd, &InitData, &mHeelShadedIndexBufferPtr);
if (FAILED(hr)) return false;
}
if (!mConstantBufferPtr)
{
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(ConstantBufferDef);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = 0;
hr = mDevicePtr->CreateBuffer(&bd, NULL, &mConstantBufferPtr);
if (FAILED(hr)) return false;
}
return true;
}
bool FootPrintDrawAgentDX::releaseDXResources()
{
if (mBoundingboxVertexBufferPtr)
{
mBoundingboxVertexBufferPtr->Release();
mBoundingboxVertexBufferPtr = NULL;
}
if (mBoundingboxIndexBufferPtr)
{
mBoundingboxIndexBufferPtr->Release();
mBoundingboxIndexBufferPtr = NULL;
}
if (mSoleVertexBufferPtr)
{
mSoleVertexBufferPtr->Release();
mSoleVertexBufferPtr = NULL;
}
if (mHeelVertexBufferPtr)
{
mHeelVertexBufferPtr->Release();
mHeelVertexBufferPtr = NULL;
}
if (mSoleWireIndexBufferPtr)
{
mSoleWireIndexBufferPtr->Release();
mSoleWireIndexBufferPtr = NULL;
}
if (mSoleShadedIndexBufferPtr)
{
mSoleShadedIndexBufferPtr->Release();
mSoleShadedIndexBufferPtr = NULL;
}
if (mHeelWireIndexBufferPtr)
{
mHeelWireIndexBufferPtr->Release();
mHeelWireIndexBufferPtr = NULL;
}
if (mHeelShadedIndexBufferPtr)
{
mHeelShadedIndexBufferPtr->Release();
mHeelShadedIndexBufferPtr = NULL;
}
if (mVertexShaderPtr)
{
mVertexShaderPtr->Release();
mVertexShaderPtr = NULL;
}
if (mPixelShaderPtr)
{
mPixelShaderPtr->Release();
mPixelShaderPtr = NULL;
}
if (mVertexLayoutPtr)
{
mVertexLayoutPtr->Release();
mVertexLayoutPtr = NULL;
}
if (mConstantBufferPtr)
{
mConstantBufferPtr->Release();
mConstantBufferPtr = NULL;
}
return true;
}
#endif // _WIN32
MStatus footPrint::initialize()
{
MFnUnitAttribute unitFn;
MStatus stat;
size = unitFn.create( "size", "sz", MFnUnitAttribute::kDistance );
unitFn.setDefault( 1.0 );
stat = addAttribute( size );
if (!stat) {
stat.perror("addAttribute");
return stat;
}
return MS::kSuccess;
}
MStatus initializePlugin( MObject obj )
{
MStatus status;
MFnPlugin plugin( obj, PLUGIN_COMPANY, "3.0", "Any");
status = plugin.registerNode(
"footPrint",
footPrint::id,
&footPrint::creator,
&footPrint::initialize,
MPxNode::kLocatorNode,
&footPrint::drawDbClassification);
if (!status) {
status.perror("registerNode");
return status;
}
status = MHWRender::MDrawRegistry::registerDrawOverrideCreator(
footPrint::drawDbClassification,
footPrint::drawRegistrantId,
FootPrintDrawOverride::Creator);
if (!status) {
status.perror("registerDrawOverrideCreator");
return status;
}
return status;
}
MStatus uninitializePlugin( MObject obj)
{
MStatus status;
MFnPlugin plugin( obj );
status = MHWRender::MDrawRegistry::deregisterDrawOverrideCreator(
footPrint::drawDbClassification,
footPrint::drawRegistrantId);
if (!status) {
status.perror("deregisterDrawOverrideCreator");
return status;
}
status = plugin.deregisterNode( footPrint::id );
if (!status) {
status.perror("deregisterNode");
return status;
}
#ifdef _WIN32
FootPrintDrawAgentDX& drawAgentRef = FootPrintDrawAgentDX::getDrawAgent();
drawAgentRef.releaseDXResources();
#endif
return status;
}