footPrintNode/footPrintNode.cpp

footPrintNode/footPrintNode.cpp
//-
// ==========================================================================
// Copyright 2012 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.
// ==========================================================================
//+
#if _MSC_VER >= 1700
#pragma warning( disable: 4005 )
#endif
#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>
// Viewport 2.0 includes
#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 <maya/MRenderTargetManager.h>
#include <maya/MAnimControl.h>
#include <assert.h>
// DX stuff
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <d3d11.h>
#if _MSC_VER < 1700
#include <d3dx11.h>
#include <xnamath.h>
#else
#include <dxgi.h>
#include <DirectXMath.h>
using namespace DirectX;
#endif
#include <d3dcompiler.h>
#ifndef D3DCOMPILE_ENABLE_STRICTNESS
#define D3DCOMPILE_ENABLE_STRICTNESS D3D10_SHADER_ENABLE_STRICTNESS
#define D3DCOMPILE_DEBUG D3D10_SHADER_DEBUG
#endif
#endif //_WIN32
// Foot Data
//
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;
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Node implementation with standard viewport draw
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
class footPrint : public MPxLocatorNode
{
public:
footPrint();
virtual ~footPrint();
virtual MStatus compute( const MPlug& plug, MDataBlock& data );
virtual void draw( M3dView & view, const MDagPath & path,
virtual bool isBounded() const;
virtual MBoundingBox boundingBox() const;
static void * creator();
static MStatus initialize();
static MObject size; // The size of the foot
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& /*plug*/, MDataBlock& /*data*/ )
{
}
void footPrint::draw( M3dView & view, const MDagPath & /*path*/,
{
// Get the size
//
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 ) )
{
// Push the color settings
//
glPushAttrib( GL_CURRENT_BIT );
if ( status == M3dView::kActive ) {
} else {
}
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();
}
// Draw the outline of the foot
//
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();
// Draw the name of the footPrint
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
{
// Get the size
//
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();
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Viewport 2.0 override implementation
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
class FootPrintData : public MUserData
{
public:
FootPrintData() : MUserData(false) {} // don't delete after draw
virtual ~FootPrintData() {}
float fMultiplier;
float fColor[3];
bool fCustomBoxDraw;
MBoundingBox fCurrentBoundingBox;
};
// Helper class declaration for the object drawing
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;
};
// GL draw agent declaration
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; }
};
// DX stuff
#ifdef _WIN32
// DX draw agent declaration
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
// GL draw agent definition
//
void FootPrintDrawAgentGL::beginDraw()
{
// set world view matrix
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixd(mWorldViewMatrix.matrix[0]);
// set projection matrix
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 )
{
// set color
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 )
{
// set color
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] }; //1
float bottomRightFront[3] = { (float)max[0], (float)min[1], (float)min[2] }; //2
float topRightFront[3] = { (float)max[0], (float)max[1], (float)min[2] }; //3
float bottomLeftBack[3] = { (float)min[0], (float)min[1], (float)max[2] }; //4
float topLeftBack[3] = { (float)min[0], (float)max[1], (float)max[2] }; //5
float bottomRightBack[3] = { (float)max[0], (float)min[1], (float)max[2] }; //6
float topRightBack[3] = { (float)max[0], (float)max[1], (float)max[2] }; //7
glBegin( GL_LINES );
// 4 Bottom lines
//
glVertex3fv( bottomLeftFront );
glVertex3fv( bottomRightFront );
glVertex3fv( bottomRightFront );
glVertex3fv( bottomRightBack );
glVertex3fv( bottomRightBack );
glVertex3fv( bottomLeftBack );
glVertex3fv( bottomLeftBack );
glVertex3fv( bottomLeftFront );
// 4 Top lines
//
glVertex3fv( topLeftFront );
glVertex3fv( topRightFront );
glVertex3fv( topRightFront );
glVertex3fv( topRightBack );
glVertex3fv( topRightBack );
glVertex3fv( topLeftBack );
glVertex3fv( topLeftBack );
glVertex3fv( topLeftFront );
// 4 Side lines
//
glVertex3fv( bottomLeftFront );
glVertex3fv( topLeftFront );
glVertex3fv( bottomRightFront );
glVertex3fv( topRightFront );
glVertex3fv( bottomRightBack );
glVertex3fv( topRightBack );
glVertex3fv( bottomLeftBack );
glVertex3fv( topLeftBack );
glEnd();
}
void FootPrintDrawAgentGL::drawWireframe( float multiplier )
{
// set color
glColor4fv( &(mColor.r) );
// draw wire
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();
}
// DX stuff
#ifdef _WIN32
// DX draw agent definition
//
void FootPrintDrawAgentDX::beginDraw()
{
// Initial device
if( !mDevicePtr || !mDeviceContextPtr ){
// get renderer
if ( theRenderer ){
mDevicePtr = (ID3D11Device*)theRenderer->GPUDeviceHandle();
if ( mDevicePtr ){
mDevicePtr->GetImmediateContext( &mDeviceContextPtr );
}
}
}
assert( mDevicePtr );
assert( mDeviceContextPtr );
if ( mDevicePtr && mDeviceContextPtr ){
// Init shaders
if ( initShadersDX() ){
// Set up shader
mDeviceContextPtr->VSSetShader(mVertexShaderPtr, NULL, 0);
mDeviceContextPtr->IASetInputLayout(mVertexLayoutPtr);
mDeviceContextPtr->PSSetShader(mPixelShaderPtr, NULL, 0);
}
// Init buffers
initBuffersDX();
}
}
void FootPrintDrawAgentDX::endDraw()
{}
void FootPrintDrawAgentDX::setupConstantBuffer( const XMMATRIX& scale )
{
assert( mDeviceContextPtr );
if ( !mDeviceContextPtr )
return;
// Compute matrix
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]);
// Set constant buffer
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;
// Set constant buffer
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 );
// Draw the sole
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);
// Draw the heel
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;
// Set constant buffer
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;
// Set constant buffer
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 );
// Draw the sole
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);
// Draw the heel
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,
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)
// We want to perform custom bounding box drawing
// so return true so that the internal rendering code
// will not draw it for us.
, mCustomBoxDraw(true)
{
}
FootPrintDrawOverride::~FootPrintDrawOverride()
{
}
MHWRender::DrawAPI FootPrintDrawOverride::supportedDrawAPIs() const
{
// this plugin supports both GL and DX
}
float FootPrintDrawOverride::getMultiplier(const MDagPath& objPath) const
{
// Retrieve value of the size attribute from the node
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& /*objPath*/,
const MDagPath& /*cameraPath*/) 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)
{
// Retrieve data cache (create if does not exist)
FootPrintData* data = dynamic_cast<FootPrintData*>(oldData);
if (!data)
{
data = new FootPrintData();
}
// compute data and cache it
data->fMultiplier = getMultiplier(objPath);
data->fColor[0] = color.r;
data->fColor[1] = color.g;
data->fColor[2] = color.b;
data->fCustomBoxDraw = mCustomBoxDraw;
data->fCurrentBoundingBox = mCurrentBoundingBox;
// Get the draw override information
data->fDrawOV = objPath.getDrawOverrideInfo();
return data;
}
void FootPrintDrawOverride::addUIDrawables(
const MDagPath& objPath,
const MHWRender::MFrameContext& frameContext,
const MUserData* data)
{
// Draw a text "Foot"
MPoint pos( 0.0, 0.0, 0.0 ); // Position of the text
MColor textColor( 0.1f, 0.8f, 0.8f, 1.0f ); // Text color
drawManager.beginDrawable();
drawManager.setColor( textColor );
drawManager.text( pos, MString("Footprint"), MHWRender::MUIDrawManager::kCenter );
drawManager.endDrawable();
}
void FootPrintDrawOverride::draw(const MHWRender::MDrawContext& context, const MUserData* data)
{
// Get user draw data
const FootPrintData* footData = dynamic_cast<const FootPrintData*>(data);
if (!footData)
return;
// Get DAG object draw override
const MDAGDrawOverrideInfo& objectOverrideInfo = footData->fDrawOV;
// Sample code to determine the rendering destination
bool debugDestination = false;
if (debugDestination)
{
MString destinationIdentifier;
MString destinationType = " 3d viewport";
destinationType = " 2d viewport";
destinationType = "n image";
printf("footprint node render destination is a%s. Destination name=%s\n", destinationType.asChar(), destinationIdentifier.asChar());
}
// Just return and draw nothing, if it is overridden invisible
if ( objectOverrideInfo.fOverrideEnabled && !objectOverrideInfo.fEnableVisible )
return;
// Get display status
const unsigned int displayStyle = context.getDisplayStyle();
bool drawAsBoundingbox =
(footData->fDrawOV.fLOD == MDAGDrawOverrideInfo::kLODBoundingBox);
// If we don't want to draw the bounds within this plugin
// manually, then skip drawing altogether in bounding box mode
// since the bounds draw is handled by the renderer and
// doesn't need to be drawn here.
//
if ( drawAsBoundingbox && !footData->fCustomBoxDraw )
{
return;
}
bool animPlay = MAnimControl::isPlaying();
bool animScrub = MAnimControl::isScrubbing();
// If in playback but hidden in playback, skip drawing
if (!objectOverrideInfo.fPlaybackVisible &&
(animPlay || animScrub))
{
return;
}
// For any viewport interactions switch to bounding box mode,
// except when we are in playback.
if (context.inUserInteraction() || context.userChangingViewContext())
{
if (!animPlay && !animScrub)
drawAsBoundingbox = true;
}
// Now, something gonna draw...
// Get renderer
if (!theRenderer)
return;
// Get world view matrix
MStatus status;
const MMatrix transform =
if (status != MStatus::kSuccess) return;
// Get projection matrix
const MMatrix projection =
if (status != MStatus::kSuccess) return;
// Check to see if we are drawing in a shadow pass.
// If so then we keep the shading simple which in this
// example means to disable any extra blending state changes
//
const MHWRender::MPassContext & passCtx = context.getPassContext();
const MStringArray & passSem = passCtx.passSemantics();
bool castingShadows = false;
for (unsigned int i=0; i<passSem.length(); i++)
{
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");
}
// get cached data
float multiplier = footData->fMultiplier;
float color[4] = {
footData->fColor[0],
footData->fColor[1],
footData->fColor[2],
1.0f
};
bool requireBlending = false;
// If we're not casting shadows then do extra work
// for display styles
if (!castingShadows)
{
// Use some monotone version of color to show "default material mode"
//
{
color[0] = color[1] = color[2] = (color[0] + color[1] + color[2]) / 3.0f;
}
// Do some alpha blending if in x-ray mode
//
else if (displayStyle & MHWRender::MFrameContext::kXray)
{
requireBlending = true;
color[3] = 0.3f;
}
}
// Set blend and raster state
//
const MHWRender::MBlendState* pOldBlendState = NULL;
const MHWRender::MRasterizerState* pOldRasterState = NULL;
bool rasterStateModified = false;
if(stateMgr && (displayStyle & MHWRender::MFrameContext::kGouraudShaded))
{
// draw filled, and with blending if required
if (stateMgr && requireBlending)
{
static const MHWRender::MBlendState* blendState = NULL;
if (!blendState)
{
desc.targetBlends[0].blendEnable = true;
blendState = stateMgr->acquireBlendState(desc);
}
if (blendState)
{
pOldBlendState = stateMgr->getBlendState();
stateMgr->setBlendState(blendState);
}
}
// Override culling mode since we always want double-sided
//
pOldRasterState = stateMgr ? stateMgr->getRasterizerState() : NULL;
if (pOldRasterState)
{
MHWRender::MRasterizerStateDesc desc( pOldRasterState->desc() );
// It's also possible to change this to kCullFront or kCullBack if we
// wanted to set it to that.
if (desc.cullMode != cullMode)
{
static const MHWRender::MRasterizerState *rasterState = NULL;
if (!rasterState)
{
// Just override the cullmode
desc.cullMode = cullMode;
rasterState = stateMgr->acquireRasterizerState(desc);
}
if (rasterState)
{
rasterStateModified = true;
stateMgr->setRasterizerState(rasterState);
}
}
}
}
//========================
// Start the draw work
//========================
// Prepare draw agent, default using OpenGL
FootPrintDrawAgentGL& drawAgentRef = FootPrintDrawAgentGL::getDrawAgent();
FootPrintDrawAgent* drawAgentPtr = &drawAgentRef;
#ifdef _WIN32
// DX Draw
if ( !theRenderer->drawAPIIsOpenGL() )
{
FootPrintDrawAgentDX& drawAgentRef = FootPrintDrawAgentDX::getDrawAgent();
drawAgentPtr = &drawAgentRef;
}
#endif
assert( drawAgentPtr );
if ( drawAgentPtr ){
// Set color
drawAgentPtr->setColor( MColor(color[0],color[1],color[2],color[3]) );
// Set matrix
drawAgentPtr->setMatrix( transform, projection );
drawAgentPtr->beginDraw();
if ( drawAsBoundingbox )
{
// If it is in bounding bode, draw only bounding box wireframe, nothing else
MPoint min = footData->fCurrentBoundingBox.min();
MPoint max = footData->fCurrentBoundingBox.max();
drawAgentPtr->drawBoundingBox( min, max );
} else {
// Templated, only draw wirefame and it is not selectale
const bool overideTemplated = objectOverrideInfo.fOverrideEnabled &&
(objectOverrideInfo.fDisplayType == MDAGDrawOverrideInfo::kDisplayTypeTemplate);
// Override no shaded, only show wireframe
const bool overrideNoShaded = objectOverrideInfo.fOverrideEnabled && !objectOverrideInfo.fEnableShading;
if ( overideTemplated || overrideNoShaded ){
drawAgentPtr->drawWireframe( multiplier );
} else {
if( (displayStyle & MHWRender::MFrameContext::kGouraudShaded) ||
{
drawAgentPtr->drawShaded( multiplier );
}
{
drawAgentPtr->drawWireframe( multiplier );
}
}
}
drawAgentPtr->endDraw();
}
//========================
// End the draw work
//========================
// Restore old blend state and old raster state
if(stateMgr && (displayStyle & MHWRender::MFrameContext::kGouraudShaded))
{
if (stateMgr && pOldBlendState)
{
stateMgr->setBlendState(pOldBlendState);
}
if (rasterStateModified && pOldRasterState)
{
stateMgr->setRasterizerState(pOldRasterState);
}
}
}
// DX stuff
#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"));
// VS
if (!mVertexShaderPtr)
{
#if _MSC_VER < 1700
hr = D3DX11CompileFromFile(
effectLocation.asChar(),
NULL,
NULL,
"mainVS",
"vs_5_0",
dwShaderFlags,
0,
NULL,
&vsBlob,
&pErrorBlob,
NULL);
#else
hr = D3DCompileFromFile(
effectLocation.asWChar(),
NULL,
NULL,
"mainVS",
"vs_5_0",
dwShaderFlags,
0,
&vsBlob,
&pErrorBlob);
#endif
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;
}
}
// Layout
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;
}
}
// PS
if (!mPixelShaderPtr)
{
#if _MSC_VER < 1700
hr = D3DX11CompileFromFile(
effectLocation.asChar(),
NULL,
NULL,
"mainPS",
"ps_5_0",
dwShaderFlags,
0,
NULL,
&psBlob,
&pErrorBlob,
NULL);
#else
hr = D3DCompileFromFile(
effectLocation.asWChar(),
NULL,
NULL,
"mainPS",
"ps_5_0",
dwShaderFlags,
0,
&psBlob,
&pErrorBlob);
#endif
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)
{
// 8 Vertices for drawing the bounding box in DX mode
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
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Plugin Registration
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
MStatus footPrint::initialize()
{
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,
&footPrint::drawDbClassification);
if (!status) {
status.perror("registerNode");
return status;
}
footPrint::drawDbClassification,
footPrint::drawRegistrantId,
FootPrintDrawOverride::Creator);
if (!status) {
status.perror("registerDrawOverrideCreator");
return status;
}
return status;
}
MStatus uninitializePlugin( MObject obj)
{
MStatus status;
MFnPlugin plugin( obj );
footPrint::drawDbClassification,
footPrint::drawRegistrantId);
if (!status) {
status.perror("deregisterDrawOverrideCreator");
return status;
}
status = plugin.deregisterNode( footPrint::id );
if (!status) {
status.perror("deregisterNode");
return status;
}
// Release DX resource
#ifdef _WIN32
FootPrintDrawAgentDX& drawAgentRef = FootPrintDrawAgentDX::getDrawAgent();
drawAgentRef.releaseDXResources();
#endif
return status;
}