// once normals are supported in the polyMesh schema, polyMesh will look // different than readSubD void readPoly(double iFrame, MFnMesh & ioMesh, MObject & iParent, Alembic::AbcGeom::IPolyMesh & iNode, bool iInitialized) { Alembic::AbcGeom::IPolyMeshSchema schema = iNode.getSchema(); Alembic::AbcGeom::MeshTopologyVariance ttype = schema.getTopologyVariance(); int64_t index, ceilIndex; double alpha = getWeightAndIndex(iFrame, schema.getTimeSampling(), schema.getNumSamples(), index, ceilIndex); MFloatPointArray pointArray; Alembic::Abc::V3fArraySamplePtr ceilPoints; // we can just read the points if (ttype != Alembic::AbcGeom::kHeterogenousTopology && iInitialized) { Alembic::Abc::V3fArraySamplePtr points = schema.getPositions().getValue( Alembic::Abc::ISampleSelector(index) ); if (alpha != 0.0) { ceilPoints = schema.getPositions().getValue( Alembic::Abc::ISampleSelector(ceilIndex) ); } fillPoints(pointArray, points, ceilPoints, alpha); ioMesh.setPoints(pointArray, MSpace::kObject); if (schema.getNormals().getNumSamples() > 1) { setPolyNormals(iFrame, ioMesh, schema.getNormals()); } if (schema.getUVs().getNumSamples() > 1) { setUVs(iFrame, ioMesh, schema.getUVs()); } return; } // we need to read the topology Alembic::AbcGeom::IPolyMeshSchema::Sample samp; schema.get(samp, Alembic::Abc::ISampleSelector(index)); if (alpha != 0.0 && ttype != Alembic::AbcGeom::kHeterogenousTopology) { ceilPoints = schema.getPositions().getValue( Alembic::Abc::ISampleSelector(ceilIndex) ); } fillPoints(pointArray, samp.getPositions(), ceilPoints, alpha); fillTopology(ioMesh, iParent, pointArray, samp.getIndices(), samp.getCounts()); setPolyNormals(iFrame, ioMesh, schema.getNormals()); setUVs(iFrame, ioMesh, schema.getUVs()); }
void readSubD(double iFrame, MFnMesh & ioMesh, MObject & iParent, SubDAndColors & iNode, bool iInitialized) { Alembic::AbcGeom::ISubDSchema schema = iNode.mMesh.getSchema(); Alembic::AbcGeom::MeshTopologyVariance ttype = schema.getTopologyVariance(); Alembic::AbcCoreAbstract::index_t index, ceilIndex; double alpha = getWeightAndIndex(iFrame, schema.getTimeSampling(), schema.getNumSamples(), index, ceilIndex); MFloatPointArray pointArray; Alembic::Abc::P3fArraySamplePtr ceilPoints; // we can just read the points if (ttype != Alembic::AbcGeom::kHeterogenousTopology && iInitialized) { Alembic::Abc::P3fArraySamplePtr points = schema.getPositionsProperty( ).getValue(Alembic::Abc::ISampleSelector(index)); if (alpha != 0.0) { ceilPoints = schema.getPositionsProperty().getValue( Alembic::Abc::ISampleSelector(ceilIndex) ); } fillPoints(pointArray, points, ceilPoints, alpha); ioMesh.setPoints(pointArray, MSpace::kObject); if (schema.getUVsParam().getNumSamples() > 1) { setUVs(iFrame, ioMesh, schema.getUVsParam()); } setColors(iFrame, ioMesh, iNode.mC3s, iNode.mC4s, !iInitialized); return; } // we need to read the topology Alembic::AbcGeom::ISubDSchema::Sample samp; schema.get(samp, Alembic::Abc::ISampleSelector(index)); if (alpha != 0.0 && ttype != Alembic::AbcGeom::kHeterogenousTopology) { ceilPoints = schema.getPositionsProperty().getValue( Alembic::Abc::ISampleSelector(ceilIndex) ); } fillPoints(pointArray, samp.getPositions(), ceilPoints, alpha); fillTopology(ioMesh, iParent, pointArray, samp.getFaceIndices(), samp.getFaceCounts()); setUVs(iFrame, ioMesh, schema.getUVsParam()); setColors(iFrame, ioMesh, iNode.mC3s, iNode.mC4s, !iInitialized); }
MObject createSubD(double iFrame, SubDAndColors & iNode, MObject & iParent) { Alembic::AbcGeom::ISubDSchema schema = iNode.mMesh.getSchema(); Alembic::AbcCoreAbstract::index_t index, ceilIndex; getWeightAndIndex(iFrame, schema.getTimeSampling(), schema.getNumSamples(), index, ceilIndex); Alembic::AbcGeom::ISubDSchema::Sample samp; schema.get(samp, Alembic::Abc::ISampleSelector(index)); MString name(iNode.mMesh.getName().c_str()); MFnMesh fnMesh; MFloatPointArray pointArray; Alembic::Abc::P3fArraySamplePtr emptyPtr; fillPoints(pointArray, samp.getPositions(), emptyPtr, 0.0); fillTopology(fnMesh, iParent, pointArray, samp.getFaceIndices(), samp.getFaceCounts()); fnMesh.setName(iNode.mMesh.getName().c_str()); setInitialShadingGroup(fnMesh.partialPathName()); MObject obj = fnMesh.object(); setUVs(iFrame, fnMesh, schema.getUVsParam()); setColors(iFrame, fnMesh, iNode.mC3s, iNode.mC4s, true); // add the mFn-specific attributes to fnMesh node MFnNumericAttribute numAttr; MString attrName("SubDivisionMesh"); MObject attrObj = numAttr.create(attrName, attrName, MFnNumericData::kBoolean, 1); numAttr.setKeyable(true); numAttr.setHidden(false); fnMesh.addAttribute(attrObj, MFnDependencyNode::kLocalDynamicAttr); if (samp.getInterpolateBoundary() > 0) { attrName = MString("interpolateBoundary"); attrObj = numAttr.create(attrName, attrName, MFnNumericData::kBoolean, samp.getInterpolateBoundary()); numAttr.setKeyable(true); numAttr.setHidden(false); fnMesh.addAttribute(attrObj, MFnDependencyNode::kLocalDynamicAttr); } if (samp.getFaceVaryingInterpolateBoundary() > 0) { attrName = MString("faceVaryingInterpolateBoundary"); attrObj = numAttr.create(attrName, attrName, MFnNumericData::kBoolean, samp.getFaceVaryingInterpolateBoundary()); numAttr.setKeyable(true); numAttr.setHidden(false); fnMesh.addAttribute(attrObj, MFnDependencyNode::kLocalDynamicAttr); } if (samp.getFaceVaryingPropagateCorners() > 0) { attrName = MString("faceVaryingPropagateCorners"); attrObj = numAttr.create(attrName, attrName, MFnNumericData::kBoolean, samp.getFaceVaryingPropagateCorners()); numAttr.setKeyable(true); numAttr.setHidden(false); fnMesh.addAttribute(attrObj, MFnDependencyNode::kLocalDynamicAttr); } #if MAYA_API_VERSION >= 201100 Alembic::Abc::Int32ArraySamplePtr holes = samp.getHoles(); if (holes && !holes->size() == 0) { unsigned int numHoles = (unsigned int)holes->size(); MUintArray holeData(numHoles); for (unsigned int i = 0; i < numHoles; ++i) { holeData[i] = (*holes)[i]; } if (fnMesh.setInvisibleFaces(holeData) != MS::kSuccess) { MString warn = "Failed to set holes on: "; warn += iNode.mMesh.getName().c_str(); printWarning(warn); } } #endif Alembic::Abc::FloatArraySamplePtr creases = samp.getCreaseSharpnesses(); if (creases && !creases->size() == 0) { Alembic::Abc::Int32ArraySamplePtr indices = samp.getCreaseIndices(); Alembic::Abc::Int32ArraySamplePtr lengths = samp.getCreaseLengths(); std::size_t numLengths = lengths->size(); MUintArray edgeIds; MDoubleArray creaseData; std::size_t curIndex = 0; // curIndex incremented here to move on to the next crease length for (std::size_t i = 0; i < numLengths; ++i, ++curIndex) { std::size_t len = (*lengths)[i] - 1; float creaseSharpness = (*creases)[i]; // curIndex incremented here to go between all the edges that make // up a given length for (std::size_t j = 0; j < len; ++j, ++curIndex) { Alembic::Util::int32_t vertA = (*indices)[curIndex]; Alembic::Util::int32_t vertB = (*indices)[curIndex+1]; MItMeshVertex itv(obj); int prev; itv.setIndex(vertA, prev); MIntArray edges; itv.getConnectedEdges(edges); std::size_t numEdges = edges.length(); for (unsigned int k = 0; k < numEdges; ++k) { int oppVert = -1; itv.getOppositeVertex(oppVert, edges[k]); if (oppVert == vertB) { creaseData.append(creaseSharpness); edgeIds.append(edges[k]); break; } } } } if (fnMesh.setCreaseEdges(edgeIds, creaseData) != MS::kSuccess) { MString warn = "Failed to set creases on: "; warn += iNode.mMesh.getName().c_str(); printWarning(warn); } } Alembic::Abc::FloatArraySamplePtr corners = samp.getCornerSharpnesses(); if (corners && !corners->size() == 0) { Alembic::Abc::Int32ArraySamplePtr cornerVerts = samp.getCornerIndices(); unsigned int numCorners = static_cast<unsigned int>(corners->size()); MUintArray vertIds(numCorners); MDoubleArray cornerData(numCorners); for (unsigned int i = 0; i < numCorners; ++i) { cornerData[i] = (*corners)[i]; vertIds[i] = (*cornerVerts)[i]; } if (fnMesh.setCreaseVertices(vertIds, cornerData) != MS::kSuccess) { MString warn = "Failed to set corners on: "; warn += iNode.mMesh.getName().c_str(); printWarning(warn); } } return obj; }
MObject createPoly(double iFrame, PolyMeshAndColors & iNode, MObject & iParent) { Alembic::AbcGeom::IPolyMeshSchema schema = iNode.mMesh.getSchema(); MString name(iNode.mMesh.getName().c_str()); MObject obj; // add other properties if (!schema.isConstant()) { MFloatPointArray emptyPt; MIntArray emptyInt; MFnMesh fnMesh; obj = fnMesh.create(0, 0, emptyPt, emptyInt, emptyInt, iParent); fnMesh.setName(name); } else { Alembic::AbcCoreAbstract::index_t index, ceilIndex; double alpha = getWeightAndIndex(iFrame, schema.getTimeSampling(), schema.getNumSamples(), index, ceilIndex); Alembic::AbcGeom::IPolyMeshSchema::Sample samp; schema.get(samp, Alembic::Abc::ISampleSelector(index)); MFloatPointArray ptArray; Alembic::Abc::P3fArraySamplePtr ceilPoints; if (index != ceilIndex) { Alembic::AbcGeom::IPolyMeshSchema::Sample ceilSamp; schema.get(ceilSamp, Alembic::Abc::ISampleSelector(ceilIndex)); ceilPoints = ceilSamp.getPositions(); } fillPoints(ptArray, samp.getPositions(), ceilPoints, alpha); MFnMesh fnMesh; fillTopology(fnMesh, iParent, ptArray, samp.getFaceIndices(), samp.getFaceCounts()); fnMesh.setName(iNode.mMesh.getName().c_str()); setPolyNormals(iFrame, fnMesh, schema.getNormalsParam()); setUVs(iFrame, fnMesh, schema.getUVsParam()); obj = fnMesh.object(); } MFnMesh fnMesh(obj); MString pathName = fnMesh.partialPathName(); setInitialShadingGroup(pathName); setColors(iFrame, fnMesh, iNode.mC3s, iNode.mC4s, true); if ( !schema.getNormalsParam().valid() ) { MFnNumericAttribute attr; MString attrName("noNormals"); MObject attrObj = attr.create(attrName, attrName, MFnNumericData::kBoolean, true); attr.setKeyable(true); attr.setHidden(false); fnMesh.addAttribute(attrObj, MFnDependencyNode::kLocalDynamicAttr); } return obj; }
MObject createSubD(double iFrame, SubDAndFriends & iNode, MObject & iParent) { Alembic::AbcGeom::ISubDSchema schema = iNode.mMesh.getSchema(); Alembic::AbcCoreAbstract::index_t index, ceilIndex; getWeightAndIndex(iFrame, schema.getTimeSampling(), schema.getNumSamples(), index, ceilIndex); Alembic::AbcGeom::ISubDSchema::Sample samp; schema.get(samp, Alembic::Abc::ISampleSelector(index)); MString name(iNode.mMesh.getName().c_str()); MFnMesh fnMesh; MFloatPointArray pointArray; Alembic::Abc::P3fArraySamplePtr emptyPtr; fillPoints(pointArray, samp.getPositions(), emptyPtr, 0.0); fillTopology(fnMesh, iParent, pointArray, samp.getFaceIndices(), samp.getFaceCounts()); fnMesh.setName(iNode.mMesh.getName().c_str()); setInitialShadingGroup(fnMesh.partialPathName()); MObject obj = fnMesh.object(); setColorsAndUVs(iFrame, fnMesh, schema.getUVsParam(), iNode.mV2s, iNode.mC3s, iNode.mC4s, true); // add the mFn-specific attributes to fnMesh node MFnNumericAttribute numAttr; MString attrName("SubDivisionMesh"); MObject attrObj = numAttr.create(attrName, attrName, MFnNumericData::kBoolean, 1); numAttr.setKeyable(true); numAttr.setHidden(false); fnMesh.addAttribute(attrObj, MFnDependencyNode::kLocalDynamicAttr); if (samp.getInterpolateBoundary() > 0) { attrName = MString("interpolateBoundary"); attrObj = numAttr.create(attrName, attrName, MFnNumericData::kBoolean, samp.getInterpolateBoundary()); numAttr.setKeyable(true); numAttr.setHidden(false); fnMesh.addAttribute(attrObj, MFnDependencyNode::kLocalDynamicAttr); } if (samp.getFaceVaryingInterpolateBoundary() > 0) { attrName = MString("faceVaryingInterpolateBoundary"); attrObj = numAttr.create(attrName, attrName, MFnNumericData::kBoolean, samp.getFaceVaryingInterpolateBoundary()); numAttr.setKeyable(true); numAttr.setHidden(false); fnMesh.addAttribute(attrObj, MFnDependencyNode::kLocalDynamicAttr); } if (samp.getFaceVaryingPropagateCorners() > 0) { attrName = MString("faceVaryingPropagateCorners"); attrObj = numAttr.create(attrName, attrName, MFnNumericData::kBoolean, samp.getFaceVaryingPropagateCorners()); numAttr.setKeyable(true); numAttr.setHidden(false); fnMesh.addAttribute(attrObj, MFnDependencyNode::kLocalDynamicAttr); } fillCreasesCornersAndHoles(fnMesh, iNode, samp); return obj; }
MObject readNurbs(double iFrame, Alembic::AbcGeom::INuPatch & iNode, MObject & iObject) { MStatus status; MObject obj; Alembic::AbcGeom::INuPatchSchema schema = iNode.getSchema(); // no interpolation for now Alembic::AbcCoreAbstract::index_t index, ceilIndex; getWeightAndIndex(iFrame, schema.getTimeSampling(), schema.getNumSamples(), index, ceilIndex); Alembic::AbcGeom::INuPatchSchema::Sample samp; schema.get(samp, Alembic::Abc::ISampleSelector(index)); Alembic::Abc::P3fArraySamplePtr pos = samp.getPositions(); Alembic::Abc::FloatArraySamplePtr weights = samp.getPositionWeights(); MString surfaceName(iNode.getName().c_str()); unsigned int degreeU = samp.getUOrder() - 1; unsigned int degreeV = samp.getVOrder() - 1; unsigned int numCVInU = samp.getNumU(); unsigned int numCVInV = samp.getNumV(); // cv points unsigned int numCV = numCVInU*numCVInV; unsigned int curPos = 0; MPointArray controlVertices; controlVertices.setLength(numCV); for (unsigned int v = 0; v < numCVInV; ++v) { for (unsigned int u = 0; u < numCVInU; ++u, ++curPos) { unsigned int mayaIndex = u * numCVInV + (numCVInV - v - 1); MPoint pt((*pos)[curPos].x, (*pos)[curPos].y, (*pos)[curPos].z); if (weights) { pt.w = (*weights)[curPos]; } // go from u,v order to reversed v, u order controlVertices.set(pt, mayaIndex); } } // Nurbs form // Alemblic file does not record the form of nurb surface, we get the form // by checking the CV data. If the first degree number CV overlap the last // degree number CV, then the form is kPeriodic. If only the first CV overlaps // the last CV, then the form is kClosed. MFnNurbsSurface::Form formU = MFnNurbsSurface::kPeriodic; MFnNurbsSurface::Form formV = MFnNurbsSurface::kPeriodic; // Check all curves bool notOpen = true; for (unsigned int v = 0; notOpen && v < numCVInV; v++) { for (unsigned int u = 0; u < degreeU; u++) { unsigned int firstIndex = u * numCVInV + (numCVInV - v - 1); unsigned int lastPeriodicIndex = (numCVInU - degreeU + u) * numCVInV + (numCVInV - v - 1); if (!controlVertices[firstIndex].isEquivalent(controlVertices[lastPeriodicIndex])) { formU = MFnNurbsSurface::kOpen; notOpen = false; break; } } } if (formU == MFnNurbsSurface::kOpen) { formU = MFnNurbsSurface::kClosed; for (unsigned int v = 0; v < numCVInV; v++) { unsigned int lastUIndex = (numCVInU - 1) * numCVInV + (numCVInV - v - 1); if (! controlVertices[numCVInV-v-1].isEquivalent(controlVertices[lastUIndex])) { formU = MFnNurbsSurface::kOpen; break; } } } notOpen = true; for (unsigned int u = 0; notOpen && u < numCVInU; u++) { for (unsigned int v = 0; v < degreeV; v++) { unsigned int firstIndex = u * numCVInV + (numCVInV - v - 1); unsigned int lastPeriodicIndex = u * numCVInV + (degreeV - v - 1); //numV - (numV - vDegree + v) - 1; if (!controlVertices[firstIndex].isEquivalent(controlVertices[lastPeriodicIndex])) { formV = MFnNurbsSurface::kOpen; notOpen = false; break; } } } if (formV == MFnNurbsSurface::kOpen) { formV = MFnNurbsSurface::kClosed; for (unsigned int u = 0; u < numCVInU; u++) { if (! controlVertices[u * numCVInV + (numCVInV-1)].isEquivalent(controlVertices[u * numCVInV])) { formV = MFnNurbsSurface::kOpen; break; } } } Alembic::Abc::FloatArraySamplePtr uKnot = samp.getUKnot(); Alembic::Abc::FloatArraySamplePtr vKnot = samp.getVKnot(); unsigned int numKnotsInU = static_cast<unsigned int>(uKnot->size() - 2); MDoubleArray uKnotSequences; uKnotSequences.setLength(numKnotsInU); for (unsigned int i = 0; i < numKnotsInU; ++i) { uKnotSequences.set((*uKnot)[i+1], i); } unsigned int numKnotsInV = static_cast<unsigned int>(vKnot->size() - 2); MDoubleArray vKnotSequences; vKnotSequences.setLength(numKnotsInV); for (unsigned int i = 0; i < numKnotsInV; i++) { vKnotSequences.set((*vKnot)[i+1], i); } // Node creation try the API first MFnNurbsSurface mFn; obj = mFn.create(controlVertices, uKnotSequences, vKnotSequences, degreeU, degreeV, formU, formV, true, iObject, &status); // something went wrong, try open/open create if (status != MS::kSuccess && (formU != MFnNurbsSurface::kOpen || formV != MFnNurbsSurface::kOpen)) { obj = mFn.create(controlVertices, uKnotSequences, vKnotSequences, degreeU, degreeV, MFnNurbsSurface::kOpen, MFnNurbsSurface::kOpen, true, iObject, &status); } if (status == MS::kSuccess) { mFn.setName(surfaceName); } else { MString errorMsg = "Could not create Nurbs Surface: "; errorMsg += surfaceName; MGlobal::displayError(errorMsg); } trimSurface(samp, mFn); return obj; }
MObject createSubD(double iFrame, Alembic::AbcGeom::ISubD & iNode, MObject & iParent, std::vector<std::string> & oSampledPropNameList) { Alembic::AbcGeom::ISubDSchema schema = iNode.getSchema(); int64_t index, ceilIndex; double alpha = getWeightAndIndex(iFrame, schema.getTimeSampling(), schema.getNumSamples(), index, ceilIndex); Alembic::AbcGeom::ISubDSchema::Sample samp; schema.get(samp, Alembic::Abc::ISampleSelector(index)); MString name(iNode.getName().c_str()); MFnMesh fnMesh; MFloatPointArray pointArray; Alembic::Abc::V3fArraySamplePtr emptyPtr; fillPoints(pointArray, samp.getPositions(), emptyPtr, 0.0); fillTopology(fnMesh, iParent, pointArray, samp.getFaceIndices(), samp.getFaceCounts()); fnMesh.setName(iNode.getName().c_str()); setInitialShadingGroup(fnMesh.partialPathName()); MObject obj = fnMesh.object(); //addProperties(iFrame, iNode, obj, oSampledPropNameList); setUVs(iFrame, fnMesh, schema.getUVs()); // add the mFn-specific attributes to fnMesh node MFnNumericAttribute numAttr; MString attrName("SubDivisionMesh"); MObject attrObj = numAttr.create(attrName, attrName, MFnNumericData::kBoolean, 1); numAttr.setKeyable(true); numAttr.setHidden(false); fnMesh.addAttribute(attrObj, MFnDependencyNode::kLocalDynamicAttr); if (samp.getInterpolateBoundary() > 0) { attrName = MString("interpolateBoundary"); attrObj = numAttr.create(attrName, attrName, MFnNumericData::kBoolean, samp.getInterpolateBoundary()); numAttr.setKeyable(true); numAttr.setHidden(false); fnMesh.addAttribute(attrObj, MFnDependencyNode::kLocalDynamicAttr); } if (samp.getFaceVaryingInterpolateBoundary() > 0) { attrName = MString("faceVaryingInterpolateBoundary"); attrObj = numAttr.create(attrName, attrName, MFnNumericData::kBoolean, samp.getFaceVaryingInterpolateBoundary()); numAttr.setKeyable(true); numAttr.setHidden(false); fnMesh.addAttribute(attrObj, MFnDependencyNode::kLocalDynamicAttr); } if (samp.getFaceVaryingPropagateCorners() > 0) { attrName = MString("faceVaryingPropagateCorners"); attrObj = numAttr.create(attrName, attrName, MFnNumericData::kBoolean, samp.getFaceVaryingPropagateCorners()); numAttr.setKeyable(true); numAttr.setHidden(false); fnMesh.addAttribute(attrObj, MFnDependencyNode::kLocalDynamicAttr); } if (samp.getHoles() && !samp.getHoles()->size() == 0) { printWarning("Hole Poly Indices not yet supported."); } if (samp.getCreaseSharpnesses() && !samp.getCreaseSharpnesses()->size() == 0) { printWarning("Creases not yet supported."); } if (samp.getCornerSharpnesses() && !samp.getCornerSharpnesses()->size() == 0) { printWarning("Corners not yet supported."); } return obj; }
void read(double iFrame, Alembic::AbcGeom::ICamera & iCamera, std::vector<double> & oArray) { oArray.resize(18); // set some optional scale values oArray[13] = 1.0; oArray[16] = 1.0; oArray[17] = 1.0; Alembic::AbcGeom::ICameraSchema schema = iCamera.getSchema(); Alembic::AbcCoreAbstract::index_t index, ceilIndex; double alpha = getWeightAndIndex(iFrame, schema.getTimeSampling(), schema.getNumSamples(), index, ceilIndex); if (alpha != 0.0) { Alembic::AbcGeom::CameraSample samp, ceilSamp; schema.get(samp, index); schema.get(ceilSamp, ceilIndex); oArray[0] = simpleLerp<double>(alpha, samp.getFocalLength(), ceilSamp.getFocalLength()); oArray[1] = simpleLerp<double>(alpha, samp.getLensSqueezeRatio(), ceilSamp.getLensSqueezeRatio()); oArray[2] = simpleLerp<double>(alpha, samp.getHorizontalAperture(), ceilSamp.getHorizontalAperture()) / 2.54; oArray[3] = simpleLerp<double>(alpha, samp.getVerticalAperture(), ceilSamp.getVerticalAperture()) / 2.54; oArray[4] = simpleLerp<double>(alpha, samp.getHorizontalFilmOffset(), ceilSamp.getHorizontalFilmOffset()) / 2.54; oArray[5] = simpleLerp<double>(alpha, samp.getVerticalFilmOffset(), ceilSamp.getVerticalFilmOffset()) / 2.54; if (samp.getOverScanLeft() == samp.getOverScanRight() && samp.getOverScanTop() == samp.getOverScanBottom() && samp.getOverScanLeft() == samp.getOverScanTop() && ceilSamp.getOverScanLeft() == ceilSamp.getOverScanRight() && ceilSamp.getOverScanTop() == ceilSamp.getOverScanBottom() && ceilSamp.getOverScanLeft() == ceilSamp.getOverScanTop()) { oArray[6] = simpleLerp<double>(alpha, samp.getOverScanLeft() + 1.0, ceilSamp.getOverScanLeft() + 1.0); } else { oArray[6] = 1.0; } oArray[7] = simpleLerp<double>(alpha, samp.getNearClippingPlane(), ceilSamp.getNearClippingPlane()); oArray[8] = simpleLerp<double>(alpha, samp.getFarClippingPlane(), ceilSamp.getFarClippingPlane()); oArray[9] = simpleLerp<double>(alpha, samp.getFStop(), ceilSamp.getFStop()); oArray[10] = simpleLerp<double>(alpha, samp.getFocusDistance(), ceilSamp.getFocusDistance()); double shutterClose = simpleLerp<double>(alpha, samp.getShutterClose(), ceilSamp.getShutterClose()); double shutterOpen = simpleLerp<double>(alpha, samp.getShutterOpen(), ceilSamp.getShutterOpen()); MTime sec(1.0, MTime::kSeconds); oArray[11] = 360.0 * (shutterClose - shutterOpen) * sec.as(MTime::uiUnit()); std::size_t numOps = samp.getNumOps(); for (std::size_t i = 0; i < numOps; ++i) { Alembic::AbcGeom::FilmBackXformOp & op = samp[i]; Alembic::AbcGeom::FilmBackXformOp & ceilOp = ceilSamp[i]; if (op.getHint() == "filmFitOffs") { double val = op.getChannelValue(0) * samp.getHorizontalAperture(); double ceilVal = ceilOp.getChannelValue(0) * ceilSamp.getHorizontalAperture(); if (val != 0.0) { // chanValue(0) * 0.5 * horiz aper / 2.54 oArray[12] = simpleLerp<double>(alpha, val, ceilVal) / 5.08; } else { val = op.getChannelValue(1) * samp.getHorizontalAperture(); ceilVal = ceilOp.getChannelValue(1) * ceilSamp.getHorizontalAperture(); // chanValue(1)* 0.5 * horiz aper / 2.54 oArray[12] = simpleLerp<double>(alpha, val, ceilVal) / 5.08; } } else if (op.getHint() == "preScale") { oArray[13] = 1.0 / simpleLerp<double>(alpha, op.getChannelValue(0), ceilOp.getChannelValue(0)); } else if (op.getHint() == "filmTranslate") { oArray[14] = simpleLerp<double>(alpha, op.getChannelValue(0), ceilOp.getChannelValue(0)); oArray[15] = simpleLerp<double>(alpha, op.getChannelValue(1), ceilOp.getChannelValue(1)); } else if (op.getHint() == "postScale") { oArray[16] = 1.0 / simpleLerp<double>(alpha, op.getChannelValue(0), ceilOp.getChannelValue(0)); } else if (op.getHint() == "cameraScale") { oArray[17] = simpleLerp<double>(alpha, op.getChannelValue(0), ceilOp.getChannelValue(0)); } } } else { Alembic::AbcGeom::CameraSample samp; schema.get(samp, index); oArray[0] = samp.getFocalLength(); oArray[1] = samp.getLensSqueezeRatio(); oArray[2] = samp.getHorizontalAperture()/2.54; oArray[3] = samp.getVerticalAperture()/2.54; oArray[4] = samp.getHorizontalFilmOffset()/2.54; oArray[5] = samp.getVerticalFilmOffset()/2.54; if (samp.getOverScanLeft() == samp.getOverScanRight() && samp.getOverScanTop() == samp.getOverScanBottom() && samp.getOverScanLeft() == samp.getOverScanTop()) { oArray[6] = samp.getOverScanLeft() + 1.0; } else { oArray[6] = 1.0; } oArray[7] = samp.getNearClippingPlane(); oArray[8] = samp.getFarClippingPlane(); oArray[9] = samp.getFStop(); oArray[10] = samp.getFocusDistance(); MTime sec(1.0, MTime::kSeconds); oArray[11] = 360.0 * (samp.getShutterClose()-samp.getShutterOpen()) * sec.as(MTime::uiUnit()); // prescale, film translate H, V, roll pivot H,V, film roll value // post scale might be in the 3x3 std::size_t numOps = samp.getNumOps(); for (std::size_t i = 0; i < numOps; ++i) { Alembic::AbcGeom::FilmBackXformOp & op = samp[i]; if (op.getHint() == "filmFitOffs") { if (op.getChannelValue(0) != 0.0) { oArray[12] = op.getChannelValue(0) * samp.getHorizontalAperture() / 5.08; } else { oArray[12] = op.getChannelValue(1) * samp.getHorizontalAperture() / 5.08; } } else if (op.getHint() == "preScale") { oArray[13] = 1.0 / op.getChannelValue(0); } else if (op.getHint() == "filmTranslate") { oArray[14] = op.getChannelValue(0); oArray[15] = op.getChannelValue(1); } else if (op.getHint() == "postScale") { oArray[16] = 1.0 / op.getChannelValue(0); } else if (op.getHint() == "cameraScale") { oArray[17] = op.getChannelValue(0); } } } }