MStatus AlembicCurvesLocatorNode::compute(const MPlug &plug, MDataBlock &dataBlock) { ESS_PROFILE_SCOPE("AlembicCurvesLocatorNode::compute"); MStatus status; // update the frame number to be imported double inputTime = dataBlock.inputValue(mTimeAttr).asTime().as(MTime::kSeconds); MString &fileName = dataBlock.inputValue(mFileNameAttr).asString(); MString &identifier = dataBlock.inputValue(mIdentifierAttr).asString(); AbcG::ICurves obj; // check if we have the file if (fileName != mFileName || identifier != mIdentifier) { mSchema.reset(); if (fileName != mFileName) { delRefArchive(mFileName); mFileName = fileName; addRefArchive(mFileName); } mIdentifier = identifier; // get the object from the archive Abc::IObject iObj = getObjectFromArchive(mFileName, identifier); if (!iObj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' not found in archive '" + mFileName + "'."); return MStatus::kFailure; } obj = AbcG::ICurves(iObj, Abc::kWrapExisting); if (!obj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' in archive '" + mFileName + "' is not a Curves."); return MStatus::kFailure; } mSchema = obj.getSchema(); } if (!mSchema.valid()) { return MStatus::kFailure; } // get the sample SampleInfo sampleInfo = getSampleInfo(inputTime, mSchema.getTimeSampling(), mSchema.getNumSamples()); // check if we have to do this at all if (mNbCurves == 0 || mLastSampleInfo.floorIndex != sampleInfo.floorIndex || mLastSampleInfo.ceilIndex != sampleInfo.ceilIndex) { AbcG::ICurvesSchema::Sample sample; AbcG::ICurvesSchema::Sample sample2; mSchema.get(sample, sampleInfo.floorIndex); if (sampleInfo.alpha != 0.0) { mSchema.get(sample2, sampleInfo.ceilIndex); } // update the indices Abc::P3fArraySamplePtr samplePos = sample.getPositions(); if (mNbCurves != sample.getNumCurves() || mNbVertices != samplePos->size()) { mNbCurves = (unsigned int)sample.getNumCurves(); mNbVertices = (unsigned int)samplePos->size(); Abc::Int32ArraySamplePtr nbVertices = sample.getCurvesNumVertices(); mIndices.clear(); unsigned int offset = 0; for (unsigned int i = 0; i < mNbCurves; i++) { unsigned int verticesPerCurve = nbVertices->get()[i]; for (unsigned j = 0; j < verticesPerCurve - 1; j++) { mIndices.push_back(offset); offset++; mIndices.push_back(offset); } offset++; } } if (mPositions.size() != samplePos->size()) { mPositions.resize(samplePos->size()); } // check if we need to interpolate bool done = false; mBoundingBox.clear(); if (sampleInfo.alpha != 0.0) { Abc::P3fArraySamplePtr samplePos2 = sample2.getPositions(); if (samplePos->size() == samplePos2->size()) { float alpha = float(sampleInfo.alpha); float ialpha = 1.0f - alpha; for (unsigned int i = 0; i < samplePos->size(); i++) { mPositions[i].x = ialpha * samplePos->get()[i].x + alpha * samplePos2->get()[i].x; mPositions[i].y = ialpha * samplePos->get()[i].y + alpha * samplePos2->get()[i].y; mPositions[i].z = ialpha * samplePos->get()[i].z + alpha * samplePos2->get()[i].z; mBoundingBox.expand( MPoint(mPositions[i].x, mPositions[i].y, mPositions[i].z)); } done = true; } } if (!done) { for (unsigned int i = 0; i < samplePos->size(); i++) { mPositions[i].x = samplePos->get()[i].x; mPositions[i].y = samplePos->get()[i].y; mPositions[i].z = samplePos->get()[i].z; mBoundingBox.expand( MPoint(mPositions[i].x, mPositions[i].y, mPositions[i].z)); } } // get the colors // mColors.clear(); Abc::IC4fArrayProperty propColor; if (getArbGeomParamPropertyAlembic(obj, "color", propColor)) { mColors.clear(); SampleInfo colorSampleInfo = getSampleInfo( inputTime, propColor.getTimeSampling(), propColor.getNumSamples()); Abc::C4fArraySamplePtr sampleColor = propColor.getValue(colorSampleInfo.floorIndex); mColors.resize(mPositions.size()); if (sampleColor->size() == 1) { for (unsigned int i = 0; i < (unsigned int)mColors.size(); i++) { mColors[i].r = sampleColor->get()[0].r; mColors[i].g = sampleColor->get()[0].g; mColors[i].b = sampleColor->get()[0].b; mColors[i].a = sampleColor->get()[0].a; } } else if (sampleColor->size() == mPositions.size()) { for (unsigned int i = 0; i < sampleColor->size(); i++) { mColors[i].r = sampleColor->get()[i].r; mColors[i].g = sampleColor->get()[i].g; mColors[i].b = sampleColor->get()[i].b; mColors[i].a = sampleColor->get()[i].a; } } else if (sampleColor->size() == mNbCurves) { Abc::Int32ArraySamplePtr nbVertices = sample.getCurvesNumVertices(); unsigned int offset = 0; for (unsigned int i = 0; i < nbVertices->size(); i++) { for (unsigned j = 0; j < (unsigned int)nbVertices->get()[i]; j++) { mColors[offset].r = sampleColor->get()[i].r; mColors[offset].g = sampleColor->get()[i].g; mColors[offset].b = sampleColor->get()[i].b; mColors[offset].a = sampleColor->get()[i].a; offset++; } } } } } mLastSampleInfo = sampleInfo; MDataHandle outSent = dataBlock.outputValue(mSentinelAttr); // increment, this tells the draw routine that the display list needs to be // regenerated outSent.set((mSent + 1 % 10)); dataBlock.setClean(mSentinelAttr); return MStatus::kSuccess; }
AtNode *createCurvesNode(nodeData &nodata, userData * ud, std::vector<float> &samples, int i) { Alembic::AbcGeom::ICurves typedObject(nodata.object, Alembic::Abc::kWrapExisting); size_t minNumSamples = typedObject.getSchema().getNumSamples() == 1 ? typedObject.getSchema().getNumSamples() : samples.size(); shiftedProcessing(nodata, ud); AtNode *shapeNode = AiNode("curves"); nodata.createdShifted = false; // create arrays to hold the data AtArray *pos = NULL; // loop over all samples AtULong posOffset = 0; size_t totalNumPoints = 0; size_t totalNumPositions = 0; for(size_t sampleIndex = 0; sampleIndex < minNumSamples; ++sampleIndex) { SampleInfo sampleInfo = getSampleInfo( samples[sampleIndex], typedObject.getSchema().getTimeSampling(), typedObject.getSchema().getNumSamples() ); // get the floor sample Alembic::AbcGeom::ICurvesSchema::Sample sample; typedObject.getSchema().get(sample,sampleInfo.floorIndex); // access the num points Alembic::Abc::Int32ArraySamplePtr abcNumPoints = sample.getCurvesNumVertices(); // take care of the topology if(sampleIndex == 0) { // hard coded pixel width, basis and mode AiNodeSetFlt(shapeNode, "min_pixel_width", 0.25f); AiNodeSetStr(shapeNode, "basis", "catmull-rom"); AiNodeSetStr(shapeNode, "mode", ud->gCurvesMode.c_str()); // setup the num_points AtArray * numPoints = AiArrayAllocate((AtInt)abcNumPoints->size(),1,AI_TYPE_UINT); for(size_t i=0;i<abcNumPoints->size();i++) { totalNumPoints += abcNumPoints->get()[i]; totalNumPositions += abcNumPoints->get()[i] + 2; AiArraySetUInt(numPoints,(AtULong)i,(AtUInt)(abcNumPoints->get()[i]+2)); } AiNodeSetArray(shapeNode,"num_points",numPoints); // check if we have a radius Alembic::Abc::IFloatArrayProperty propRadius; if( getArbGeomParamPropertyAlembic( typedObject, "radius", propRadius ) ) { Alembic::Abc::FloatArraySamplePtr abcRadius = propRadius.getValue(sampleInfo.floorIndex); AtArray * radius = AiArrayAllocate((AtInt)abcRadius->size(),1,AI_TYPE_FLOAT); for(size_t i=0; i < abcRadius->size(); ++i) AiArraySetFlt(radius,(AtULong)i,abcRadius->get()[i]); AiNodeSetArray(shapeNode,"radius",radius); } // check if we have uvs Alembic::AbcGeom::IV2fGeomParam uvsParam = typedObject.getSchema().getUVsParam(); if(uvsParam.valid()) { Alembic::Abc::V2fArraySamplePtr abcUvs = uvsParam.getExpandedValue(sampleInfo.floorIndex).getVals(); if(AiNodeDeclare(shapeNode, "Texture_Projection", "uniform POINT2")) { AtArray* uvs = AiArrayAllocate((AtInt)abcUvs->size(), 1, AI_TYPE_POINT2); AtPoint2 uv; for(size_t i=0; i<abcUvs->size(); i++) { uv.x = abcUvs->get()[i].x; uv.y = abcUvs->get()[i].y; AiArraySetPnt2(uvs, (AtULong)i, uv); } AiNodeSetArray(shapeNode, "Texture_Projection", uvs); } } // check if we have colors Alembic::Abc::IC4fArrayProperty propColor; if( getArbGeomParamPropertyAlembic( typedObject, "color", propColor ) ) { Alembic::Abc::C4fArraySamplePtr abcColors = propColor.getValue(sampleInfo.floorIndex); AtBoolean result = false; if(abcColors->size() == 1) result = AiNodeDeclare(shapeNode, "Color", "constant RGBA"); else if(abcColors->size() == abcNumPoints->size()) result = AiNodeDeclare(shapeNode, "Color", "uniform RGBA"); else result = AiNodeDeclare(shapeNode, "Color", "varying RGBA"); if(result) { AtArray * colors = AiArrayAllocate((AtInt)abcColors->size(), 1, AI_TYPE_RGBA); AtRGBA color; for(size_t i=0; i<abcColors->size(); ++i) { color.r = abcColors->get()[i].r; color.g = abcColors->get()[i].g; color.b = abcColors->get()[i].b; color.a = abcColors->get()[i].a; AiArraySetRGBA(colors, (AtULong)i, color); } AiNodeSetArray(shapeNode, "Color", colors); } } } // access the positions Alembic::Abc::P3fArraySamplePtr abcPos = sample.getPositions(); if(pos == NULL) pos = AiArrayAllocate((AtInt)(totalNumPositions * 3),(AtInt)minNumSamples,AI_TYPE_FLOAT); // if we have to interpolate bool done = false; if(sampleInfo.alpha > sampleTolerance) { Alembic::AbcGeom::ICurvesSchema::Sample sample2; typedObject.getSchema().get(sample2,sampleInfo.ceilIndex); Alembic::Abc::P3fArraySamplePtr abcPos2 = sample2.getPositions(); float alpha = (float)sampleInfo.alpha; float ialpha = 1.0f - alpha; size_t offset = 0; if(abcPos2->size() == abcPos->size()) { for(size_t i=0; i<abcNumPoints->size(); ++i) { // add the first and last point manually (catmull clark) for(size_t j=0; j<abcNumPoints->get()[i]; ++j) { AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].x * ialpha + abcPos2->get()[offset].x * alpha); AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].y * ialpha + abcPos2->get()[offset].y * alpha); AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].z * ialpha + abcPos2->get()[offset].z * alpha); if(j==0 || j == abcNumPoints->get()[i]-1) { AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].x * ialpha + abcPos2->get()[offset].x * alpha); AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].y * ialpha + abcPos2->get()[offset].y * alpha); AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].z * ialpha + abcPos2->get()[offset].z * alpha); } ++offset; } } done = true; } else { Alembic::Abc::P3fArraySamplePtr abcVel = sample.getPositions(); if(abcVel) { if(abcVel->size() == abcPos->size()) { for(size_t i=0; i<abcNumPoints->size(); ++i) { // add the first and last point manually (catmull clark) for(size_t j=0; j<abcNumPoints->get()[i]; ++j) { AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].x + abcVel->get()[offset].x * alpha); AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].y + abcVel->get()[offset].y * alpha); AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].z + abcVel->get()[offset].z * alpha); if(j==0 || j == abcNumPoints->get()[i]-1) { AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].x + abcVel->get()[offset].x * alpha); AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].y + abcVel->get()[offset].y * alpha); AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].z + abcVel->get()[offset].z * alpha); } ++offset; } } done = true; } } } } if(!done) { size_t offset = 0; for(size_t i=0; i<abcNumPoints->size(); ++i) { // add the first and last point manually (catmull clark) for(size_t j=0; j<abcNumPoints->get()[i]; ++j) { AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].x); AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].y); AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].z); if(j==0 || j == abcNumPoints->get()[i]-1) { AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].x); AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].y); AiArraySetFlt(pos,posOffset++,abcPos->get()[offset].z); } ++offset; } } } } AiNodeSetArray(shapeNode, "points", pos); return shapeNode; }