#include "MayaNurbsSurfaceWriter.h"
#include "MayaUtility.h"
MayaNurbsSurfaceWriter::MayaNurbsSurfaceWriter(
MDagPath & iDag,
Alembic::Abc::OObject & iParent, Alembic::Util::uint32_t iTimeIndex,
const JobArgs & iArgs) :
mIsSurfaceAnimated(false), mDagPath(iDag)
{
if (!stat)
{
"MFnNurbsSurface() failed for MayaNurbsSurfaceWriter" );
}
name = util::stripNamespaces(name, iArgs.stripNamespace);
Alembic::AbcGeom::ONuPatch obj(iParent, name.
asChar(), iTimeIndex);
mSchema = obj.getSchema();
Alembic::Abc::OCompoundProperty cp;
Alembic::Abc::OCompoundProperty up;
if (AttributesWriter::hasAnyAttr(nurbs, iArgs))
{
cp = mSchema.getArbGeomParams();
up = mSchema.getUserProperties();
}
mAttrs = AttributesWriterPtr(new AttributesWriter(cp, up, obj, nurbs,
iTimeIndex, iArgs));
util::isAnimated(surface)) )
{
mIsSurfaceAnimated = true;
}
else
{
iTimeIndex = 0;
}
write();
}
bool MayaNurbsSurfaceWriter::isAnimated() const
{
return mIsSurfaceAnimated ||
(mAttrs != NULL && mAttrs->isAnimated());
}
unsigned int MayaNurbsSurfaceWriter::getNumCVs()
{
return nurbs.numCVsInU() * nurbs.numCVsInV();
}
void MayaNurbsSurfaceWriter::write()
{
double startU, endU, startV, endV;
nurbs.getKnotDomain(startU, endU, startV, endV);
Alembic::AbcGeom::ONuPatchSchema::Sample samp;
samp.setUOrder(nurbs.degreeU() + 1);
samp.setVOrder(nurbs.degreeV() + 1);
unsigned int numKnotsInU = nurbs.numKnotsInU();
std::vector<float> sampKnotsInU;
if (numKnotsInU > 1)
{
nurbs.getKnotsInU(knotsInU);
sampKnotsInU.reserve(numKnotsInU+2);
sampKnotsInU.push_back(0.0);
for (unsigned int i = 0; i < numKnotsInU; i++)
sampKnotsInU.push_back( static_cast<float>(knotsInU[i]));
double k1 = sampKnotsInU[1];
double k2 = sampKnotsInU[2];
double klast_1 = sampKnotsInU[numKnotsInU];
double klast_2 = sampKnotsInU[numKnotsInU-1];
sampKnotsInU[0] = static_cast<float>(2.0 * k1 - k2);
sampKnotsInU.push_back(static_cast<float>(2.0 * klast_1 - klast_2));
samp.setUKnot(Alembic::Abc::FloatArraySample(sampKnotsInU));
}
unsigned int numKnotsInV = nurbs.numKnotsInV();
std::vector<float> sampKnotsInV;
if (numKnotsInV > 1)
{
nurbs.getKnotsInV(knotsInV);
sampKnotsInV.reserve(numKnotsInV+2);
sampKnotsInV.push_back(0.0);
for (unsigned int i = 0; i < numKnotsInV; i++)
sampKnotsInV.push_back(static_cast<float>(knotsInV[i]));
double k1 = sampKnotsInV[1];
double k2 = sampKnotsInV[2];
double klast_1 = sampKnotsInV[numKnotsInV];
double klast_2 = sampKnotsInV[numKnotsInV-1];
sampKnotsInV[0] = static_cast<float>(2.0 * k1 - k2);
sampKnotsInV.push_back(static_cast<float>(2.0 * klast_1 - klast_2));
samp.setVKnot(Alembic::Abc::FloatArraySample(sampKnotsInV));
}
nurbs.getCVs(cvArray);
unsigned int numCVs = cvArray.
length();
int numCVsInU = nurbs.numCVsInU();
int numCVsInV = nurbs.numCVsInV();
samp.setNu(numCVsInU);
samp.setNv(numCVsInV);
std::vector<Alembic::Abc::V3f> sampPos;
sampPos.reserve(numCVs);
std::vector<float> sampPosWeights;
sampPosWeights.reserve(numCVs);
bool weightsOne = true;
for (int v = numCVsInV - 1; v > -1; v--)
{
for (int u = 0; u < numCVsInU; u++)
{
int index = u * numCVsInV + v;
sampPos.push_back(Alembic::Abc::V3f(
static_cast<float>(cvArray[index].x),
static_cast<float>(cvArray[index].y),
static_cast<float>(cvArray[index].z) ));
if (cvArray[index].w != 1.0)
{
weightsOne = false;
}
sampPosWeights.push_back(static_cast<float>(cvArray[index].w));
}
}
samp.setPositions(Alembic::Abc::V3fArraySample(sampPos));
if (!weightsOne)
{
samp.setPositionWeights(Alembic::Abc::FloatArraySample(sampPosWeights));
}
if (!nurbs.isTrimmedSurface())
{
mSchema.set(samp);
return;
}
unsigned int numRegions = nurbs.numRegions();
std::vector<Alembic::Util::int32_t> trimNumCurves;
std::vector<Alembic::Util::int32_t> trimNumPos;
std::vector<Alembic::Util::int32_t> trimOrder;
std::vector<float> trimKnot;
std::vector<float> trimMin;
std::vector<float> trimMax;
std::vector<float> trimU;
std::vector<float> trimV;
std::vector<float> trimW;
Alembic::Util::int32_t numLoops = 0;
for (unsigned int i = 0; i < numRegions; i++)
{
nurbs.getTrimBoundaries(result, i, true);
unsigned int numBoundaries = result.
length();
for (unsigned int j = 0; j < numBoundaries; j++)
{
unsigned int numTrimCurve = boundary.
length();
trimNumCurves.push_back(static_cast<Alembic::Util::int32_t>(numTrimCurve));
numLoops++;
for (unsigned int k = 0; k < numTrimCurve; k++)
{
{
Alembic::Util::int32_t numCVs = mFnCurve.numCVs();
trimNumPos.push_back(numCVs);
trimOrder.push_back(mFnCurve.degree()+1);
double start, end;
mFnCurve.getKnotDomain(start, end);
trimMin.push_back(static_cast<float>(start));
trimMax.push_back(static_cast<float>(end));
mFnCurve.getCVs(cvArray);
double offsetV = startV+endV;
for (Alembic::Util::int32_t l = 0; l < numCVs; l++)
{
trimU.push_back(static_cast<float>(cvArray[l].x));
trimV.push_back(
static_cast<float>(offsetV-cvArray[l].y));
trimW.push_back(static_cast<float>(cvArray[l].w));
}
mFnCurve.getKnots(knot);
unsigned int numKnots = knot.
length();
std::size_t totalNumKnots = trimKnot.size();
trimKnot.push_back(0.0);
for (unsigned int l = 0; l < numKnots; l++)
{
trimKnot.push_back(static_cast<float>(knot[l]));
}
double k1 = trimKnot[totalNumKnots+1];
double k2 = trimKnot[totalNumKnots+2];
double klast_1 = trimKnot[trimKnot.size()-1];
double klast_2 = trimKnot[trimKnot.size()-2];
trimKnot[totalNumKnots] = static_cast<float>(2.0 * k1 - k2);
trimKnot.push_back(
static_cast<float>(2.0 * klast_1 - klast_2));
}
}
}
}
samp.setTrimCurve(numLoops,
Alembic::Abc::Int32ArraySample(trimNumCurves),
Alembic::Abc::Int32ArraySample(trimNumPos),
Alembic::Abc::Int32ArraySample(trimOrder),
Alembic::Abc::FloatArraySample(trimKnot),
Alembic::Abc::FloatArraySample(trimMin),
Alembic::Abc::FloatArraySample(trimMax),
Alembic::Abc::FloatArraySample(trimU),
Alembic::Abc::FloatArraySample(trimV),
Alembic::Abc::FloatArraySample(trimW));
mSchema.set(samp);
}