#include <string.h>
#include <maya/MIOStream.h>
#include <maya/MStringArray.h>
#include <math.h>
#include <maya/MPxDeformerNode.h>
#include <maya/MItGeometry.h>
#include <maya/MPxLocatorNode.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnMatrixAttribute.h>
#include <maya/MFnMatrixData.h>
#include <maya/MFnFloatArrayData.h>
#include <maya/MFnPlugin.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MTypeId.h>
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MArrayDataHandle.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MMatrix.h>
#include <maya/MMatrixArray.h>
#include <maya/MDagModifier.h>
#include <maya/MPxGPUStandardDeformer.h>
#include <maya/MGPUDeformerRegistry.h>
#include <maya/MOpenCLBuffer.h>
#include <maya/MOpenCLInfo.h>
#include <maya/MOpenCLUtils.h>
#include <maya/MViewport2Renderer.h>
#include <maya/MFnMesh.h>
#include <clew/clew.h>
#include <vector>
{
public:
offset();
~offset() override;
static void* creator();
unsigned int multiIndex) override;
public:
private:
};
offset::offset() {}
offset::~offset() {}
void* offset::creator()
{
return new offset();
}
{
offsetMatrix=mAttr.
create(
"locateMatrix",
"lm");
addAttribute( offsetMatrix);
addAttribute( chunkEnvelope );
addAttribute( chunkCount );
attributeAffects( offset::offsetMatrix, offset::outputGeom );
attributeAffects( offset::chunkEnvelope, offset::outputGeom );
attributeAffects( offset::chunkCount, offset::outputGeom );
}
unsigned int multiIndex)
{
if (MS::kSuccess != returnStatus)
return returnStatus;
float chunkWeight = chunkEnvelopeData.
asFloat();
int numChunks = chunkCountData.
asInt();
if (numChunks != randomOffsetTable.length()) {
srand(numChunks*827);
randomOffsetTable.setLength(numChunks);
for (size_t i = 0; i < numChunks; ++i) {
float r = (rand() % 1001)/500.0 - 1.0;
randomOffsetTable.set(r, i);
}
}
if (MS::kSuccess != returnStatus) return returnStatus;
bool useRandomOffset = (numChunks > 0 && chunkWeight > 0.0);
pt *= omatinv;
float weight = weightValue(block,multiIndex,iter.
index());
if (useRandomOffset)
weight *= (1.0 + chunkWeight*randomOffsetTable[iter.
index()%numChunks]);
pt.
y = pt.
y + env*weight;
pt *= omat;
}
return returnStatus;
}
offset::accessoryAttribute() const
{
return offset::offsetMatrix;
}
{
&result);
if (MS::kSuccess == result) {
MObject attrMat = fnLoc.attribute(attrName);
result = cmd.
connect(objLoc,attrMat,this->thisMObject(),offset::offsetMatrix);
}
return result;
}
offset::getFixedSetupData(
const MString& name)
{
if (name == "randomOffsetTable") {
return fn.
create(randomOffsetTable);
}
}
{
public:
offsetGPUDeformer();
~offsetGPUDeformer() override;
private:
unsigned int fRandomOffsetTableSize;
float fChunkEnvelope;
};
{
public:
offsetNodeGPUDeformerInfo() {}
~offsetNodeGPUDeformerInfo() override{}
{
return new offsetGPUDeformer();
}
{
return offsetGPUDeformer::validateNodeInGraph(block, evaluationNode, plug, messages);
}
{
return offsetGPUDeformer::validateNodeValues(block, evaluationNode, plug, messages);
}
};
{
static offsetNodeGPUDeformerInfo theOne;
return &theOne;
}
offsetGPUDeformer::offsetGPUDeformer()
{
}
offsetGPUDeformer::~offsetGPUDeformer()
{
terminate();
}
{
return true;
}
{
MPlug chunkEnvelopePlug(node, offset::chunkEnvelope);
chunkEnvelopePlug.getValue(chunkEnvelopeData);
if (chunkEnvelopeData.
asFloat() < 0.0)
{
MOpenCLInfo::appendMessage(messages,
"Offset %s not supported by deformer evaluator because chunkEnvelope is smaller than 0.0", fnNode.name().asChar());
return false;
}
return true;
}
cl_int offsetGPUDeformer::enqueueDeformation(
{
cl_int err = CL_SUCCESS;
unsigned int count = affectCount();
MGPUEventList eventList;
eventList.
add(syncInputEvent);
unsigned int parameterId = 0;
err = fKernelInfo.setKernelArgBuffer(parameterId++, outputPositions.
buffer(), err);
err = fKernelInfo.setKernelArgBuffer(parameterId++, inputPositions.
buffer(), err);
err = fKernelInfo.setKernelArgBuffer(parameterId++, weightsBuffer(), err, hasEnvelopeWeights());
err = fKernelInfo.setKernelArgBuffer(parameterId++, affectMapBuffer(), err, !isIdentityMap());
err = fKernelInfo.setKernelArgBuffer(parameterId++, fOffsetMatrixBuffer, err);
err = fKernelInfo.setKernelArgBuffer(parameterId++, fRandomOffsetTableBuffer, err);
err = fKernelInfo.setKernelArg<cl_uint>(parameterId++, fRandomOffsetTableSize, err);
err = fKernelInfo.setKernelArg<cl_float>(parameterId++, envelope(), err);
err = fKernelInfo.setKernelArg<cl_float>(parameterId++, fChunkEnvelope, err);
err = fKernelInfo.setKernelArg<cl_uint>(parameterId++, count, err);
return CL_SUCCESS == err ? fKernelInfo.enqueueKernel(eventList, syncEvent) : err;
}
MPxGPUDeformer::DeformerStatus offsetGPUDeformer::evaluate(
)
{
MPxGPUDeformer::DeformerStatus ds = prepareEvaluation(block, evaluationNode, plug, inputPlugs, inputData, outputData, syncEvent);
if (ds != MPxGPUDeformer::kDeformerSuccess)
return ds;
prepareAffectMapBuffer();
prepareWeightsBuffer(evaluationNode);
extractOffsetMatrix(block, evaluationNode, plug);
extractRandomOffsetTable(block, evaluationNode, plug);
fChunkEnvelope = (MS::kSuccess != status) ? 1.0 : chunkEnvelopeData.
asFloat();
MString openCLKernelFile = offset::pluginPath +
"/offset.cl";
MString openCLKernelName(
"offset");
if (!fKernelInfo.loadOrUpdate(openCLKernelFile, openCLKernelName, affectCount()))
return MPxGPUDeformer::kDeformerFailure;
cl_int err = CL_SUCCESS;
err = initializeOutputPositions(syncEvent);
if ( err != CL_SUCCESS )
return MPxGPUDeformer::kDeformerFailure;
err = enqueueDeformation(syncEvent, inputPositions(), outputPositions());
if ( err != CL_SUCCESS )
return MPxGPUDeformer::kDeformerFailure;
return finishEvaluation(syncEvent, outputData);
}
void offsetGPUDeformer::terminate()
{
fOffsetMatrixBuffer.reset();
fRandomOffsetTableBuffer.reset();
fKernelInfo.reset();
}
{
if (!isBufferUpdateNeeded(fOffsetMatrixBuffer, evaluationNode, offset::offsetMatrix))
{
return true;
}
if (MS::kSuccess != status)
return false;
return (err == CL_SUCCESS);
}
{
if (!isBufferUpdateNeeded(fRandomOffsetTableBuffer, evaluationNode, offset::chunkCount))
{
return true;
}
cl_int err = CL_SUCCESS;
err = uploadFixedSetupData("randomOffsetTable", fRandomOffsetTableBuffer, err, &fRandomOffsetTableSize);
return (err == CL_SUCCESS);
}
{
MFnPlugin plugin( obj, PLUGIN_COMPANY,
"3.0",
"Any");
result = plugin.registerNode( "offset", offset::id, offset::creator,
MString registrantId(
"mayaPluginExample");
nodeClassName,
registrantId,
offsetGPUDeformer::getGPUDeformerInfo());
nodeClassName,
registrantId,
offset::chunkEnvelope);
offset::pluginPath = plugin.loadPath();
return result;
}
{
MString registrantId(
"mayaPluginExample");
nodeClassName,
registrantId);
result = plugin.deregisterNode(offset::id);
return result;
}