// 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); }
void MayaMeshWriter::writePoly( const Alembic::AbcGeom::OV2fGeomParam::Sample & iUVs) { MStatus status = MS::kSuccess; MFnMesh lMesh( mDagPath, &status ); if ( !status ) { MGlobal::displayError( "MFnMesh() failed for MayaMeshWriter" ); } std::vector<float> points; std::vector<Alembic::Util::int32_t> facePoints; std::vector<Alembic::Util::int32_t> pointCounts; fillTopology(points, facePoints, pointCounts); Alembic::AbcGeom::ON3fGeomParam::Sample normalsSamp; std::vector<float> normals; getPolyNormals(normals); if (!normals.empty()) { normalsSamp.setScope( Alembic::AbcGeom::kFacevaryingScope ); normalsSamp.setVals(Alembic::AbcGeom::N3fArraySample( (const Imath::V3f *) &normals.front(), normals.size() / 3)); } Alembic::AbcGeom::OPolyMeshSchema::Sample samp( Alembic::Abc::V3fArraySample((const Imath::V3f *)&points.front(), points.size() / 3), Alembic::Abc::Int32ArraySample(facePoints), Alembic::Abc::Int32ArraySample(pointCounts), iUVs, normalsSamp); // if this mesh is animated, write out the animated geometry if (mIsGeometryAnimated) { mPolySchema.set(samp); } else { mPolySchema.set(samp); } writeColor(); }
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; }
void MayaMeshWriter::writeSubD( const Alembic::AbcGeom::OV2fGeomParam::Sample & iUVs) { MStatus status = MS::kSuccess; MFnMesh lMesh( mDagPath, &status ); if ( !status ) { MGlobal::displayError( "MFnMesh() failed for MayaMeshWriter" ); } std::vector<float> points; std::vector<Alembic::Util::int32_t> facePoints; std::vector<Alembic::Util::int32_t> pointCounts; fillTopology(points, facePoints, pointCounts); Alembic::AbcGeom::OSubDSchema::Sample samp( Alembic::AbcGeom::V3fArraySample((const Imath::V3f *)&points.front(), points.size() / 3), Alembic::Abc::Int32ArraySample(facePoints), Alembic::Abc::Int32ArraySample(pointCounts)); samp.setUVs( iUVs ); MPlug plug = lMesh.findPlug("faceVaryingInterpolateBoundary"); if (!plug.isNull()) samp.setFaceVaryingInterpolateBoundary(plug.asInt()); plug = lMesh.findPlug("interpolateBoundary"); if (!plug.isNull()) samp.setInterpolateBoundary(plug.asInt()); plug = lMesh.findPlug("faceVaryingPropagateCorners"); if (!plug.isNull()) samp.setFaceVaryingPropagateCorners(plug.asInt()); std::vector <Alembic::Util::int32_t> creaseIndices; std::vector <Alembic::Util::int32_t> creaseLengths; std::vector <float> creaseSharpness; std::vector <Alembic::Util::int32_t> cornerIndices; std::vector <float> cornerSharpness; MUintArray edgeIds; MDoubleArray creaseData; if (lMesh.getCreaseEdges(edgeIds, creaseData) == MS::kSuccess) { unsigned int numCreases = creaseData.length(); creaseIndices.resize(numCreases * 2); creaseLengths.resize(numCreases, 2); creaseSharpness.resize(numCreases); for (unsigned int i = 0; i < numCreases; ++i) { int verts[2]; lMesh.getEdgeVertices(edgeIds[i], verts); creaseIndices[2 * i] = verts[0]; creaseIndices[2 * i + 1] = verts[1]; creaseSharpness[i] = static_cast<float>(creaseData[i]); } samp.setCreaseIndices(Alembic::Abc::Int32ArraySample(creaseIndices)); samp.setCreaseLengths(Alembic::Abc::Int32ArraySample(creaseLengths)); samp.setCreaseSharpnesses( Alembic::Abc::FloatArraySample(creaseSharpness)); } MUintArray cornerIds; MDoubleArray cornerData; if (lMesh.getCreaseVertices(cornerIds, cornerData) == MS::kSuccess) { unsigned int numCorners = cornerIds.length(); cornerIndices.resize(numCorners); cornerSharpness.resize(numCorners); for (unsigned int i = 0; i < numCorners; ++i) { cornerIndices[i] = cornerIds[i]; cornerSharpness[i] = static_cast<float>(cornerData[i]); } samp.setCornerSharpnesses( Alembic::Abc::FloatArraySample(cornerSharpness)); samp.setCornerIndices( Alembic::Abc::Int32ArraySample(cornerIndices)); } #if MAYA_API_VERSION >= 201100 MUintArray holes = lMesh.getInvisibleFaces(); unsigned int numHoles = holes.length(); std::vector <Alembic::Util::int32_t> holeIndices(numHoles); for (unsigned int i = 0; i < numHoles; ++i) { holeIndices[i] = holes[i]; } if (!holeIndices.empty()) { samp.setHoles(holeIndices); } #endif mSubDSchema.set(samp); writeColor(); writeUVSets(); }
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; }