void MayaTransformWriter::pushTransformStack(const MFnTransform & iTrans,
	bool iForceStatic)
{

	// inspect the translate
	addTranslate(iTrans, "translate", "translateX", "translateY", "translateZ",
		Alembic::AbcGeom::kTranslateHint, false, iForceStatic, false, mSample,
		mAnimChanList);


	// inspect the rotate pivot translate
	addTranslate(iTrans, "rotatePivotTranslate", "rotatePivotTranslateX",
		"rotatePivotTranslateY", "rotatePivotTranslateZ",
		Alembic::AbcGeom::kRotatePivotTranslationHint, false,
			iForceStatic, false, mSample, mAnimChanList);

	// inspect the rotate pivot
	addTranslate(iTrans, "rotatePivot", "rotatePivotX", "rotatePivotY",
		"rotatePivotZ",  Alembic::AbcGeom::kRotatePivotPointHint,
		false, iForceStatic, false, mSample, mAnimChanList);

	// inspect rotate names
	MString rotateNames[3];
	rotateNames[0] = "rotateX";
	rotateNames[1] = "rotateY";
	rotateNames[2] = "rotateZ";

	unsigned int rotOrder[3];

	// if this returns false then the rotation order was kInvalid or kLast
	MTransformationMatrix::RotationOrder eRotOrder(iTrans.rotationOrder());
	if (util::getRotOrder(eRotOrder, rotOrder[0], rotOrder[1],
		rotOrder[2]))
	{
		addRotate(iTrans, "rotate", rotateNames, rotOrder,
			Alembic::AbcGeom::kRotateHint, iForceStatic, false,
			mSample, mAnimChanList, mRotateOpIndex);
	}

	// now look at the rotation orientation, aka rotate axis
	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);

	// invert the rotate pivot if necessary
	addTranslate(iTrans, "rotatePivot", "rotatePivotX", "rotatePivotY",
		"rotatePivotZ", Alembic::AbcGeom::kRotatePivotPointHint,
		true, iForceStatic, false, mSample, mAnimChanList);

	// inspect the scale pivot translation
	addTranslate(iTrans, "scalePivotTranslate", "scalePivotTranslateX",
		"scalePivotTranslateY", "scalePivotTranslateZ",
		Alembic::AbcGeom::kScalePivotTranslationHint, false, iForceStatic,
		false, mSample, mAnimChanList);

	// inspect the scale pivot point
	addTranslate(iTrans, "scalePivot", "scalePivotX", "scalePivotY",
		"scalePivotZ", Alembic::AbcGeom::kScalePivotPointHint, false,
		iForceStatic, false, mSample, mAnimChanList);

	// inspect the shear
	addShear(iTrans, iForceStatic, mSample, mAnimChanList);

	// add the scale
	addScale(iTrans, "scale", "scaleX", "scaleY", "scaleZ", false,
		iForceStatic, false, mSample, mAnimChanList);

	// inverse the scale pivot point if necessary
	addTranslate(iTrans, "scalePivot", "scalePivotX", "scalePivotY",
		"scalePivotZ", Alembic::AbcGeom::kScalePivotPointHint, true,
		iForceStatic, false, mSample, mAnimChanList);

	// remember current rotation
	if (mFilterEulerRotations)
	{
		double xx(0), yy(0), zz(0);

		// there are 2 rotation order enum definitions:
		//	 MEulerRotation::RotationOrder = MTransformationMatrix::RotationOrder-1
		if (getSampledRotation( mSample, mRotateOpIndex, xx, yy, zz ))
		{
			mPrevRotateSolution.setValue(xx, yy, zz, (MEulerRotation::RotationOrder)(eRotOrder-1));
		}

		if (getSampledRotation( mSample, mRotateAxisOpIndex, xx, yy, zz ))
		{
			mPrevRotateAxisSolution.setValue(xx, yy, zz, MEulerRotation::kXYZ);
		}
	}

}
Beispiel #2
0
// Creates an AnimChannel from a Maya compound attribute if there is meaningful
// data.  This means we found data that is non-identity.
//
// returns true if we extracted an AnimChannel and false otherwise (e.g., the
// data was identity). 
static bool 
_GatherAnimChannel(
        XFormOpType opType, 
        const MFnTransform& iTrans, 
        MString parentName, 
        MString xName, MString yName, MString zName, 
        std::vector<AnimChannel>* oAnimChanList, 
        bool isWritingAnimation,
        bool setOpName)
{
    AnimChannel chan;
    chan.opType = opType;
    chan.isInverse = false;
    if (setOpName) {
        chan.opName = parentName.asChar();
    }

    // We default to single precision (later we set the main translate op and
    // shear to double)
    chan.precision = UsdGeomXformOp::PrecisionFloat;
    
    unsigned int validComponents = 0;
    
    // this is to handle the case where there is a connection to the parent
    // plug but not to the child plugs, if the connection is there and you are
    // not forcing static, then all of the children are considered animated
    int parentSample = PxrUsdMayaUtil::getSampledType(iTrans.findPlug(parentName),false);
    
    // Determine what plug are needed based on default value & being
    // connected/animated
    MStringArray channels;
    channels.append(parentName+xName);
    channels.append(parentName+yName);
    channels.append(parentName+zName);

    GfVec3d nullValue(opType == SCALE ? 1.0 : 0.0);
    for (unsigned int i = 0; i<3; i++) {
        // Find the plug and retrieve the data as the channel default value. It
        // won't be updated if the channel is NOT ANIMATED
        chan.plug[i] = iTrans.findPlug(channels[i]);
        double plugValue = chan.plug[i].asDouble();
        chan.defValue[i] = opType == ROTATE ? GfRadiansToDegrees(plugValue) : plugValue;
        chan.sampleType[i] = NO_XFORM;
        // If we allow animation and either the parentsample or local sample is
        // not 0 then we havea ANIMATED sample else we have a scale and the
        // value is NOT 1 or if the value is NOT 0 then we have a static xform
        if ((parentSample != 0 || PxrUsdMayaUtil::getSampledType(chan.plug[i], true) != 0) && 
             isWritingAnimation) {
            chan.sampleType[i] = ANIMATED; 
            validComponents++;
        } 
        else if (!GfIsClose(chan.defValue[i], nullValue[i], 1e-7)) {
            chan.sampleType[i] = STATIC; 
            validComponents++;
        }
    }

    // If there are valid component, then we will add the animation channel.
    // Rotates with 1 component will be optimized to single axis rotation
    if (validComponents>0) {
        if (opType == SCALE) {
            chan.usdOpType = UsdGeomXformOp::TypeScale;
        } else if (opType == TRANSLATE) {
            chan.usdOpType = UsdGeomXformOp::TypeTranslate;
            // The main translate is set to double precision
            if (parentName == "translate") {
                chan.precision = UsdGeomXformOp::PrecisionDouble;
            }
        } else if (opType == ROTATE) {
            chan.usdOpType = UsdGeomXformOp::TypeRotateXYZ;
            if (validComponents == 1) {
                if (chan.sampleType[0] != NO_XFORM) chan.usdOpType = UsdGeomXformOp::TypeRotateX;
                if (chan.sampleType[1] != NO_XFORM) chan.usdOpType = UsdGeomXformOp::TypeRotateY;
                if (chan.sampleType[2] != NO_XFORM) chan.usdOpType = UsdGeomXformOp::TypeRotateZ;
            } 
            else {
                // Rotation Order ONLY applies to the "rotate" attribute
                if (parentName == "rotate") {
                    switch (iTrans.rotationOrder()) {
                        case MTransformationMatrix::kYZX:
                            chan.usdOpType = UsdGeomXformOp::TypeRotateYZX;
                        break;
                        case MTransformationMatrix::kZXY:
                            chan.usdOpType = UsdGeomXformOp::TypeRotateZXY;
                        break;
                        case MTransformationMatrix::kXZY:
                            chan.usdOpType = UsdGeomXformOp::TypeRotateXZY;
                        break;
                        case MTransformationMatrix::kYXZ:
                            chan.usdOpType = UsdGeomXformOp::TypeRotateYXZ;
                        break;
                        case MTransformationMatrix::kZYX:
                            chan.usdOpType = UsdGeomXformOp::TypeRotateZYX;
                        break;
                        default: break;
                    }
                }
            }
        } 
        else if (opType == SHEAR) {
            chan.usdOpType = UsdGeomXformOp::TypeTransform;
            chan.precision = UsdGeomXformOp::PrecisionDouble;
        } 
        else {
            return false;
        }
        oAnimChanList->push_back(chan);
        return true;
    }
    return false;
}
void MayaTransformWriter::pushTransformStack(double iFrame,
    const MFnTransform & iTrans)
{
    bool forceStatic = (iFrame == DBL_MAX);

    // inspect the translate
    addTranslate(iTrans, "translate", "translateX", "translateY", "translateZ",
        Alembic::AbcGeom::kTranslateHint, false, forceStatic, mSample,
        mAnimChanList);


    // inspect the rotate pivot translate
    addTranslate(iTrans, "rotatePivotTranslate", "rotatePivotTranslateX",
        "rotatePivotTranslateY", "rotatePivotTranslateZ",
        Alembic::AbcGeom::kRotatePivotTranslationHint, false,
            forceStatic, mSample, mAnimChanList);

    // inspect the rotate pivot
    addTranslate(iTrans, "rotatePivot", "rotatePivotX", "rotatePivotY",
        "rotatePivotZ",  Alembic::AbcGeom::kRotatePivotPointHint,
        false, forceStatic, mSample, mAnimChanList);

    // inspect rotate names
    MString rotateNames[3];
    rotateNames[0] = "rotateX";
    rotateNames[1] = "rotateY";
    rotateNames[2] = "rotateZ";

    unsigned int rotOrder[3];

    // if this returns false then the rotation order was kInvalid or kLast
    if (util::getRotOrder(iTrans.rotationOrder(), rotOrder[0], rotOrder[1],
        rotOrder[2]))
    {
        addRotate(iTrans, "rotate", rotateNames, rotOrder,
            Alembic::AbcGeom::kRotateHint, forceStatic, false,
            mSample, mAnimChanList);
    }

    // now look at the rotation orientation, aka rotate axis
    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, forceStatic, false,
        mSample, mAnimChanList);

    // invert the rotate pivot if necessary
    addTranslate(iTrans, "rotatePivot", "rotatePivotX", "rotatePivotY",
        "rotatePivotZ", Alembic::AbcGeom::kRotatePivotPointHint,
        true, forceStatic, mSample, mAnimChanList);

    // inspect the scale pivot translation
    addTranslate(iTrans, "scalePivotTranslate", "scalePivotTranslateX",
        "scalePivotTranslateY", "scalePivotTranslateZ",
        Alembic::AbcGeom::kScalePivotTranslationHint, false, forceStatic,
        mSample, mAnimChanList);

    // inspect the scale pivot point
    addTranslate(iTrans, "scalePivot", "scalePivotX", "scalePivotY",
        "scalePivotZ", Alembic::AbcGeom::kScalePivotPointHint, false,
        forceStatic, mSample, mAnimChanList);

    // inspect the shear
    addShear(iTrans, forceStatic, mSample, mAnimChanList);

    // add the scale
    addScale(iTrans, "scale", "scaleX", "scaleY", "scaleZ", forceStatic,
        mSample, mAnimChanList);

    // inverse the scale pivot point if necessary
    addTranslate(iTrans, "scalePivot", "scalePivotX", "scalePivotY",
        "scalePivotZ", Alembic::AbcGeom::kScalePivotPointHint, true,
        forceStatic, mSample, mAnimChanList);
}