#include "geometryOverrideHighPerformance.h"
#include "geometryOverrideHighPerformanceHelper.h"
#include <maya/MFnPlugin.h>
#include <maya/MDrawRegistry.h>
#include <maya/MShaderManager.h>
#include <maya/MSelectionMask.h>
#include <maya/MEvaluationNode.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnDagNode.h>
#include <maya/MDistance.h>
#include <maya/MFnUnitAttribute.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MPlugArray.h>
#include <maya/MGeometryExtractor.h>
#include <maya/MGlobal.h>
#include <maya/MDGModifier.h>
static void instancingChangedCallback(
MDagPath& child,
MDagPath& parent,
void* clientData)
{
}
MTypeId GeometryOverrideHighPerformance_shape::fsId =
MTypeId(0x8003F);
MObject GeometryOverrideHighPerformance_shape::fsSize;
MObject GeometryOverrideHighPerformance_shape::fsInputMesh;
MObject GeometryOverrideHighPerformance_shape::fsInputMeshBoundingBoxMin;
MObject GeometryOverrideHighPerformance_shape::fsInputMeshBoundingBoxMax;
MObject GeometryOverrideHighPerformance_shape::fsSizeChangedSinceVP2Update;
MObject GeometryOverrideHighPerformance_shape::fsInputMeshChanged;
MObject GeometryOverrideHighPerformance_shape::fsInputMeshGeoChanged;
MObject GeometryOverrideHighPerformance_shape::fsMaterialChanged;
Float3Array GeometryOverrideHighPerformance_shape::fPositions;
Float3Array GeometryOverrideHighPerformance_shape::fNormals;
Float3Array GeometryOverrideHighPerformance_shape::fTangents;
Float3Array GeometryOverrideHighPerformance_shape::fBiTangents;
Float2Array GeometryOverrideHighPerformance_shape::fTextureCoords;
IndexList GeometryOverrideHighPerformance_shape::fIndices;
MBoundingBox GeometryOverrideHighPerformance_shape::fBoundingBox;
GeometryOverrideHighPerformance_shape::GeometryOverrideHighPerformance_shape()
{
}
MStatus GeometryOverrideHighPerformance_shape::initialize()
{
stat = addAttribute(fsSize);
if (!stat) {
stat.
perror(
"Failed to create the size attribute !");
return stat;
}
stat = addAttribute(fsInputMesh);
if (!stat) {
stat.
perror(
"Failed to create the inputMesh attribute !");
return stat;
}
addAttribute(fsInputMeshBoundingBoxMin);
addAttribute(fsInputMeshBoundingBoxMax);
stat = addAttribute(fsSizeChangedSinceVP2Update);
if (!stat) {
stat.
perror(
"Failed to create the sizeChangedSinceVP2Update attribute !");
return stat;
}
stat = addAttribute(fsInputMeshChanged);
if (!stat) {
stat.
perror(
"Failed to create the inputMeshChangedSinceVP2Update attribute !");
return stat;
}
stat = addAttribute(fsInputMeshGeoChanged);
if (!stat) {
stat.
perror(
"Failed to create the inputMeshGeoChangedSinceVP2Update attribute !");
return stat;
}
stat = addAttribute(fsMaterialChanged);
if (!stat) {
stat.
perror(
"Failed to create the materialChangedSinceVP2Update attribute !");
return stat;
}
createSphere(1, 50, 50,
GeometryOverrideHighPerformance_shape::fPositions,
GeometryOverrideHighPerformance_shape::fNormals,
GeometryOverrideHighPerformance_shape::fTangents,
GeometryOverrideHighPerformance_shape::fBiTangents,
GeometryOverrideHighPerformance_shape::fTextureCoords,
GeometryOverrideHighPerformance_shape::fIndices,
GeometryOverrideHighPerformance_shape::fBoundingBox);
return MS::kSuccess;
}
GeometryOverrideHighPerformance_shape::~GeometryOverrideHighPerformance_shape()
{
}
void GeometryOverrideHighPerformance_shape::postConstructor()
{
setRenderable(true);
}
MSelectionMask GeometryOverrideHighPerformance_shape::getShapeSelectionMask()
const
{
}
MBoundingBox GeometryOverrideHighPerformance_shape::boundingBox()
const
{
MPlug sizePlug(thisNode, fsSize);
sizePlug.getValue(sizeVal);
if(fUseInputMesh)
{
MDataBlock block =
const_cast<GeometryOverrideHighPerformance_shape*
>(
this)->forceCache();
}
return MBoundingBox(fBoundingBox.min() * multiplier, fBoundingBox.max() * multiplier);
}
MStatus GeometryOverrideHighPerformance_shape::connectionMade(
const MPlug& plug,
const MPlug& otherPlug,
bool asSrc)
{
if (asSrc &&
{
setMaterialChangedSinceVP2Update(true);
}
if (!asSrc &&
{
fUseInputMesh = true;
setInputMeshChangedSinceVP2Update(true);
MPlug boundingBoxMinPlug(thisNode, fsInputMeshBoundingBoxMin);
MPlug boundingBoxMaxPlug(thisNode, fsInputMeshBoundingBoxMax);
modifier.
connect(inputMeshBoundingBoxMinPlug, boundingBoxMinPlug);
modifier.connect(inputMeshBoundingBoxMaxPlug, boundingBoxMaxPlug);
modifier.doIt();
}
}
MStatus GeometryOverrideHighPerformance_shape::connectionBroken(
const MPlug& plug,
const MPlug& otherPlug,
bool asSrc)
{
if (asSrc &&
{
setMaterialChangedSinceVP2Update(true);
}
if (!asSrc &&
{
fUseInputMesh = false;
setInputMeshChangedSinceVP2Update(true);
MPlug boundingBoxMinPlug(thisNode, fsInputMeshBoundingBoxMin);
MPlug boundingBoxMaxPlug(thisNode, fsInputMeshBoundingBoxMax);
modifier.
disconnect(inputMeshBoundingBoxMinPlug, boundingBoxMinPlug);
modifier.disconnect(inputMeshBoundingBoxMaxPlug, boundingBoxMaxPlug);
modifier.doIt();
}
}
{
if (plug.
attribute() == GeometryOverrideHighPerformance_shape::fsSize)
{
setSizeChangedSinceVP2Update(true);
}
else if (plug.
attribute() == GeometryOverrideHighPerformance_shape::fsInputMesh)
{
setInputMeshGeoChangedSinceVP2Update(true);
}
}
{
if (evaluationNode.
dirtyPlugExists(GeometryOverrideHighPerformance_shape::fsSize, &status) && status)
{
setSizeChangedSinceVP2Update(true);
}
if (evaluationNode.
dirtyPlugExists(GeometryOverrideHighPerformance_shape::fsInputMesh, &status) && status)
{
setInputMeshGeoChangedSinceVP2Update(true);
}
}
void GeometryOverrideHighPerformance_shape::setSizeChangedSinceVP2Update(bool sizeChanged)
{
}
bool GeometryOverrideHighPerformance_shape::evalSizeChangedSinceVP2Update()
{
}
void GeometryOverrideHighPerformance_shape::setInputMeshChangedSinceVP2Update(bool value)
{
}
bool GeometryOverrideHighPerformance_shape::evalInputMeshChangedSinceVP2Update()
{
}
void GeometryOverrideHighPerformance_shape::setInputMeshGeoChangedSinceVP2Update(bool value)
{
}
bool GeometryOverrideHighPerformance_shape::evalInputMeshGeoChangedSinceVP2Update()
{
}
bool GeometryOverrideHighPerformance_shape::evalMaterialChangedSinceVP2Update()
{
}
void GeometryOverrideHighPerformance_shape::setMaterialChangedSinceVP2Update(bool value)
{
}
const char* GeometryOverrideHighPerformance::sActiveWireframeRenderItemName = "GeometryOverrideHighPerformance_ActiveWireframe";
const char* GeometryOverrideHighPerformance::sDormantWireframeRenderItemName = "GeometryOverrideHighPerformance_DormantWireframe";
const char* GeometryOverrideHighPerformance::sCustomShadedItemName = "GeometryOverrideHighPerformance_shaded";
GeometryOverrideHighPerformance::GeometryOverrideHighPerformance(
const MObject& obj)
, fSurfaceNode(obj)
{
if (status)
{
fMesh = dynamic_cast<GeometryOverrideHighPerformance_shape*>(node.userNode());
}
}
GeometryOverrideHighPerformance::~GeometryOverrideHighPerformance()
{
}
{
}
void GeometryOverrideHighPerformance::updateDG()
{
if (fMesh && fMesh->evalInputMeshChangedSinceVP2Update())
{
MPlug plug(fSurfaceNode, GeometryOverrideHighPerformance_shape::fsInputMesh);
{
for (
unsigned int i = 0; i < connections.
length(); ++i)
{
MObject node = connections[i].node();
{
break;
}
}
}
else
{
}
}
if (fMesh && fMesh->evalSizeChangedSinceVP2Update())
{
MPlug plug(fSurfaceNode, GeometryOverrideHighPerformance_shape::fsSize);
{
{
}
}
}
}
bool GeometryOverrideHighPerformance::requiresGeometryUpdate() const
{
return fMesh &&
(fMesh->evalInputMeshChangedSinceVP2Update() ||
fMesh->evalInputMeshGeoChangedSinceVP2Update() ||
fMesh->evalSizeChangedSinceVP2Update());
}
{
if(fInputMeshPath.isValid())
{
if (fMesh && fMesh->evalInputMeshChangedSinceVP2Update())
{
return true;
}
else if (fMesh &&
( fMesh->evalInputMeshGeoChangedSinceVP2Update() ||
fMesh->evalSizeChangedSinceVP2Update()))
{
return true;
}
else
{
return true;
}
}
else
{
if(fMesh && fMesh->evalInputMeshChangedSinceVP2Update())
{
return true;
}
else if (desc.
semantic() == MGeometry::kPosition)
{
return fMesh && fMesh->evalSizeChangedSinceVP2Update();
}
else
{
return false;
}
}
}
bool GeometryOverrideHighPerformance::isIndexingDirty(const MRenderItem& item)
{
return fMesh && fMesh->evalInputMeshChangedSinceVP2Update();
}
bool GeometryOverrideHighPerformance::requiresUpdateRenderItems(
const MDagPath& path)
const
{
if(fMesh && fMesh->evalMaterialChangedSinceVP2Update())
{
fMesh->setMaterialChangedSinceVP2Update(false);
return true;
}
if (currentDisplayStatus == fDisplayStatus)
return false;
return true;
}
bool GeometryOverrideHighPerformance::supportsEvaluationManagerParallelUpdate() const
{
return true;
}
bool GeometryOverrideHighPerformance::supportsVP2CustomCaching() const
{
return true;
}
{
return;
MRenderer* renderer = MRenderer::theRenderer();
if (!renderer)
return;
const MShaderManager* shaderManager = renderer->getShaderManager();
if (!shaderManager)
return;
auto standardShadedItemIndex = renderItems.
indexOf(
"StandardShadedItem");
auto renderItemIndex = renderItems.
indexOf(sCustomShadedItemName);
if (standardShadedItemIndex < 0 && renderItemIndex < 0)
{
shadedRenderItem->
enable(
true);
MShaderInstance* shader = shaderManager->getFragmentShader("mayaLambertSurface", "outSurfaceFinal", true);
if (shader)
{
const float blueColor[] = { 0.0f, 0.0f, 1.0f, 1.0f };
shader->setParameter("color", blueColor);
shaderManager->releaseShader(shader);
}
renderItems.
append(shadedRenderItem);
}
if(standardShadedItemIndex >= 0 && renderItemIndex >= 0)
{
if (renderItem)
renderItem = renderItems.
itemAt(standardShadedItemIndex);
if (renderItem)
}
if (standardShadedItemIndex < 0 && renderItemIndex >= 0)
{
if (renderItem)
}
updateWireframeItems(sActiveWireframeRenderItemName,
fWireframeDisplayColor,
isWireFrameRenderItemEnabled,
renderItems,
*shaderManager);
updateWireframeItems(sDormantWireframeRenderItemName,
fWireframeDisplayColor,
isWireFrameRenderItemEnabled,
renderItems,
*shaderManager);
}
{
if (!fMesh)
return;
if(fInputMeshPath.isValid())
{
populateInputMeshGeometry(requirements, renderItems, data);
}
else
{
populateDefaultMeshGeometry(requirements, renderItems, data);
}
fMesh->setSizeChangedSinceVP2Update(false);
fMesh->setInputMeshChangedSinceVP2Update(false);
fMesh->setInputMeshGeoChangedSinceVP2Update(false);
}
void GeometryOverrideHighPerformance::cleanUp()
{
}
void GeometryOverrideHighPerformance::updateWireframeItems(const char* renderItemName, MGeometry::DrawMode drawMode,
unsigned int depthPriority,
MColor color,
bool isEnabled,
{
auto renderItemIndex = renderItemList.
indexOf(renderItemName);
if (renderItemIndex < 0)
{
MShaderInstance* shader = shaderManager.
getStockShader(MShaderManager::k3dSolidShader);
if (shader)
{
}
renderItemList.
append(renderItem);
}
else
{
renderItem = renderItemList.
itemAt(renderItemIndex);
}
if(renderItem)
{
if (shader)
{
}
renderItem->
enable(isEnabled);
}
}
{
if (MS::kFailure == status)
return;
const MVertexBufferDescriptorList& vertexBufferDescriptorList = requirements.
vertexRequirements();
for (int i = 0; i < vertexBufferDescriptorList.length(); i++)
{
MVertexBufferDescriptor desc{};
if (!vertexBufferDescriptorList.getDescriptor(i, desc))
continue;
if (vertexBuffer)
{
float* data = (float*)vertexBuffer->acquire(vertexCount, true );
if (data)
{
status = extractor.populateVertexBuffer(data, vertexCount, desc);
if (MS::kFailure == status)
return;
if (desc.
semantic() == MGeometry::kPosition)
{
for (int i = 0; i < vertexCount; i++)
{
data[i * 3] *= fSizeMultiplier;
data[i * 3 + 1] *= fSizeMultiplier;
data[i * 3 + 2] *= fSizeMultiplier;
}
}
vertexBuffer->commit(data);
}
}
}
for (
int i = 0; i < renderItems.
length(); ++i)
{
const MRenderItem* item = renderItems.
itemAt(i);
if (!item) continue;
MIndexBuffer* indexBuffer = data.createIndexBuffer(MGeometry::kUnsignedInt32);
if (!indexBuffer) continue;
if (item->primitive() == MGeometry::kTriangles)
{
MIndexBufferDescriptor triangleDesc(MIndexBufferDescriptor::kTriangle,
MString(), MGeometry::kTriangles, 3);
unsigned int numTriangles = extractor.primitiveCount(triangleDesc);
unsigned int* indices = (unsigned int*)indexBuffer->acquire(3 * numTriangles, true );
status = extractor.populateIndexBuffer(indices, numTriangles, triangleDesc);
if (MS::kFailure == status)
return;
indexBuffer->commit(indices);
}
else if (item->primitive() == MGeometry::kLines)
{
MIndexBufferDescriptor edgeDesc(MIndexBufferDescriptor::kEdgeLine,
MString(), MGeometry::kLines, 2);
unsigned int numEdges = extractor.primitiveCount(edgeDesc);
unsigned int* indices = (unsigned int*)indexBuffer->acquire(2 * numEdges, true );
status = extractor.populateIndexBuffer(indices, numEdges, edgeDesc);
if (MS::kFailure == status)
return;
indexBuffer->commit(indices);
}
item->associateWithIndexBuffer(indexBuffer);
}
}
{
const MVertexBufferDescriptorList& vertexBufferDescriptorList = requirements.
vertexRequirements();
for (int i = 0; i < vertexBufferDescriptorList.length(); i++)
{
MVertexBufferDescriptor desc{};
if (!vertexBufferDescriptorList.getDescriptor(i, desc))
continue;
{
case MGeometry::kPosition:
{
if (positionBuffer)
{
const Float3Array& positions = fMesh->getPositions();
Float3* buffer =
static_cast<Float3*
>(positionBuffer->
acquire(positions.size(),
true ));
if (buffer)
{
for (std::size_t i = 0; i < positions.size(); i++)
{
buffer[i].x = positions[i].x * fSizeMultiplier;
buffer[i].y = positions[i].y * fSizeMultiplier;
buffer[i].z = positions[i].z * fSizeMultiplier;
}
positionBuffer->
commit(buffer);
}
}
}
break;
case MGeometry::kNormal:
{
if (normalsBuffer)
{
const Float3Array& normals = fMesh->getNormals();
void* buffer = normalsBuffer->
acquire(normals.size(),
true );
if (buffer)
{
const std::size_t bufferSizeInByte =
sizeof(Float3Array::value_type) * normals.size();
memcpy(buffer, normals.data(), bufferSizeInByte);
normalsBuffer->
commit(buffer);
}
}
}
break;
case MGeometry::kTangent:
{
if (tangentBuffer)
{
const Float3Array& tangents = fMesh->getTangents();
void* buffer = tangentBuffer->
acquire(tangents.size(),
true );
if (buffer)
{
const std::size_t bufferSizeInByte =
sizeof(Float3Array::value_type) * tangents.size();
memcpy(buffer, tangents.data(), bufferSizeInByte);
tangentBuffer->
commit(buffer);
}
}
}
break;
case MGeometry::kBitangent:
{
if (tangentBuffer)
{
const Float3Array& tangents = fMesh->getBiTangents();
void* buffer = tangentBuffer->
acquire(tangents.size(),
true );
if (buffer)
{
const std::size_t bufferSizeInByte =
sizeof(Float3Array::value_type) * tangents.size();
memcpy(buffer, tangents.data(), bufferSizeInByte);
tangentBuffer->
commit(buffer);
}
}
}
break;
case MGeometry::kTexture:
{
if (vertexBuffer)
{
const Float2Array& texCoords = fMesh->getTexCoords();
void* vertexBufferData = vertexBuffer->
acquire(texCoords.size(),
true );
if (vertexBufferData)
{
const std::size_t bufferSizeInByte =
sizeof(Float2Array::value_type) * texCoords.size();
memcpy(vertexBufferData, texCoords.data(), bufferSizeInByte);
vertexBuffer->
commit(vertexBufferData);
}
}
}
break;
case MGeometry::kColor:
case MGeometry::kTangentWithSign:
case MGeometry::kInvalidSemantic:
break;
}
}
const int numItems = renderItems.
length();
for (int i = 0; i < numItems; i++)
{
if (!item)
continue;
{
if (indexBuffer)
{
IndexList indices = fMesh->getIndices();
void* buffer = indexBuffer->
acquire(indices.size(),
true );
if (buffer)
{
const std::size_t bufferSizeInByte =
sizeof(IndexList::value_type) * indices.size();
memcpy(buffer, indices.data(), bufferSizeInByte);
}
}
}
}
}
namespace
{
MString sDrawDbClassification(
"drawdb/geometry/geometryOverrideHighPerformance");
MString sDrawRegistrantId(
"geometryOverrideHighPerformancePlugin");
}
{
MFnPlugin plugin(obj, PLUGIN_COMPANY,
"1.0",
"Any");
status = plugin.registerShape("geometryOverrideHighPerformance_shape",
GeometryOverrideHighPerformance_shape::fsId,
&GeometryOverrideHighPerformance_shape::creator,
&GeometryOverrideHighPerformance_shape::initialize,
nullptr,
&sDrawDbClassification);
if (!status)
{
cerr << "Failed to register geometryOverrideHighPerformance_shape." << std::endl;
return status;
}
sDrawRegistrantId,
GeometryOverrideHighPerformance::Creator);
if (!status)
{
std::cerr << "Failed to register Viewport 2.0 geometry override." << std::endl;
return status;
}
return status;
}
{
if (!status)
{
std::cerr << "Failed to deregister geometry override." << std::endl;
}
status = plugin.deregisterNode(GeometryOverrideHighPerformance_shape::fsId);
if (!status)
{
cerr << "Failed to deregister GeometryOverrideHighPerformance_shape." << std::endl;
}
return status;
}