#include <maya/MPxLocatorNode.h>
#include <maya/MString.h>
#include <maya/MTypeId.h>
#include <maya/MPlug.h>
#include <maya/MPlugArray.h>
#include <maya/MVector.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MColor.h>
#include <maya/MFnPlugin.h>
#include <maya/MDistance.h>
#include <maya/MFnUnitAttribute.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MGlobal.h>
#include <maya/MEvaluationNode.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MDagMessage.h>
#include <maya/MDrawRegistry.h>
#include <maya/MPxGeometryOverride.h>
#include <maya/MUserData.h>
#include <maya/MDrawContext.h>
#include <maya/MShaderManager.h>
#include <maya/MHWGeometry.h>
#include <maya/MHWGeometryUtilities.h>
#include <maya/MPointArray.h>
#include <unordered_map>
namespace
{
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 } };
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 } };
int soleCount = 21;
int heelCount = 17;
const MString colorParameterName_ =
"solidColor";
const MString wireframeItemName_ =
"footPrintLocatorWires";
const MString shadedItemName_ =
"footPrintLocatorTriangles";
struct MColorHash
{
std::size_t operator()(
const MColor& color)
const
{
std::size_t seed = 0;
CombineHashCode(seed, color.
r);
CombineHashCode(seed, color.
g);
CombineHashCode(seed, color.
b);
CombineHashCode(seed, color.
a);
return seed;
}
void CombineHashCode(std::size_t& seed, float v) const
{
std::hash<float> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
};
std::unordered_map<MColor, MHWRender::MShaderInstance*, MColorHash> the3dSolidShaders;
{
auto it = the3dSolidShaders.find(color);
if (it != the3dSolidShaders.end())
{
return it->second;
}
if (renderer)
{
if (shaderMgr)
{
}
}
if (shader)
{
float solidColor[] = { color.
r, color.
g, color.
b, 1.0f };
the3dSolidShaders[color] = shader;
}
return shader;
}
{
if (renderer)
{
if (shaderMgr)
{
for (auto it = the3dSolidShaders.begin(); it != the3dSolidShaders.end(); it++)
{
}
the3dSolidShaders.clear();
return MS::kSuccess;
}
}
return MS::kFailure;
}
struct VP2InstanceDrawInfo
{
VP2InstanceDrawInfo() : mDisplayStatus(MHWRender::DisplayStatus::kNoStatus) {}
};
typedef std::unordered_map<unsigned int, VP2InstanceDrawInfo*> VP2InstancesDrawInfo;
struct VP2DrawInfo
{
VP2DrawInfo() : mCallbackInitialized(false) {}
VP2InstancesDrawInfo mInstanceInfo;
bool mCallbackInitialized;
};
}
{
public:
footPrint();
~footPrint() override;
static void * creator();
static MObject sizeChangedSinceVP2Update;
static MObject colorChangedSinceVP2Update;
void setSizeChangedSinceVP2Update(bool sizeChanged);
bool getSizeChangedSinceVP2Update();
void setColorChangedSinceVP2Update(bool colorChanged);
bool getColorChangedSinceVP2Update();
friend class footPrintGeometryOverrideAnimatedMaterial;
public:
static MString drawDbClassification;
};
{
public:
{
return new footPrintGeometryOverrideAnimatedMaterial(obj);
}
~footPrintGeometryOverrideAnimatedMaterial() override;
{
return false;
}
{
fputs("footPrintGeometryOverrideAnimatedMaterial: ", stderr);
fputs(message.
asChar(), stderr);
fputs("\n", stderr);
}
static void instancingChangedCallback(
MDagPath& child,
MDagPath& parent,
void* clientData);
private:
footPrintGeometryOverrideAnimatedMaterial(
const MObject& obj);
void clearInstanceInfo();
friend class footPrint;
float mMultiplier;
footPrint* mFootPrintNode;
VP2DrawInfo mVP2DrawInfo;
};
MObject footPrint::sizeChangedSinceVP2Update;
MObject footPrint::colorChangedSinceVP2Update;
MTypeId footPrint::id( 0x00080033 );
MString footPrint::drawDbClassification(
"drawdb/geometry/light/footPrint_GeometryOverride_AnimatedMaterial");
static bool sMakeFootPrintDirLight = (getenv("MAYA_FOOTPRINT_GEOMETRY_OVERRIDE_AS_DIRLIGHT") != NULL);
static MString lightClassification(
"light:drawdb/geometry/light/footPrint_GeometryOverride_AnimatedMaterial:drawdb/light/directionalLight");
MString footPrint::drawRegistrantId(
"footPrintNode_GeometryOverride_AnimatedMaterialPlugin");
footPrint::footPrint() {}
footPrint::~footPrint() {}
{
{
MPlug sizePlug(thisNode, size);
setSizeChangedSinceVP2Update(true);
}
{
MPlug colorPlug(thisNode, solidColor);
setColorChangedSinceVP2Update(true);
}
}
{
{
sizeHandle.
copy(inputSizeHandle);
}
{
colorHandle.
copy(inputColorHandle);
}
else
{
return MS::kUnknownParameter;
}
}
bool footPrint::isBounded() const
{
return true;
}
{
MPlug plug( thisNode, size );
MPoint corner1( -0.17, 0.0, -0.7 );
MPoint corner2( 0.17, 0.0, 0.3 );
corner1 = corner1 * multiplier;
corner2 = corner2 * multiplier;
}
{
}
{
{
setSizeChangedSinceVP2Update(true);
}
{
setColorChangedSinceVP2Update(true);
}
}
void footPrint::setSizeChangedSinceVP2Update(bool sizeChanged)
{
sizeChangedSinceVP2UpdateHandle.
setBool(sizeChanged);
}
void footPrint::setColorChangedSinceVP2Update(bool colorChanged)
{
colorChangedSinceVP2UpdateHandle.
setBool(colorChanged);
}
bool footPrint::getSizeChangedSinceVP2Update()
{
return sizeChangedSinceVP2UpdateHandle.
asBool();
}
bool footPrint::getColorChangedSinceVP2Update()
{
return colorChangedSinceVP2UpdateHandle.
asBool();
}
void* footPrint::creator()
{
return new footPrint();
}
footPrintGeometryOverrideAnimatedMaterial::footPrintGeometryOverrideAnimatedMaterial(
const MObject& obj)
, mLocatorNode(obj)
, mMultiplier(0.0f)
, mFootPrintNode(nullptr)
{
MPxNode* footPrintNode = dependNode.userNode(&returnStatus);
mFootPrintNode = dynamic_cast<footPrint*>(footPrintNode);
}
footPrintGeometryOverrideAnimatedMaterial::~footPrintGeometryOverrideAnimatedMaterial()
{
clearInstanceInfo();
}
void footPrintGeometryOverrideAnimatedMaterial::clearInstanceInfo()
{
VP2InstancesDrawInfo& instanceInfo = mVP2DrawInfo.mInstanceInfo;
for (auto it = instanceInfo.begin(); it != instanceInfo.end(); it++)
{
delete it->second;
}
instanceInfo.clear();
}
{
}
void footPrintGeometryOverrideAnimatedMaterial::updateDG()
{
if (mFootPrintNode->getSizeChangedSinceVP2Update())
{
MPlug plug(mLocatorNode, footPrint::size);
{
{
}
}
}
if (mFootPrintNode->getColorChangedSinceVP2Update())
{
MDataBlock datablock = mFootPrintNode->forceCache();
}
}
void footPrintGeometryOverrideAnimatedMaterial::instancingChangedCallback(
MDagPath& child,
MDagPath& parent,
void* clientData)
{
footPrintGeometryOverrideAnimatedMaterial* geometryOverride = reinterpret_cast<footPrintGeometryOverrideAnimatedMaterial*>(clientData);
geometryOverride->clearInstanceInfo();
}
bool footPrintGeometryOverrideAnimatedMaterial::requiresUpdateRenderItems(
const MDagPath& path)
const
{
auto instanceDrawInfoIter = mVP2DrawInfo.mInstanceInfo.find(path.
instanceNumber(&returnStatus));
if (returnStatus ==
MStatus::kFailure || (mVP2DrawInfo.mInstanceInfo.end() == instanceDrawInfoIter))
return true;
const VP2InstanceDrawInfo* instanceDrawInfo = instanceDrawInfoIter->second;
if (currentDisplayStatus != instanceDrawInfo->mDisplayStatus) return true;
if (mFootPrintNode->getColorChangedSinceVP2Update()) return true;
return false;
}
bool footPrintGeometryOverrideAnimatedMaterial::supportsEvaluationManagerParallelUpdate() const
{
return true;
}
bool footPrintGeometryOverrideAnimatedMaterial::supportsVP2CustomCaching() const
{
return true;
}
bool footPrintGeometryOverrideAnimatedMaterial::requiresGeometryUpdate() const
{
return mFootPrintNode->getSizeChangedSinceVP2Update();
}
{
VP2InstanceDrawInfo* instanceDrawInfo = mVP2DrawInfo.mInstanceInfo[path.
instanceNumber(&returnStatus)];
if (!instanceDrawInfo)
{
instanceDrawInfo = new VP2InstanceDrawInfo;
mVP2DrawInfo.mInstanceInfo[path.
instanceNumber(&returnStatus)] = instanceDrawInfo;
if (!mVP2DrawInfo.mCallbackInitialized)
{
mVP2DrawInfo.mCallbackInitialized = true;
}
}
instanceDrawInfo->mDisplayStatus = displayStatus;
instanceDrawInfo->mDisplayColor = displayColor;
if (!wireframeShader) return;
unsigned int depthPriority;
switch (displayStatus)
{
break;
default:
break;
}
int index = list.
indexOf(wireframeItemName_);
if (index < 0)
{
wireframeItemName_,
}
else
{
wireframeItem = list.
itemAt(index);
}
if(wireframeItem)
{
}
index = list.
indexOf(shadedItemName_);
if (index < 0)
{
shadedItemName_,
}
else
{
shadedItem = list.
itemAt(index);
}
if(shadedItem)
{
if (!solidShader)
{
if (renderer)
{
if (shaderMgr)
{
}
}
if (!solidShader) return;
}
{
float activeColor[] = { displayColor.
r, displayColor.
g, displayColor.
b, 1.0f };
solidShader->
setParameter(colorParameterName_, activeColor);
}
else
{
float solidColor[] = { mSolidColor[0], mSolidColor[1], mSolidColor[2], 1.0f };
}
}
mFootPrintNode->setColorChangedSinceVP2Update(false);
}
void footPrintGeometryOverrideAnimatedMaterial::populateGeometry(
{
float* vertices = NULL;
const int numberOfVertexRequirments = vertexBufferDescriptorList.
length();
for (int requirmentNumber = 0; requirmentNumber < numberOfVertexRequirments; ++requirmentNumber)
{
if (!vertexBufferDescriptorList.
getDescriptor(requirmentNumber, vertexBufferDescriptor))
{
continue;
}
switch (vertexBufferDescriptor.
semantic())
{
{
if (!verticesBuffer)
{
if (verticesBuffer)
{
vertices = (
float*)verticesBuffer->
acquire(soleCount+heelCount,
false);
}
}
}
break;
default:
break;
}
}
int verticesPointerOffset = 0;
for (int currentVertex = 0 ; currentVertex < soleCount+heelCount; ++currentVertex)
{
if(vertices)
{
if (currentVertex < heelCount)
{
int heelVtx = currentVertex;
vertices[verticesPointerOffset++] = heel[heelVtx][0] * mMultiplier;
vertices[verticesPointerOffset++] = heel[heelVtx][1] * mMultiplier;
vertices[verticesPointerOffset++] = heel[heelVtx][2] * mMultiplier;
}
else
{
int soleVtx = currentVertex - heelCount;
vertices[verticesPointerOffset++] = sole[soleVtx][0] * mMultiplier;
vertices[verticesPointerOffset++] = sole[soleVtx][1] * mMultiplier;
vertices[verticesPointerOffset++] = sole[soleVtx][2] * mMultiplier;
}
}
}
if(verticesBuffer && vertices)
{
verticesBuffer->
commit(vertices);
}
for (
int i=0; i < renderItems.
length(); ++i)
{
if (!item)
{
continue;
}
if (item->
name() == wireframeItemName_ )
{
int primitiveIndex = 0;
int startIndex = 0;
int numPrimitive = heelCount + soleCount - 2;
int numIndex = numPrimitive * 2;
unsigned int* indices = (
unsigned int*)indexBuffer->
acquire(numIndex);
for (int i = 0; i < numIndex; )
{
if (i < (heelCount - 1) * 2)
{
startIndex = 0;
primitiveIndex = i / 2;
}
else
{
startIndex = heelCount;
primitiveIndex = i / 2 - heelCount + 1;
}
indices[i++] = startIndex + primitiveIndex;
indices[i++] = startIndex + primitiveIndex + 1;
}
}
else if (item->
name() == shadedItemName_ )
{
int primitiveIndex = 0;
int startIndex = 0;
int numPrimitive = heelCount + soleCount - 4;
int numIndex = numPrimitive * 3;
unsigned int* indices = (
unsigned int*)indexBuffer->
acquire(numIndex);
for (int i = 0; i < numIndex; )
{
if (i < (heelCount - 2) * 3)
{
startIndex = 0;
primitiveIndex = i / 3;
}
else
{
startIndex = heelCount;
primitiveIndex = i / 3 - heelCount + 2;
}
indices[i++] = startIndex;
indices[i++] = startIndex + primitiveIndex + 1;
indices[i++] = startIndex + primitiveIndex + 2;
}
}
}
mFootPrintNode->setSizeChangedSinceVP2Update(false);
}
{
stat = addAttribute(size);
if (!stat) {
return stat;
}
stat = addAttribute(inputSize);
if (!stat) {
return stat;
}
attributeAffects(inputSize, size);
stat = addAttribute(sizeChangedSinceVP2Update);
if (!stat) {
return stat;
}
stat = addAttribute(inputColor);
if (!stat) {
return stat;
}
solidColor = nAttr.
createColor(
"solidColor",
"sc", &stat);
if (!stat) {
return stat;
}
stat = addAttribute(solidColor);
if (!stat) {
return stat;
}
attributeAffects(inputColor, solidColor);
stat = addAttribute(colorChangedSinceVP2Update);
if (!stat) {
return stat;
}
return MS::kSuccess;
}
{
MFnPlugin plugin( obj, PLUGIN_COMPANY,
"3.0",
"Any");
status = plugin.registerNode(
"footPrint_GeometryOverride_AnimatedMaterial",
footPrint::id,
&footPrint::creator,
&footPrint::initialize,
(sMakeFootPrintDirLight ? &lightClassification : &footPrint::drawDbClassification));
if (!status) {
status.
perror(
"registerNode");
return status;
}
footPrint::drawDbClassification,
footPrint::drawRegistrantId,
footPrintGeometryOverrideAnimatedMaterial::Creator);
if (!status) {
status.
perror(
"registerDrawOverrideCreator");
return status;
}
return status;
}
{
footPrint::drawDbClassification,
footPrint::drawRegistrantId);
if (!status) {
status.
perror(
"deregisterDrawOverrideCreator");
return status;
}
status = releaseShaders();
if (!status) {
status.
perror(
"releaseShaders");
return status;
}
status = plugin.deregisterNode( footPrint::id );
if (!status) {
status.
perror(
"deregisterNode");
return status;
}
return status;
}