#include "MayaTransformWriter.h"
#include "MayaUtility.h"
Alembic::Util::uint8_t iHint, bool inverse, bool forceStatic,
bool forceAnimated, Alembic::AbcGeom::XformSample & oSample,
std::vector < AnimChan > & oAnimChanList)
{
Alembic::AbcGeom::XformOp op(Alembic::AbcGeom::kTranslateOperation, iHint);
int xSamp = 0;
if (!forceStatic)
{
if (!forceAnimated)
xSamp = util::getSampledType(xPlug);
else
xSamp = 1;
}
int ySamp = 0;
if (!forceStatic)
{
if (!forceAnimated)
ySamp = util::getSampledType(yPlug);
else
ySamp = 1;
}
int zSamp = 0;
if (!forceStatic)
{
if (!forceAnimated)
zSamp = util::getSampledType(zPlug);
else
zSamp = 1;
}
int parentSamp = 0;
if (!forceStatic)
{
if (!forceAnimated)
parentSamp = util::getSampledType(parentPlug);
else
parentSamp = 1;
}
if (parentSamp != 0)
{
xSamp = 1;
ySamp = 1;
zSamp = 1;
}
if (xSamp != 0 || ySamp != 0 || zSamp != 0 || xVal != 0.0 || yVal != 0.0 ||
zVal != 0.0)
{
if (inverse)
{
xVal = -xVal;
yVal = -yVal;
zVal = -zVal;
}
op.setChannelValue(0, xVal);
op.setChannelValue(1, yVal);
op.setChannelValue(2, zVal);
if (xSamp != 0)
{
AnimChan chan;
chan.plug = xPlug;
chan.scale = 1.0;
if (inverse)
chan.scale = -1.0;
chan.opNum = oSample.getNumOps();
chan.channelNum = 0;
oAnimChanList.push_back(chan);
}
if (ySamp != 0)
{
AnimChan chan;
chan.plug = yPlug;
chan.scale = 1.0;
if (inverse)
chan.scale = -1.0;
chan.opNum = oSample.getNumOps();
chan.channelNum = 1;
oAnimChanList.push_back(chan);
}
if (zSamp != 0)
{
AnimChan chan;
chan.plug = zPlug;
chan.scale = 1.0;
if (inverse)
chan.scale = -1.0;
chan.opNum = oSample.getNumOps();
chan.channelNum = 2;
oAnimChanList.push_back(chan);
}
oSample.addOp(op);
}
}
MString parentName,
const MString* iNames,
const unsigned int* iOrder,
Alembic::Util::uint8_t iHint, bool forceStatic, bool forceAnimated,
Alembic::AbcGeom::XformSample & oSample,
std::vector < AnimChan > & oAnimChanList,
size_t oOpIndex[3])
{
static const Alembic::AbcGeom::XformOperationType rots[3] = {
Alembic::AbcGeom::kRotateXOperation,
Alembic::AbcGeom::kRotateYOperation,
Alembic::AbcGeom::kRotateZOperation
};
int parentSamp = 0;
if (!forceStatic)
{
if (!forceAnimated)
parentSamp = util::getSampledType(parentPlug);
else
parentSamp = 1;
}
bool isXYZ = ((iOrder[0] == 0) && (iOrder[1] == 1) && (iOrder[2] == 2));
int i = 2;
for (; i > -1; i--)
{
unsigned int index = iOrder[i];
int samp = 0;
if (!forceStatic)
{
if (!forceAnimated)
samp = util::getSampledType(plug);
else
samp = 1;
if (samp == 0)
samp = parentSamp;
}
Alembic::AbcGeom::XformOp op(rots[index], iHint);
op.setChannelValue(0, Alembic::AbcGeom::RadiansToDegrees(plugVal));
if (samp != 0)
{
AnimChan chan;
chan.plug = plug;
chan.scale = Alembic::AbcGeom::RadiansToDegrees(1.0);
chan.opNum = oSample.getNumOps();
chan.channelNum = 0;
oAnimChanList.push_back(chan);
}
else if (isXYZ && plugVal == 0.0)
continue;
oOpIndex[index] = oSample.addOp(op);
}
}
Alembic::AbcGeom::XformSample & oSample,
std::vector < AnimChan > & oAnimChanList)
{
Alembic::AbcGeom::XformOp op(Alembic::AbcGeom::kMatrixOperation,
Alembic::AbcGeom::kMayaShearHint);
int xySamp = 0;
if (!forceStatic)
{
xySamp = util::getSampledType(xyPlug);
}
str = "shearXZ";
int xzSamp = 0;
if (!forceStatic)
{
xzSamp = util::getSampledType(xzPlug);
}
str = "shearYZ";
int yzSamp = 0;
if (!forceStatic)
{
yzSamp = util::getSampledType(yzPlug);
}
str = "shear";
if (!forceStatic && util::getSampledType(parentPlug) != 0)
{
xySamp = 1;
xzSamp = 1;
yzSamp = 1;
}
if (xySamp != 0 || xzSamp != 0 || yzSamp != 0 ||
xyVal != 0.0 || xzVal != 0.0 || yzVal != 0.0)
{
Alembic::Abc::M44d m;
m.makeIdentity();
op.setMatrix(m);
op.setChannelValue(4, xyVal);
op.setChannelValue(8, xzVal);
op.setChannelValue(9, yzVal);
if (xySamp != 0)
{
AnimChan chan;
chan.plug = xyPlug;
chan.scale = 1.0;
chan.opNum = oSample.getNumOps();
chan.channelNum = 4;
oAnimChanList.push_back(chan);
}
if (xzSamp != 0)
{
AnimChan chan;
chan.plug = xzPlug;
chan.scale = 1.0;
chan.opNum = oSample.getNumOps();
chan.channelNum = 8;
oAnimChanList.push_back(chan);
}
if (yzSamp != 0)
{
AnimChan chan;
chan.plug = yzPlug;
chan.scale = 1.0;
chan.opNum = oSample.getNumOps();
chan.channelNum = 9;
oAnimChanList.push_back(chan);
}
oSample.addOp(op);
}
}
bool forceStatic, bool forceAnimated, Alembic::AbcGeom::XformSample & oSample,
std::vector < AnimChan > & oAnimChanList)
{
Alembic::AbcGeom::XformOp op(Alembic::AbcGeom::kScaleOperation,
Alembic::AbcGeom::kScaleHint);
int xSamp = 0;
if (!forceStatic)
{
if (!forceAnimated)
xSamp = util::getSampledType(xPlug);
else
xSamp = 1;
}
int ySamp = 0;
if (!forceStatic)
{
if (!forceAnimated)
ySamp = util::getSampledType(yPlug);
else
ySamp = 1;
}
int zSamp = 0;
if (!forceStatic)
{
if (!forceAnimated)
zSamp = util::getSampledType(zPlug);
else
zSamp = 1;
}
int parentSamp = 0;
if (!forceStatic)
{
if (!forceAnimated)
parentSamp = util::getSampledType(parentPlug);
else
parentSamp = 1;
}
if (parentSamp != 0)
{
xSamp = 1;
ySamp = 1;
zSamp = 1;
}
if (xSamp != 0 || ySamp != 0 || zSamp != 0 || xVal != 1.0 || yVal != 1.0 ||
zVal != 1.0)
{
if (inverse)
{
xVal = util::inverseScale(xVal);
yVal = util::inverseScale(yVal);
zVal = util::inverseScale(zVal);
}
op.setChannelValue(0, xVal);
op.setChannelValue(1, yVal);
op.setChannelValue(2, zVal);
if (xSamp != 0)
{
AnimChan chan;
chan.plug = xPlug;
chan.scale = 1.0;
if (inverse)
chan.scale = -std::numeric_limits<double>::infinity();
chan.opNum = oSample.getNumOps();
chan.channelNum = 0;
oAnimChanList.push_back(chan);
}
if (ySamp != 0)
{
AnimChan chan;
chan.plug = yPlug;
chan.scale = 1.0;
if (inverse)
chan.scale = -std::numeric_limits<double>::infinity();
chan.opNum = oSample.getNumOps();
chan.channelNum = 1;
oAnimChanList.push_back(chan);
}
if (zSamp != 0)
{
AnimChan chan;
chan.plug = zPlug;
chan.scale = 1.0;
if (inverse)
chan.scale = -std::numeric_limits<double>::infinity();
chan.opNum = oSample.getNumOps();
chan.channelNum = 2;
oAnimChanList.push_back(chan);
}
oSample.addOp(op);
}
}
bool getSampledRotation(const Alembic::AbcGeom::XformSample& sample,
const size_t opIndex[3], double& xx, double& yy, double& zz)
{
bool success = false;
xx = 0.0;
if (opIndex[0] < sample.getNumOps())
{
double angleX = sample[opIndex[0]].getChannelValue(0);
xx = Alembic::AbcGeom::DegreesToRadians(angleX);
success = true;
}
yy = 0.0;
if (opIndex[1] < sample.getNumOps())
{
double angleY = sample[opIndex[1]].getChannelValue(0);
yy = Alembic::AbcGeom::DegreesToRadians(angleY);
success = true;
}
zz = 0.0;
if (opIndex[2] < sample.getNumOps())
{
double angleZ = sample[opIndex[2]].getChannelValue(0);
zz = Alembic::AbcGeom::DegreesToRadians(angleZ);
success = true;
}
return success;
}
bool setSampledRotation(Alembic::AbcGeom::XformSample& sample,
const size_t opIndex[3], double xx, double yy, double zz)
{
bool success = false;
if (opIndex[0] < sample.getNumOps())
{
sample[opIndex[0]].setChannelValue(0, Alembic::AbcGeom::RadiansToDegrees(xx));
success = true;
}
if (opIndex[1] < sample.getNumOps())
{
sample[opIndex[1]].setChannelValue(0, Alembic::AbcGeom::RadiansToDegrees(yy));
success = true;
}
if (opIndex[2] < sample.getNumOps())
{
sample[opIndex[2]].setChannelValue(0, Alembic::AbcGeom::RadiansToDegrees(zz));
success = true;
}
return success;
}
MayaTransformWriter::MayaTransformWriter(Alembic::AbcGeom::OObject & iParent,
MDagPath & iDag, Alembic::Util::uint32_t iTimeIndex,
const JobArgs & iArgs)
{
mFilterEulerRotations = iArgs.filterEulerRotations;
mJointOrientOpIndex[0] = mJointOrientOpIndex[1] = mJointOrientOpIndex[2] =
mRotateOpIndex[0] = mRotateOpIndex[1] = mRotateOpIndex[2] =
mRotateAxisOpIndex[0] = mRotateAxisOpIndex[1] = mRotateAxisOpIndex[2] = ~size_t(0);
{
jointName = util::stripNamespaces(jointName, iArgs.stripNamespace);
Alembic::AbcGeom::OXform obj(iParent, jointName.
asChar(),
iTimeIndex);
mSchema = obj.getSchema();
Alembic::Abc::OCompoundProperty cp;
Alembic::Abc::OCompoundProperty up;
if (AttributesWriter::hasAnyAttr(joint, iArgs))
{
cp = mSchema.getArbGeomParams();
up = mSchema.getUserProperties();
}
mAttrs = AttributesWriterPtr(new AttributesWriter(cp, up, obj, joint,
iTimeIndex, iArgs));
if (!iArgs.worldSpace)
{
pushTransformStack(joint, iTimeIndex == 0);
MPlug inheritPlug = dagNode.findPlug(
"inheritsTransform");
{
if (util::getSampledType(inheritPlug) != 0)
{
mInheritsPlug = inheritPlug;
}
mSample.setInheritsXforms(inheritPlug.
asBool());
}
if (mAnimChanList.empty() && mInheritsPlug.isNull())
{
mSchema.setTimeSampling(0);
}
if (mSample.getNumOps() == 0 && mSample.getInheritsXforms())
{
return;
}
mSchema.set(mSample);
return;
}
}
else
{
transName = util::stripNamespaces(transName, iArgs.stripNamespace);
Alembic::AbcGeom::OXform obj(iParent, transName.
asChar(),
iTimeIndex);
mSchema = obj.getSchema();
Alembic::Abc::OCompoundProperty cp;
Alembic::Abc::OCompoundProperty up;
if (AttributesWriter::hasAnyAttr(trans, iArgs))
{
cp = mSchema.getArbGeomParams();
up = mSchema.getUserProperties();
}
mAttrs = AttributesWriterPtr(new AttributesWriter(cp, up, obj, trans,
iTimeIndex, iArgs));
if (!iArgs.worldSpace)
{
pushTransformStack(trans, iTimeIndex == 0);
MPlug inheritPlug = dagNode.findPlug(
"inheritsTransform");
{
if (util::getSampledType(inheritPlug) != 0)
{
mInheritsPlug = inheritPlug;
}
mSample.setInheritsXforms(inheritPlug.
asBool());
}
if (mAnimChanList.empty() && mInheritsPlug.isNull())
{
mSchema.setTimeSampling(0);
}
if (mSample.getNumOps() == 0 && mSample.getInheritsXforms())
{
return;
}
mSchema.set(mSample);
return;
}
}
int i;
int numPaths = dag.length();
std::vector< MDagPath > dagList;
for (i = numPaths - 1; i > -1; i--, dag.pop())
{
dagList.push_back(dag);
MPlug inheritPlug = dagNode.findPlug(
"inheritsTransform");
break;
}
std::vector< MDagPath >::iterator iStart = dagList.begin();
std::vector< MDagPath >::iterator iCur = dagList.end();
iCur--;
for (; iCur != iStart; iCur--)
{
{
pushTransformStack(joint, iTimeIndex == 0);
}
else
{
pushTransformStack(trans, iTimeIndex == 0);
}
}
{
pushTransformStack(joint, iTimeIndex == 0);
}
else
{
pushTransformStack(trans, iTimeIndex == 0);
}
MPlug inheritPlug = dagNode.findPlug(
"inheritsTransform");
{
if (util::getSampledType(inheritPlug) != 0)
{
mInheritsPlug = inheritPlug;
}
mSample.setInheritsXforms(inheritPlug.
asBool());
}
if (mAnimChanList.empty() && mInheritsPlug.isNull())
{
mSchema.setTimeSampling(0);
}
if (mSample.getNumOps() == 0 && mSample.getInheritsXforms())
{
return;
}
mSchema.set(mSample);
}
MayaTransformWriter::MayaTransformWriter(MayaTransformWriter & iParent,
MDagPath & iDag, Alembic::Util::uint32_t iTimeIndex,
const JobArgs & iArgs)
{
mFilterEulerRotations = iArgs.filterEulerRotations;
mJointOrientOpIndex[0] = mJointOrientOpIndex[1] = mJointOrientOpIndex[2] =
mRotateOpIndex[0] = mRotateOpIndex[1] = mRotateOpIndex[2] =
mRotateAxisOpIndex[0] = mRotateAxisOpIndex[1] = mRotateAxisOpIndex[2] = ~size_t(0);
{
jointName = util::stripNamespaces(jointName, iArgs.stripNamespace);
Alembic::AbcGeom::OXform obj(iParent.getObject(), jointName.
asChar(),
iTimeIndex);
mSchema = obj.getSchema();
Alembic::Abc::OCompoundProperty cp;
Alembic::Abc::OCompoundProperty up;
if (AttributesWriter::hasAnyAttr(joint, iArgs))
{
cp = mSchema.getArbGeomParams();
up = mSchema.getUserProperties();
}
mAttrs = AttributesWriterPtr(new AttributesWriter(cp, up, obj, joint,
iTimeIndex, iArgs));
pushTransformStack(joint, iTimeIndex == 0);
}
else
{
transName = util::stripNamespaces(transName, iArgs.stripNamespace);
Alembic::AbcGeom::OXform obj(iParent.getObject(), transName.
asChar(),
iTimeIndex);
mSchema = obj.getSchema();
Alembic::Abc::OCompoundProperty cp;
Alembic::Abc::OCompoundProperty up;
if (AttributesWriter::hasAnyAttr(trans, iArgs))
{
cp = mSchema.getArbGeomParams();
up = mSchema.getUserProperties();
}
mAttrs = AttributesWriterPtr(new AttributesWriter(cp, up, obj, trans,
iTimeIndex, iArgs));
pushTransformStack(trans, iTimeIndex == 0);
}
MPlug inheritPlug = dagNode.findPlug(
"inheritsTransform");
{
if (util::getSampledType(inheritPlug) != 0)
mInheritsPlug = inheritPlug;
mSample.setInheritsXforms(inheritPlug.
asBool());
}
if (mSample.getNumOps() == 0 && mSample.getInheritsXforms())
return;
mSchema.set(mSample);
}
MayaTransformWriter::~MayaTransformWriter()
{
}
void MayaTransformWriter::write()
{
size_t numSamples = mAnimChanList.size();
if (numSamples > 0)
{
std::vector < AnimChan >::iterator it, itEnd;
for (it = mAnimChanList.begin(), itEnd = mAnimChanList.end();
it != itEnd; ++it)
{
if (it->scale == -std::numeric_limits<double>::infinity())
val = util::inverseScale(val);
else if (it->scale != 1.0)
val *= it->scale;
mSample[it->opNum].setChannelValue(it->channelNum, val);
}
if (!mInheritsPlug.isNull())
{
mSample.setInheritsXforms(mInheritsPlug.asBool());
}
if (mFilterEulerRotations)
{
double xx(0), yy(0), zz(0);
if (getSampledRotation(mSample, mJointOrientOpIndex, xx, yy, zz))
{
euler.setToClosestSolution(mPrevJointOrientSolution);
setSampledRotation(mSample, mJointOrientOpIndex, euler.x, euler.y, euler.z);
mPrevJointOrientSolution = euler;
}
if (getSampledRotation(mSample, mRotateOpIndex, xx, yy, zz))
{
euler.setToClosestSolution(mPrevRotateSolution);
setSampledRotation(mSample, mRotateOpIndex, euler.x, euler.y, euler.z);
mPrevRotateSolution = euler;
}
if (getSampledRotation(mSample, mRotateAxisOpIndex, xx, yy, zz))
{
euler.setToClosestSolution(mPrevRotateAxisSolution);
setSampledRotation(mSample, mRotateAxisOpIndex, euler.x, euler.y, euler.z);
mPrevRotateAxisSolution = euler;
}
}
mSchema.set(mSample);
}
}
bool MayaTransformWriter::isAnimated() const
{
return mAnimChanList.size() > 0 || !mInheritsPlug.isNull();
}
void MayaTransformWriter::pushTransformStack(
const MFnTransform & iTrans,
bool iForceStatic)
{
addTranslate(iTrans, "translate", "translateX", "translateY", "translateZ",
Alembic::AbcGeom::kTranslateHint, false, iForceStatic, false, mSample,
mAnimChanList);
addTranslate(iTrans, "rotatePivotTranslate", "rotatePivotTranslateX",
"rotatePivotTranslateY", "rotatePivotTranslateZ",
Alembic::AbcGeom::kRotatePivotTranslationHint, false,
iForceStatic, false, mSample, mAnimChanList);
addTranslate(iTrans, "rotatePivot", "rotatePivotX", "rotatePivotY",
"rotatePivotZ", Alembic::AbcGeom::kRotatePivotPointHint,
false, iForceStatic, false, mSample, mAnimChanList);
rotateNames[0] = "rotateX";
rotateNames[1] = "rotateY";
rotateNames[2] = "rotateZ";
unsigned int rotOrder[3];
if (util::getRotOrder(eRotOrder, rotOrder[0], rotOrder[1],
rotOrder[2]))
{
addRotate(iTrans, "rotate", rotateNames, rotOrder,
Alembic::AbcGeom::kRotateHint, iForceStatic, false,
mSample, mAnimChanList, mRotateOpIndex);
}
rotateNames[0] = "rotateAxisX";
rotateNames[1] = "rotateAxisY";
rotateNames[2] = "rotateAxisZ";
rotOrder[0] = 0;
rotOrder[1] = 1;
rotOrder[2] = 2;
addRotate(iTrans, "rotateAxis", rotateNames, rotOrder,
Alembic::AbcGeom::kRotateOrientationHint, iForceStatic, false,
mSample, mAnimChanList, mRotateAxisOpIndex);
addTranslate(iTrans, "rotatePivot", "rotatePivotX", "rotatePivotY",
"rotatePivotZ", Alembic::AbcGeom::kRotatePivotPointHint,
true, iForceStatic, false, mSample, mAnimChanList);
addTranslate(iTrans, "scalePivotTranslate", "scalePivotTranslateX",
"scalePivotTranslateY", "scalePivotTranslateZ",
Alembic::AbcGeom::kScalePivotTranslationHint, false, iForceStatic,
false, mSample, mAnimChanList);
addTranslate(iTrans, "scalePivot", "scalePivotX", "scalePivotY",
"scalePivotZ", Alembic::AbcGeom::kScalePivotPointHint, false,
iForceStatic, false, mSample, mAnimChanList);
addShear(iTrans, iForceStatic, mSample, mAnimChanList);
addScale(iTrans, "scale", "scaleX", "scaleY", "scaleZ", false,
iForceStatic, false, mSample, mAnimChanList);
addTranslate(iTrans, "scalePivot", "scalePivotX", "scalePivotY",
"scalePivotZ", Alembic::AbcGeom::kScalePivotPointHint, true,
iForceStatic, false, mSample, mAnimChanList);
if (mFilterEulerRotations)
{
double xx(0), yy(0), zz(0);
if (getSampledRotation( mSample, mRotateOpIndex, xx, yy, zz ))
{
}
if (getSampledRotation( mSample, mRotateAxisOpIndex, xx, yy, zz ))
{
}
}
}
void MayaTransformWriter::pushTransformStack(
const MFnIkJoint & iJoint,
bool iForceStatic)
{
bool forceAnimated = util::isDrivenByFBIK(iJoint) || util::isDrivenBySplineIK(iJoint);
addTranslate(iJoint, "translate", "translateX", "translateY", "translateZ",
Alembic::AbcGeom::kTranslateHint, false, iForceStatic, forceAnimated,
mSample, mAnimChanList);
MPlug scaleCompensatePlug = iJoint.
findPlug(
"segmentScaleCompensate");
if (scaleCompensatePlug.
asBool())
{
addScale(iJoint, "inverseScale", "inverseScaleX", "inverseScaleY",
"inverseScaleZ", true, iForceStatic, forceAnimated, mSample, mAnimChanList);
}
double vals[3];
unsigned int rotOrder[3];
rotateNames[0] = "jointOrientX";
rotateNames[1] = "jointOrientY";
rotateNames[2] = "jointOrientZ";
if (util::getRotOrder(eJointOrientOrder, rotOrder[0], rotOrder[1], rotOrder[2]))
{
addRotate(iJoint, "jointOrient", rotateNames, rotOrder,
Alembic::AbcGeom::kRotateHint, iForceStatic, true,
mSample, mAnimChanList, mJointOrientOpIndex);
}
rotateNames[0] = "rotateX";
rotateNames[1] = "rotateY";
rotateNames[2] = "rotateZ";
if (util::getRotOrder(eRotOrder, rotOrder[0], rotOrder[1],
rotOrder[2]))
{
addRotate(iJoint, "rotate", rotateNames, rotOrder,
Alembic::AbcGeom::kRotateHint, iForceStatic, true,
mSample, mAnimChanList, mRotateOpIndex);
}
rotateNames[0] = "rotateAxisX";
rotateNames[1] = "rotateAxisY";
rotateNames[2] = "rotateAxisZ";
if (util::getRotOrder(eRotateAxisOrder, rotOrder[0], rotOrder[1], rotOrder[2]))
{
addRotate(iJoint, "rotateAxis", rotateNames, rotOrder,
Alembic::AbcGeom::kRotateOrientationHint, iForceStatic, true,
mSample, mAnimChanList, mRotateAxisOpIndex);
}
addScale(iJoint, "scale", "scaleX", "scaleY", "scaleZ", false,
iForceStatic, forceAnimated, mSample, mAnimChanList);
if (mFilterEulerRotations)
{
double xx(0), yy(0), zz(0);
if (getSampledRotation( mSample, mJointOrientOpIndex, xx, yy, zz ))
{
}
if (getSampledRotation( mSample, mRotateOpIndex, xx, yy, zz ))
{
}
if (getSampledRotation( mSample, mRotateAxisOpIndex, xx, yy, zz ))
{
}
}
}