Last active
February 22, 2024 09:45
-
-
Save JohnOnSoftware/9ca01686525a368b765f3da247215a35 to your computer and use it in GitHub Desktop.
Core code to support XGen Interactive Grooming in Arnold
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MFnDagNode fnDagNode(m_dagPath); | |
// Apply the render overrides | |
static const MString sApplyRenderOverrideCmd = "xgmSplineApplyRenderOverride "; | |
MGlobal::executeCommand(sApplyRenderOverrideCmd + fnDagNode.partialPathName()); | |
// Stream out the spline data | |
std::string data; | |
MPlug outPlug = fnDagNode.findPlug("outRenderData"); | |
MObject outObj = outPlug.asMObject(); | |
MPxData* outData = MFnPluginData(outObj).data(); | |
if (outData) | |
{ | |
std::ostringstream opaqueStrm; | |
outData->writeBinary(opaqueStrm); | |
data = opaqueStrm.str(); | |
} | |
// Load the sample for i-th motion step | |
_splines.load(opaqueStrm, sampleSize, sampleTime) | |
// Count the number of curves and the number of points | |
// Arnold's b-spline requires two phantom points. | |
unsigned int curveCount = 0; | |
unsigned int pointCount = 0; | |
unsigned int pointInterpoCount = 0; | |
for (XgItSpline splineIt = _splines.iterator(); !splineIt.isDone(); splineIt.next()) | |
{ | |
curveCount += splineIt.primitiveCount(); | |
pointCount += splineIt.vertexCount(); | |
pointInterpoCount += splineIt.vertexCount() + splineIt.primitiveCount() * 2; | |
} | |
// Get the number of motion samples | |
const unsigned int steps = _splines.sampleCount(); | |
// Allocate buffers for the curves | |
_numPoints = AiArrayAllocate(curveCount, 1, AI_TYPE_UINT); | |
_points = AiArrayAllocate(pointInterpoCount, steps, AI_TYPE_POINT); | |
_radius = AiArrayAllocate(pointCount, 1, AI_TYPE_FLOAT); | |
_uCoord = AiArrayAllocate(curveCount, 1, AI_TYPE_FLOAT); | |
_vCoord = AiArrayAllocate(curveCount, 1, AI_TYPE_FLOAT); | |
_wCoord = AiArrayAllocate(pointInterpoCount, 1, AI_TYPE_FLOAT); | |
unsigned int* numPoints = reinterpret_cast<unsigned int*>(_numPoints->data); | |
SgVec3f* points = reinterpret_cast<SgVec3f*>(_points->data); | |
float* radius = reinterpret_cast<float*>(_radius->data); | |
float* uCoord = reinterpret_cast<float*>(_uCoord->data); | |
float* vCoord = reinterpret_cast<float*>(_vCoord->data); | |
float* wCoord = reinterpret_cast<float*>(_wCoord->data); | |
// Fill the array buffers for motion step 0 | |
for (XgItSpline splineIt = _splines.iterator(); !splineIt.isDone(); splineIt.next()) | |
{ | |
const unsigned int stride = splineIt.primitiveInfoStride(); | |
const unsigned int primitiveCount = splineIt.primitiveCount(); | |
const unsigned int* primitiveInfos = splineIt.primitiveInfos(); | |
const SgVec3f* positions = splineIt.positions(0); | |
const float* width = splineIt.width(); | |
const SgVec2f* texcoords = splineIt.texcoords(); | |
const SgVec2f* patchUVs = splineIt.patchUVs(); | |
for (unsigned int p = 0; p < primitiveCount; p++) | |
{ | |
const unsigned int offset = primitiveInfos[p * stride]; | |
const unsigned int length = primitiveInfos[p * stride + 1]; | |
// Number of points | |
*numPoints++ = length + 2; | |
// Texcoord using the patch UV from the root point | |
*uCoord++ = patchUVs[offset][0]; | |
*vCoord++ = patchUVs[offset][1]; | |
// Add phantom points at the beginning | |
*points++ = phantomFirst(&positions[offset], length); | |
*wCoord++ = phantomFirst(&texcoords[offset], length)[1]; | |
// Copy varying data | |
for (unsigned int i = 0; i < length; i++) | |
{ | |
*points++ = positions[offset + i]; | |
*radius++ = width[offset + i] * 0.5f; | |
*wCoord++ = texcoords[offset + i][1]; | |
} | |
// Add phantom points at the end | |
*points++ = phantomLast(&positions[offset], length); | |
*wCoord++ = phantomLast(&texcoords[offset], length)[1]; | |
} // for each primitive | |
} // for each primitive batch | |
// Fill the array buffers for motion step > 0 | |
for (unsigned int key = 1; key < steps; key++) | |
{ | |
for (XgItSpline splineIt = _splines.iterator(); !splineIt.isDone(); splineIt.next()) | |
{ | |
const unsigned int stride = splineIt.primitiveInfoStride(); | |
const unsigned int primitiveCount = splineIt.primitiveCount(); | |
const unsigned int* primitiveInfos = splineIt.primitiveInfos(); | |
const SgVec3f* positions = splineIt.positions(key); | |
for (unsigned int p = 0; p < primitiveCount; p++) | |
{ | |
const unsigned int offset = primitiveInfos[p * stride]; | |
const unsigned int length = primitiveInfos[p * stride + 1]; | |
// Add phantom points at the beginning | |
*points++ = phantomFirst(&positions[offset], length); | |
// Copy varying data | |
for (unsigned int i = 0; i < length; i++) | |
{ | |
*points++ = positions[offset + i]; | |
} | |
// Add phantom points at the end | |
*points++ = phantomLast(&positions[offset], length); | |
} // for each primitive | |
} // for each primitive batch | |
} // for each motion step | |
// Set the buffers to the curves node | |
AiNodeSetArray(_curves, "num_points", _numPoints); | |
AiNodeSetArray(_curves, "points", _points); | |
AiNodeSetArray(_curves, "radius", _radius); | |
AiNodeSetArray(_curves, "uparamcoord", _uCoord); | |
AiNodeSetArray(_curves, "vparamcoord", _vCoord); | |
AiNodeSetArray(_curves, "wparamcoord", _wCoord); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment