/*! * Description: Deform the point using the Sederberg-Parry FFD algorithm. * * Arguments: * block : the datablock of the node * iter : an iterator for the geometry to be deformed * m : matrix to transform the point into world space * multiIndex : the index of the geometry that we are deforming */ MStatus ffdPlanar::deform( MDataBlock& block, MItGeometry& iter, const MMatrix& /*m*/, unsigned int multiIndex ) { MStatus status = MS::kSuccess; // Determine the displacement lattice points. MDataHandle row1Data = block.inputValue( latticeRow1, &status ); MCheckErr( status, "Error getting r1 data handle\n" ); MVector row1Vector = row1Data.asVector(); MDataHandle row2Data = block.inputValue( latticeRow2, &status ); MCheckErr( status, "Error getting r2 data handle\n" ); MVector row2Vector = row2Data.asVector(); MDataHandle row3Data = block.inputValue( latticeRow3, &status ); MCheckErr( status, "Error getting r3 data\n" ); MVector row3Vector = row3Data.asVector(); // Determine the envelope (this is a global scale factor for the deformer). MDataHandle envData = block.inputValue(envelope,&status); MCheckErr(status, "Error getting envelope data handle\n"); float env = envData.asFloat(); // Generate the FFD lattice. MVector lattice[FFD_LATTICE_POINTS_S][FFD_LATTICE_POINTS_T][FFD_LATTICE_POINTS_U] = { // Since dimensions known ahead of time, generate array now. { // x = 0 { MVector(0.f, row1Vector.x, 0.f), MVector(0.f, row1Vector.y, .5f), MVector(0.f, row1Vector.z, 1.f) }, // y = 0 }, { // x = 1 { MVector(.5f, row2Vector.x, 0.f), MVector(.5f, row2Vector.y, .5f), MVector(.5f, row2Vector.z, 1.f) }, // y = 0 }, { // x = 2 { MVector(1.f, row3Vector.x, 0.f), MVector(1.f, row3Vector.y, .5f), MVector(1.f, row3Vector.z, 1.f) }, // y = 0 } }; MBoundingBox boundingBox; status = getBoundingBox( block, multiIndex, boundingBox ); MCheckErr( status, "Error getting bounding box\n" ); MTransformationMatrix transform = getXyzToStuTransformation( boundingBox ); MMatrix transformMatrix = transform.asMatrix(); MMatrix inverseMatrix = transform.asMatrixInverse(); // Iterate through each point in the geometry. for ( ; !iter.isDone(); iter.next() ) { MPoint pt = iter.position(); MPoint ptStu = pt * transformMatrix; MPoint deformed = getDeformedPoint( ptStu, lattice ) * inverseMatrix; if ( env != 1.f ) { MVector diff = deformed - pt; deformed = pt + env * diff; } iter.setPosition( deformed ); } return status; }
void GlobalComponent::updateComponent(MDGModifier & dgMod,bool forceUpdate, bool globalPos) { MStatus status; if( !this->m_metaDataNode.isNull() ) { //get the rig name MFnDependencyNode metaDataNodeFn( m_metaDataNode ); MString metaNodeName = metaDataNodeFn.name(); MStringArray nameArray; metaNodeName.split('_', nameArray); MString rigName = nameArray[1]; //get the controller name MString controllerName = nameArray[2]; MString compXmlName = this->m_pCompGuide->getName(); //update names of component objects if( rigName != this->m_rigName || controllerName != compXmlName ) { //set the metadata node name lrutils::stringReplaceAll(metaNodeName, rigName, this->m_rigName); lrutils::stringReplaceAll(metaNodeName, controllerName, this->m_pCompGuide->getName()); metaDataNodeFn.setName(metaNodeName); //set controller object name MObject globalCtlObj; lrutils::getMetaNodeConnection(this->m_metaDataNode, globalCtlObj, "controller"); MFnDependencyNode globalCtlFn( globalCtlObj ); MString globalCtlName = globalCtlFn.name(); lrutils::stringReplaceAll(globalCtlName, rigName, this->m_rigName); lrutils::stringReplaceAll(globalCtlName, controllerName, this->m_pCompGuide->getName()); globalCtlFn.setName(globalCtlName); //set controller group object name MObject globalCtlGroupObj; lrutils::getMetaNodeConnection(this->m_metaDataNode, globalCtlGroupObj, "controllerGroup"); MFnDependencyNode globalCtlGroupFn( globalCtlGroupObj ); MString globalCtlGroupName = globalCtlGroupFn.name(); lrutils::stringReplaceAll(globalCtlGroupName, rigName, this->m_rigName); lrutils::stringReplaceAll(globalCtlGroupName, controllerName, this->m_pCompGuide->getName()); globalCtlGroupFn.setName(globalCtlGroupName); //set rigParentConstraint object name MObject rigParentConstraintObj; lrutils::getMetaNodeConnection(this->m_metaDataNode, rigParentConstraintObj, "rigParentConstraint"); MFnDependencyNode rigParentConstraintFn( rigParentConstraintObj ); MString rigParentConstraintName = rigParentConstraintFn.name(); lrutils::stringReplaceAll(rigParentConstraintName, rigName, this->m_rigName); lrutils::stringReplaceAll(rigParentConstraintName, controllerName, this->m_pCompGuide->getName()); rigParentConstraintFn.setName(rigParentConstraintName); //set rigScaleConstraint object name MObject rigScaleConstraintObj; lrutils::getMetaNodeConnection(this->m_metaDataNode, rigScaleConstraintObj, "rigScaleConstraint"); MFnDependencyNode rigScaleConstraintFn( rigScaleConstraintObj ); MString rigScaleConstraintName = rigScaleConstraintFn.name(); lrutils::stringReplaceAll(rigScaleConstraintName, rigName, this->m_rigName); lrutils::stringReplaceAll(rigScaleConstraintName, controllerName, this->m_pCompGuide->getName()); rigScaleConstraintFn.setName(rigScaleConstraintName); //set noTransformScaleConstraint object name MObject noTransformScaleConstraintObj; lrutils::getMetaNodeConnection(this->m_metaDataNode, noTransformScaleConstraintObj, "noTransformScaleConstraint"); MFnDependencyNode noTransformScaleConstraintFn( noTransformScaleConstraintObj ); MString noTransformScaleConstraintName = noTransformScaleConstraintFn.name(); lrutils::stringReplaceAll(noTransformScaleConstraintName, rigName, this->m_rigName); lrutils::stringReplaceAll(noTransformScaleConstraintName, controllerName, this->m_pCompGuide->getName()); noTransformScaleConstraintFn.setName(noTransformScaleConstraintName); } //update component settings, if the version increment is raised //or force update is true MPlug versionPlug = metaDataNodeFn.findPlug( "version" ); float nodeVersion; versionPlug.getValue(nodeVersion); if( (this->m_pCompGuide->getVersion() > nodeVersion) || forceUpdate ) { versionPlug.setValue( this->m_pCompGuide->getVersion() ); //make a new controller object based upon the xml settings GlobalComponentGuidePtr globalGuide = boost::dynamic_pointer_cast<GlobalComponentGuide>(this->m_pCompGuide); MString ctlColor = globalGuide->getColor(); MString ctlIcon = globalGuide->getIcon(); MGlobal::executeCommand( "python(\"control = rig101().rig101WCGetByName('" + ctlIcon + "')\");" ); MGlobal::executeCommand( "python(\"Utils.setControllerColor(control, '" + ctlColor + "')\");" ); MCommandResult res; MGlobal::executeCommand( MString("python(\"control.fullPath()\");"), res ); MString sResult; res.getResult(sResult); MObject ctlObj; MStatus status = lrutils::getObjFromName(sResult, ctlObj); MyCheckStatus(status, "lrutils::getObjFromName() failed"); //apply the scale of the controller location to the new shape MVectorArray ctlLocation = this->m_pCompGuide->getLocation(0); MFnTransform ctlFn( ctlObj ); lrutils::setLocation(ctlObj, ctlLocation, MFnTransform::MFnTransform(), false, false, true); //get the global transforms of the controller for all keyframes and save them for later use MObject oldCtlObj; status = lrutils::getMetaNodeConnection( this->m_metaDataNode, oldCtlObj, "controller" ); MyCheckStatus(status, "getMetaNodeConnection() failed"); MFnTransform oldCtlFn( oldCtlObj ); std::map<double, MMatrix> oldCtlWorldMatrices; if(globalPos) { status = lrutils::getAllWorldTransforms(oldCtlObj, oldCtlWorldMatrices); MyCheckStatus(status, "lrutils::getAllWorldTransforms() failed"); } //get the shape node of the original controller object MStringArray sResults; MGlobal::executeCommand( "listRelatives -s -fullPath "+oldCtlFn.name()+";", sResults ); MString oldCtlShapePath = sResults[0]; MGlobal::executeCommand( "listRelatives -s -path "+oldCtlFn.name()+";", sResults ); MString oldCtlShapeName = sResults[0]; MObject oldCtlShapeObj; lrutils::getObjFromName(oldCtlShapePath, oldCtlShapeObj); //delete the old shape node MGlobal::deleteNode( oldCtlShapeObj ); //get the new shape node MGlobal::executeCommand( "listRelatives -s -fullPath "+ctlFn.name()+";", sResults ); MString ctlShapePath = sResults[0]; MObject ctlShapeObj; lrutils::getObjFromName(ctlShapePath, ctlShapeObj); //instance the new shape node under the old controller node MString command = "parent -s -add " + ctlShapePath + " " + oldCtlFn.name() + ";"; MGlobal::executeCommand( command ); MFnDependencyNode ctlShapeFn( ctlShapeObj ); ctlShapeFn.setName( oldCtlShapeName ); //set the old controller group translation to the new location MObject oldCtlGroupObj; lrutils::getMetaNodeConnection( this->m_metaDataNode, oldCtlGroupObj, "controllerGroup" ); MFnTransform oldCtlGroupFn( oldCtlGroupObj ); //save the original old controller position MTransformationMatrix oldXForm = oldCtlGroupFn.transformation(); lrutils::setLocation(oldCtlGroupObj, ctlLocation, oldCtlGroupFn, true, true, false); //compute the inverse transformation matrix of the old control group MTransformationMatrix oldCtlGrpXform = oldCtlGroupFn.transformation(); MTransformationMatrix inverseXform = MTransformationMatrix(oldCtlGrpXform.asMatrixInverse()); //set the target offset for the rigParentConstraint node lrutils::getMetaNodeConnection(this->m_metaDataNode, this->m_rigParentConstraint, "rigParentConstraint"); lrutils::setParentConstraintOffset( this->m_rigParentConstraint, inverseXform ); //delete the new controller transform MGlobal::deleteNode( ctlObj ); //find the global transformation matrix of the controller group MDagPath groupPath; status = oldCtlGroupFn.getPath(groupPath); MyCheckStatus(status, "MFnDagNode.getPath() failed"); MMatrix oldCtlGroupWorldMatrix = groupPath.inclusiveMatrix(&status); MyCheckStatus(status, "MDagPath.inclusiveMatrix() failed"); if(globalPos) { //update the animation curves attached to the old controller lrutils::updateAnimCurves(oldCtlObj, oldCtlWorldMatrices, oldCtlGroupWorldMatrix); } } } }