void AlembicImport_FillInCamera(alembic_fillcamera_options& options) { ESS_CPP_EXCEPTION_REPORTING_START ESS_LOG_INFO("AlembicImport_FillInCamera"); if (options.pCameraObj == NULL || !AbcG::ICamera::matches((*options.pIObj).getMetaData())) { return; } AbcG::ICamera objCamera = AbcG::ICamera(*options.pIObj, Abc::kWrapExisting); if (!objCamera.valid()) { return; } double sampleTime = GetSecondsFromTimeValue(options.dTicks); SampleInfo sampleInfo = getSampleInfo(sampleTime, objCamera.getSchema().getTimeSampling(), objCamera.getSchema().getNumSamples()); AbcG::CameraSample sample; objCamera.getSchema().get(sample, sampleInfo.floorIndex); // Extract the camera values from the sample // double focalLength = sample.getFocalLength(); // double fov = sample.getHorizontalAperture(); // double nearClipping = sample.getNearClippingPlane(); // double farClipping = sample.getFarClippingPlane(); // Blend the camera values, if necessary // if (sampleInfo.alpha != 0.0) //{ // objCamera.getSchema().get(sample, sampleInfo.ceilIndex); // focalLength = (1.0 - sampleInfo.alpha) * focalLength + sampleInfo.alpha // * sample.getFocalLength(); // fov = (1.0 - sampleInfo.alpha) * fov + sampleInfo.alpha * // sample.getHorizontalAperture(); // nearClipping = (1.0 - sampleInfo.alpha) * nearClipping + // sampleInfo.alpha * sample.getNearClippingPlane(); // farClipping = (1.0 - sampleInfo.alpha) * farClipping + sampleInfo.alpha // * sample.getFarClippingPlane(); //} // options.pCameraObj->SetTDist(options.dTicks, // static_cast<float>(focalLength)); // options.pCameraObj->SetFOVType(0); // Width FoV = 0 // options.pCameraObj->SetFOV(options.dTicks, static_cast<float>(fov)); // options.pCameraObj->SetClipDist(options.dTicks, CAM_HITHER_CLIP, // static_cast<float>(nearClipping)); // options.pCameraObj->SetClipDist(options.dTicks, CAM_YON_CLIP, // static_cast<float>(farClipping)); options.pCameraObj->SetManualClip(TRUE); ESS_CPP_EXCEPTION_REPORTING_END }
void AlembicImport_FillInVis_Internal(alembic_fillvis_options &options) { if (!options.pIObj->valid()) { options.bVisibility = options.bOldVisibility; return; } AbcG::IVisibilityProperty visibilityProperty = getAbcVisibilityProperty(*options.pIObj); if (!visibilityProperty.valid()) { options.bVisibility = options.bOldVisibility; return; } double sampleTime = GetSecondsFromTimeValue(options.dTicks); SampleInfo sampleInfo = getSampleInfo(sampleTime, getTimeSamplingFromObject(*options.pIObj), visibilityProperty.getNumSamples()); boost::int8_t rawVisibilityValue = visibilityProperty.getValue(sampleInfo.floorIndex); AbcG::ObjectVisibility visibilityValue = AbcG::ObjectVisibility(rawVisibilityValue); switch (visibilityValue) { case AbcG::kVisibilityVisible: { options.bVisibility = true; break; } case AbcG::kVisibilityHidden: { options.bVisibility = false; break; } default: { options.bVisibility = options.bOldVisibility; break; } } }
AtNode *createInstanceNode(nodeData &nodata, userData * ud, int i) { Alembic::AbcGeom::IPoints typedObject(ud->gIObjects[i].abc, Alembic::Abc::kWrapExisting); instanceCloudInfo * info = ud->gIObjects[i].instanceCloud; // check that we have the masternode size_t id = (size_t)ud->gIObjects[i].ID; size_t instanceID = (size_t)ud->gIObjects[i].instanceID; if(instanceID >= info->groupInfos.size()) { AiMsgError("[ExocortexAlembicArnold] Instance '%s.%d' has an invalid instanceID . Aborting.",ud->gIObjects[i].abc.getFullName().c_str(),(int)id); return NULL; } size_t groupID = (size_t)ud->gIObjects[i].instanceGroupID; if(groupID >= info->groupInfos[instanceID].identifiers.size()) { AiMsgError("[ExocortexAlembicArnold] Instance '%s.%d' has an invalid instanceGroupID. Aborting.",ud->gIObjects[i].abc.getFullName().c_str(),(int)id); return NULL; } instanceGroupInfo * group = &info->groupInfos[instanceID]; // get the right centroidTime float centroidTime = ud->gCentroidTime; if(info->time.size() > 0) { centroidTime = info->time[0]->get()[id < info->time[0]->size() ? id : info->time[0]->size() - 1]; if(info->time.size() > 1) centroidTime = (1.0f - info->timeAlpha) * centroidTime + info->timeAlpha * info->time[1]->get()[id < info->time[1]->size() ? id : info->time[1]->size() - 1]; centroidTime = roundCentroid(centroidTime); } std::map<float,AtNode*>::iterator it = group->nodes[groupID].find(centroidTime); if(it == group->nodes[groupID].end()) { AiMsgError("[ExocortexAlembicArnold] Cannot find masterNode '%s' for centroidTime '%f'. Aborting.",group->identifiers[groupID].c_str(),centroidTime); return NULL; } AtNode *usedMasterNode = it->second; AtNode *shapeNode = AiNode("ginstance"); // setup name, id and the master node AiNodeSetStr(shapeNode, "name", getNameFromIdentifier(ud->gIObjects[i].abc.getFullName(),ud->gIObjects[i].ID,(long)groupID).c_str()); AiNodeSetInt(shapeNode, "id", ud->gIObjects[i].instanceID); AiNodeSetPtr(shapeNode, "node", usedMasterNode); // declare color on the ginstance if(info->color.size() > 0 && AiNodeDeclare(shapeNode, "Color", "constant RGBA")) { Alembic::Abc::C4f color = info->color[0]->get()[id < info->color[0]->size() ? id : info->color[0]->size() - 1]; AiNodeSetRGBA(shapeNode, "Color", color.r, color.g, color.b, color.a); } // now let's take care of the transform AtArray * matrices = AiArrayAllocate(1,(AtInt)ud->gMbKeys.size(),AI_TYPE_MATRIX); for(size_t j=0;j<ud->gMbKeys.size(); ++j) { SampleInfo sampleInfo = getSampleInfo( ud->gMbKeys[j], typedObject.getSchema().getTimeSampling(), typedObject.getSchema().getNumSamples() ); Alembic::Abc::M44f matrixAbc; matrixAbc.makeIdentity(); const size_t floorIndex = j << 1; const size_t ceilIndex = floorIndex + 1; // apply translation if(info->pos[floorIndex]->size() == info->pos[ceilIndex]->size()) { matrixAbc.setTranslation(float(1.0 - sampleInfo.alpha) * info->pos[floorIndex]->get()[id < info->pos[floorIndex]->size() ? id : info->pos[floorIndex]->size() - 1] + float(sampleInfo.alpha) * info->pos[ceilIndex]->get()[id < info->pos[ceilIndex]->size() ? id : info->pos[ceilIndex]->size() - 1]); } else { const float timeAlpha = getTimeOffsetFromObject( typedObject, sampleInfo ); matrixAbc.setTranslation(info->pos[floorIndex]->get()[id < info->pos[floorIndex]->size() ? id : info->pos[floorIndex]->size() - 1] + info->vel[floorIndex]->get()[id < info->vel[floorIndex]->size() ? id : info->vel[floorIndex]->size() - 1] * timeAlpha); } // now take care of rotation if(info->rot.size() == ud->gMbKeys.size()) { Alembic::Abc::Quatf rotAbc = info->rot[j]->get()[id < info->rot[j]->size() ? id : info->rot[j]->size() - 1]; if(info->ang.size() == ud->gMbKeys.size() && sampleInfo.alpha > 0.0) { Alembic::Abc::Quatf angAbc = info->ang[j]->get()[id < info->ang[j]->size() ? id : info->ang[j]->size() -1] * (float)sampleInfo.alpha; if(angAbc.axis().length2() != 0.0f && angAbc.r != 0.0f) { rotAbc = angAbc * rotAbc; rotAbc.normalize(); } } Alembic::Abc::M44f matrixAbcRot; matrixAbcRot.setAxisAngle(rotAbc.axis(),rotAbc.angle()); matrixAbc = matrixAbcRot * matrixAbc; } // and finally scaling if(info->scale.size() == ud->gMbKeys.size() * 2) { const Alembic::Abc::V3f scalingAbc = info->scale[floorIndex]->get()[id < info->scale[floorIndex]->size() ? id : info->scale[floorIndex]->size() - 1] * info->width[floorIndex]->get()[id < info->width[floorIndex]->size() ? id : info->width[floorIndex]->size() - 1] * float(1.0 - sampleInfo.alpha) + info->scale[ceilIndex]->get()[id < info->scale[ceilIndex]->size() ? id : info->scale[ceilIndex]->size() - 1] * info->width[ceilIndex]->get()[id < info->width[ceilIndex]->size() ? id : info->width[ceilIndex]->size() - 1] * float(sampleInfo.alpha); matrixAbc.scale(scalingAbc); } else { const float width = info->width[floorIndex]->get()[id < info->width[floorIndex]->size() ? id : info->width[floorIndex]->size() - 1] * float(1.0 - sampleInfo.alpha) + info->width[ceilIndex]->get()[id < info->width[ceilIndex]->size() ? id : info->width[ceilIndex]->size() - 1] * float(sampleInfo.alpha); matrixAbc.scale(Alembic::Abc::V3f(width,width,width)); } // if we have offset matrices if(group->parents.size() > groupID && group->matrices.size() > groupID) { if(group->objects[groupID].valid() && group->parents[groupID].valid()) { // we have a matrix map and a parent. // now we need to check if we already exported the matrices std::map<float,std::vector<Alembic::Abc::M44f> >::iterator it; std::vector<Alembic::Abc::M44f> offsets; it = group->matrices[groupID].find(centroidTime); if(it == group->matrices[groupID].end()) { std::vector<float> samples(ud->gMbKeys.size()); offsets.resize(ud->gMbKeys.size()); for(AtInt sampleIndex=0;sampleIndex<(AtInt)ud->gMbKeys.size(); ++sampleIndex) { offsets[sampleIndex].makeIdentity(); // centralize the time once more samples[sampleIndex] = centroidTime + ud->gMbKeys[sampleIndex] - ud->gCentroidTime; } // if the transform differs, we need to compute the offset matrices // get the parent, which should be a transform Alembic::Abc::IObject parent = group->parents[groupID]; Alembic::Abc::IObject xform = group->objects[groupID].getParent(); while(Alembic::AbcGeom::IXform::matches(xform.getMetaData()) && xform.getFullName() != parent.getFullName()) { // cast to a xform Alembic::AbcGeom::IXform parentXform(xform,Alembic::Abc::kWrapExisting); if(parentXform.getSchema().getNumSamples() == 0) break; // loop over all samples for(size_t sampleIndex=0;sampleIndex<ud->gMbKeys.size(); ++sampleIndex) { SampleInfo sampleInfo = getSampleInfo( samples[sampleIndex], parentXform.getSchema().getTimeSampling(), parentXform.getSchema().getNumSamples() ); // get the data and blend it if necessary Alembic::AbcGeom::XformSample sample; parentXform.getSchema().get(sample,sampleInfo.floorIndex); Alembic::Abc::M44f abcMatrix; Alembic::Abc::M44d abcMatrixd = sample.getMatrix(); for(int x=0;x<4;x++) for(int y=0;y<4;y++) abcMatrix[x][y] = (float)abcMatrixd[x][y]; if(sampleInfo.alpha >= sampleTolerance) { parentXform.getSchema().get(sample,sampleInfo.ceilIndex); Alembic::Abc::M44d ceilAbcMatrixd = sample.getMatrix(); Alembic::Abc::M44f ceilAbcMatrix; for(int x=0;x<4;x++) for(int y=0;y<4;y++) ceilAbcMatrix[x][y] = (float)ceilAbcMatrixd[x][y]; abcMatrix = float(1.0 - sampleInfo.alpha) * abcMatrix + float(sampleInfo.alpha) * ceilAbcMatrix; } offsets[sampleIndex] = abcMatrix * offsets[sampleIndex]; } // go upwards xform = xform.getParent(); } group->matrices[groupID].insert(std::pair<float,std::vector<Alembic::Abc::M44f> >(centroidTime,offsets)); } else offsets = it->second; // this means we have the right amount of matrices to blend against if(offsets.size() > j) matrixAbc = offsets[j] * matrixAbc; } } // store it to the array AiArraySetMtx(matrices,(AtULong)j,matrixAbc.x); } AiNodeSetArray(shapeNode,"matrix",matrices); AiNodeSetBool(shapeNode, "inherit_xform", FALSE); return shapeNode; }
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; }
MStatus AlembicCurvesDeformNode::deform(MDataBlock &dataBlock, MItGeometry &iter, const MMatrix &localToWorld, unsigned int geomIndex) { // get the envelope data float env = dataBlock.inputValue(envelope).asFloat(); if (env == 0.0f) { // deformer turned off return MStatus::kSuccess; } // 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(); // 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; } AbcG::ICurves obj(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; } { ESS_PROFILE_SCOPE("AlembicCurvesDeformNode::deform readProps"); Alembic::Abc::ICompoundProperty arbProp = mSchema.getArbGeomParams(); Alembic::Abc::ICompoundProperty userProp = mSchema.getUserProperties(); readProps(inputTime, arbProp, dataBlock, thisMObject()); readProps(inputTime, userProp, dataBlock, thisMObject()); // Set all plugs as clean // Even if one of them failed to get set, // trying again in this frame isn't going to help for (unsigned int i = 0; i < mGeomParamPlugs.length(); i++) { dataBlock.outputValue(mGeomParamPlugs[i]).setClean(); } for (unsigned int i = 0; i < mUserAttrPlugs.length(); i++) { dataBlock.outputValue(mUserAttrPlugs[i]).setClean(); } } // get the sample SampleInfo sampleInfo = getSampleInfo(inputTime, mSchema.getTimeSampling(), mSchema.getNumSamples()); // check if we have to do this at all if (mLastSampleInfo.floorIndex == sampleInfo.floorIndex && mLastSampleInfo.ceilIndex == sampleInfo.ceilIndex) { return MStatus::kSuccess; } mLastSampleInfo = sampleInfo; // access the camera values AbcG::ICurvesSchema::Sample sample; AbcG::ICurvesSchema::Sample sample2; mSchema.get(sample, sampleInfo.floorIndex); if (sampleInfo.alpha != 0.0) { mSchema.get(sample2, sampleInfo.ceilIndex); } Abc::P3fArraySamplePtr samplePos = sample.getPositions(); Abc::P3fArraySamplePtr samplePos2; if (sampleInfo.alpha != 0.0) { samplePos2 = sample2.getPositions(); } // iteration should not be necessary. the iteration is only // required if the same mesh is attached to the same deformer // several times float blend = (float)sampleInfo.alpha; float iblend = 1.0f - blend; unsigned int index = 0; for (iter.reset(); !iter.isDone(); iter.next()) { index = iter.index(); // MFloatPoint pt = iter.position(); MPoint pt = iter.position(); MPoint abcPos = pt; float weight = weightValue(dataBlock, geomIndex, index) * env; if (weight == 0.0f) { continue; } float iweight = 1.0f - weight; if (index >= samplePos->size()) { continue; } bool done = false; if (sampleInfo.alpha != 0.0) { if (samplePos2->size() == samplePos->size()) { abcPos.x = iweight * pt.x + weight * (samplePos->get()[index].x * iblend + samplePos2->get()[index].x * blend); abcPos.y = iweight * pt.y + weight * (samplePos->get()[index].y * iblend + samplePos2->get()[index].y * blend); abcPos.z = iweight * pt.z + weight * (samplePos->get()[index].z * iblend + samplePos2->get()[index].z * blend); done = true; } } if (!done) { abcPos.x = iweight * pt.x + weight * samplePos->get()[index].x; abcPos.y = iweight * pt.y + weight * samplePos->get()[index].y; abcPos.z = iweight * pt.z + weight * samplePos->get()[index].z; } iter.setPosition(abcPos); } return MStatus::kSuccess; }
MStatus AlembicCurvesNode::compute(const MPlug &plug, MDataBlock &dataBlock) { ESS_PROFILE_SCOPE("AlembicCurvesNode::compute"); MStatus status; // update the frame number to be imported const double inputTime = dataBlock.inputValue(mTimeAttr).asTime().as(MTime::kSeconds); MString &fileName = dataBlock.inputValue(mFileNameAttr).asString(); MString &identifier = dataBlock.inputValue(mIdentifierAttr).asString(); // 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; } AbcG::ICurves obj(iObj, Abc::kWrapExisting); if (!obj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' in archive '" + mFileName + "' is not a Curves."); return MStatus::kFailure; } mObj = obj; mSchema = obj.getSchema(); mCurvesData = MObject::kNullObj; } if (!mSchema.valid()) { return MStatus::kFailure; } { ESS_PROFILE_SCOPE("AlembicCurvesNode::compute readProps"); Alembic::Abc::ICompoundProperty arbProp = mSchema.getArbGeomParams(); Alembic::Abc::ICompoundProperty userProp = mSchema.getUserProperties(); readProps(inputTime, arbProp, dataBlock, thisMObject()); readProps(inputTime, userProp, dataBlock, thisMObject()); // Set all plugs as clean // Even if one of them failed to get set, // trying again in this frame isn't going to help for (unsigned int i = 0; i < mGeomParamPlugs.length(); i++) { dataBlock.outputValue(mGeomParamPlugs[i]).setClean(); } for (unsigned int i = 0; i < mUserAttrPlugs.length(); i++) { dataBlock.outputValue(mUserAttrPlugs[i]).setClean(); } } // get the sample SampleInfo sampleInfo = getSampleInfo(inputTime, mSchema.getTimeSampling(), mSchema.getNumSamples()); // check if we have to do this at all if (!mCurvesData.isNull() && mLastSampleInfo.floorIndex == sampleInfo.floorIndex && mLastSampleInfo.ceilIndex == sampleInfo.ceilIndex) { return MStatus::kSuccess; } mLastSampleInfo = sampleInfo; const float blend = (float)sampleInfo.alpha; // access the camera values AbcG::ICurvesSchema::Sample sample; AbcG::ICurvesSchema::Sample sample2; mSchema.get(sample, sampleInfo.floorIndex); if (blend != 0.0f) { mSchema.get(sample2, sampleInfo.ceilIndex); } Abc::P3fArraySamplePtr samplePos = sample.getPositions(); Abc::P3fArraySamplePtr samplePos2 = sample2.getPositions(); Abc::Int32ArraySamplePtr nbVertices = sample.getCurvesNumVertices(); const bool applyBlending = (blend == 0.0f) ? false : (samplePos->size() == samplePos2->size()); Abc::FloatArraySamplePtr pKnotVec = getKnotVector(mObj); Abc::UInt16ArraySamplePtr pOrders = getCurveOrders(mObj); MArrayDataHandle arrh = dataBlock.outputArrayValue(mOutGeometryAttr); MArrayDataBuilder builder = arrh.builder(); // reference: // http://download.autodesk.com/us/maya/2010help/API/multi_curve_node_8cpp-example.html const int degree = (sample.getType() == AbcG::kCubic) ? 3 : 1; const bool closed = (sample.getWrap() == AbcG::kPeriodic); unsigned int pointOffset = 0; unsigned int knotOffset = 0; for (int ii = 0; ii < nbVertices->size(); ++ii) { const unsigned int nbCVs = (unsigned int)nbVertices->get()[ii]; const int ldegree = (pOrders) ? pOrders->get()[ii] : degree; const int nbSpans = (int)nbCVs - ldegree; MDoubleArray knots; if (pKnotVec) { const unsigned int nb_knot = nbCVs + ldegree - 1; for (unsigned int i = 0; i < nb_knot; ++i) { knots.append(pKnotVec->get()[knotOffset + i]); } knotOffset += nb_knot; } else { for (int span = 0; span <= nbSpans; ++span) { knots.append(double(span)); if (span == 0 || span == nbSpans) { for (int m = 1; m < degree; ++m) { knots.append(double(span)); } } } } MPointArray points; if (samplePos->size() > 0) { points.setLength((unsigned int)nbCVs); if (applyBlending) { for (unsigned int i = 0; i < nbCVs; ++i) { const Abc::P3fArraySample::value_type &vals1 = samplePos->get()[pointOffset + i]; const Abc::P3fArraySample::value_type &vals2 = samplePos2->get()[pointOffset + i]; MPoint &pt = points[i]; pt.x = vals1.x + (vals2.x - vals1.x) * blend; pt.y = vals1.y + (vals2.y - vals1.y) * blend; pt.z = vals1.z + (vals2.z - vals1.z) * blend; } } else { for (unsigned int i = 0; i < nbCVs; ++i) { const Abc::P3fArraySample::value_type &vals = samplePos->get()[pointOffset + i]; MPoint &pt = points[i]; pt.x = vals.x; pt.y = vals.y; pt.z = vals.z; } } pointOffset += nbCVs; } // create a subd either with or without uvs MObject mmCurvesData = MFnNurbsCurveData().create(); if (ldegree == 1 || ldegree == 3) mCurves.create(points, knots, ldegree, closed ? MFnNurbsCurve::kClosed : MFnNurbsCurve::kOpen, false, false, mmCurvesData); builder.addElement(ii).set(mmCurvesData); } arrh.set(builder); arrh.setAllClean(); return MStatus::kSuccess; }
void AlembicFloatController::GetValueLocalTime(TimeValue t, void* ptr, Interval& valid, GetSetMethod method) { ESS_CPP_EXCEPTION_REPORTING_START Interval interval = FOREVER; MCHAR const* strPath = NULL; this->pblock->GetValue(AlembicFloatController::ID_PATH, t, strPath, interval); MCHAR const* strIdentifier = NULL; this->pblock->GetValue(AlembicFloatController::ID_IDENTIFIER, t, strIdentifier, interval); MCHAR const* strCategory = NULL; this->pblock->GetValue(AlembicFloatController::ID_CATEGORY, t, strCategory, interval); MCHAR const* strProperty = NULL; this->pblock->GetValue(AlembicFloatController::ID_PROPERTY, t, strProperty, interval); float fTime; this->pblock->GetValue(AlembicFloatController::ID_TIME, t, fTime, interval); BOOL bMuted; this->pblock->GetValue(AlembicFloatController::ID_MUTED, t, bMuted, interval); extern bool g_bVerboseLogging; if (g_bVerboseLogging) { ESS_LOG_WARNING("Param block at tick " << t << "-----------------------"); ESS_LOG_WARNING("PATH: " << strPath); ESS_LOG_WARNING("IDENTIFIER: " << strIdentifier); ESS_LOG_WARNING("PROPERTY: " << strProperty); ESS_LOG_WARNING("TIME: " << fTime); ESS_LOG_WARNING("MUTED: " << bMuted); ESS_LOG_WARNING("Param block end -------------"); } const float fDefaultVal = -1.0; std::string szPath = EC_MCHAR_to_UTF8(strPath); std::string szIdentifier = EC_MCHAR_to_UTF8(strIdentifier); std::string szProperty = EC_MCHAR_to_UTF8(strProperty); std::string szCategory = EC_MCHAR_to_UTF8(strCategory); if (szCategory.empty()) { // default to standard properties for backwards // compatibility szCategory = std::string("standardProperties"); } if (!strProperty || !strPath || !strIdentifier /*|| !strCategory*/) { return setController("1", szProperty, valid, interval, method, ptr, fDefaultVal); } if (bMuted) { return setController("2", szProperty, valid, interval, method, ptr, fDefaultVal); } // if( szCategory.size() == 0 ) { // ESS_LOG_ERROR( "No category specified." ); // return setController("3a", szProperty, valid, interval, method, ptr, // fDefaultVal); //} if (szProperty.size() == 0) { ESS_LOG_ERROR("No property specified."); return setController("3b", szProperty, valid, interval, method, ptr, fDefaultVal); } AbcG::IObject iObj = getObjectFromArchive(szPath, szIdentifier); if (!iObj.valid()) { return setController("4", szProperty, valid, interval, method, ptr, fDefaultVal); } TimeValue dTicks = GetTimeValueFromSeconds(fTime); double sampleTime = GetSecondsFromTimeValue(dTicks); float fSampleVal = fDefaultVal; if (boost::iequals(szCategory, "standardProperties")) { if (Alembic::AbcGeom::ICamera::matches( iObj.getMetaData())) { // standard camera properties Alembic::AbcGeom::ICamera objCamera = Alembic::AbcGeom::ICamera(iObj, Alembic::Abc::kWrapExisting); SampleInfo sampleInfo = getSampleInfo(sampleTime, objCamera.getSchema().getTimeSampling(), objCamera.getSchema().getNumSamples()); Alembic::AbcGeom::CameraSample sample; objCamera.getSchema().get(sample, sampleInfo.floorIndex); double sampleVal; if (!getCameraSampleVal(objCamera, sampleInfo, sample, szProperty, sampleVal)) { return setController("5", szProperty, valid, interval, method, ptr, fDefaultVal); } // Blend the camera values, if necessary if (sampleInfo.alpha != 0.0) { objCamera.getSchema().get(sample, sampleInfo.ceilIndex); double sampleVal2 = 0.0; if (getCameraSampleVal(objCamera, sampleInfo, sample, szProperty, sampleVal2)) { sampleVal = (1.0 - sampleInfo.alpha) * sampleVal + sampleInfo.alpha * sampleVal2; } } fSampleVal = (float)sampleVal; } else if (Alembic::AbcGeom::ILight::matches( iObj.getMetaData())) { // ILight material properties ESS_PROFILE_SCOPE( "AlembicFloatController::GetValueLocalTime - read ILight shader " "parameter"); Alembic::AbcGeom::ILight objLight = Alembic::AbcGeom::ILight(iObj, Alembic::Abc::kWrapExisting); SampleInfo sampleInfo = getSampleInfo(sampleTime, objLight.getSchema().getTimeSampling(), objLight.getSchema().getNumSamples()); AbcM::IMaterialSchema matSchema = getMatSchema(objLight); std::string strProp = szProperty; std::vector<std::string> parts; boost::split(parts, strProp, boost::is_any_of(".")); if (parts.size() == 3) { const std::string& target = parts[0]; const std::string& type = parts[1]; const std::string& prop = parts[2]; Abc::IFloatProperty fProp = readShaderScalerProp<Abc::IFloatProperty>( matSchema, target, type, prop); if (fProp.valid()) { fProp.get(fSampleVal, sampleInfo.floorIndex); } else { ESS_LOG_WARNING("Float Controller Error: could find shader parameter " << strProp); } } else if (parts.size() == 5) { const std::string& target = parts[0]; const std::string& type = parts[1]; const std::string& prop = parts[2]; const std::string& propInterp = parts[3]; const std::string& propComp = parts[4]; // ESS_LOG_WARNING("propInterp: "<<propInterp); if (propInterp == "rgb") { Abc::IC3fProperty fProp = readShaderScalerProp<Abc::IC3fProperty>( matSchema, target, type, prop); if (fProp.valid()) { Abc::C3f v3f; fProp.get(v3f, sampleInfo.floorIndex); if (propComp == "x") { fSampleVal = v3f.x; } else if (propComp == "y") { fSampleVal = v3f.y; } else if (propComp == "z") { fSampleVal = v3f.z; } else { ESS_LOG_WARNING( "Float Controller Error: invalid component: " << propComp); } } else { ESS_LOG_WARNING( "Float Controller Error: could find shader parameter " << strProp); } } else { ESS_LOG_WARNING( "Float Controller Error: unrecognized parameter interpretation: " << propInterp); } } else { ESS_LOG_WARNING( "Float Controller Error: could not parse property field: " << strProperty); } } } else if (boost::iequals(szCategory, "userProperties")) { // AbcA::TimeSamplingPtr timeSampling = obj.getSchema().getTimeSampling(); // int nSamples = (int)obj.getSchema().getNumSamples(); AbcA::TimeSamplingPtr timeSampling; int nSamples = 0; Abc::ICompoundProperty propk = AbcNodeUtils::getUserProperties(iObj, timeSampling, nSamples); if (propk.valid()) { SampleInfo sampleInfo = getSampleInfo(sampleTime, timeSampling, nSamples); std::vector<std::string> parts; boost::split(parts, szProperty, boost::is_any_of(".")); if (parts.size() == 1) { Abc::IFloatProperty fProp = readScalarProperty<Abc::IFloatProperty>(propk, szProperty); if (fProp.valid()) { fProp.get(fSampleVal, sampleInfo.floorIndex); } else { Abc::IInt32Property intProp = readScalarProperty<Abc::IInt32Property>(propk, szProperty); if (intProp.valid()) { int intVal; intProp.get(intVal, sampleInfo.floorIndex); fSampleVal = (float)intVal; } else { ESS_LOG_WARNING( "Float Controller Error: could not read user property " << szProperty); } } } else if (parts.size() == 3) { const std::string& prop = parts[0]; const std::string& propInterp = parts[1]; const std::string& propComp = parts[2]; // ESS_LOG_WARNING("interpretation: "<<propInterp); if (propInterp == "rgb") { fSampleVal = readScalarPropertyExt3<Abc::IC3fProperty, Abc::C3f>( propk, sampleInfo, prop, propComp); } else if (propInterp == "vector") { fSampleVal = readScalarPropertyExt3<Abc::IV3fProperty, Abc::V3f>( propk, sampleInfo, prop, propComp); } else { ESS_LOG_WARNING( "Float Controller Error: unrecognized parameter interpretation: " << propInterp); } } } } // else if( boost::iequals(szCategory, "arbGeomParams") ){ //} return setController("6", szProperty, valid, interval, method, ptr, fSampleVal); ESS_CPP_EXCEPTION_REPORTING_END }
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; }