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; }
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; }