MStatus testNucleusNode::compute(const MPlug &plug, MDataBlock &data) { MStatus stat; if ( plug == nextState ) { //get the value of the currentTime MTime currTime = data.inputValue(currentTime).asTime(); MObject inputData; //pull on start state or current state depending on the current time. if(currTime.value() <= 0.0) { MArrayDataHandle multiDataHandle = data.inputArrayValue(startState); multiDataHandle.jumpToElement(0); inputData =multiDataHandle.inputValue().data(); } else { MArrayDataHandle multiDataHandle = data.inputArrayValue(currentState); multiDataHandle.jumpToElement(0); inputData =multiDataHandle.inputValue().data(); } MFnNObjectData inputNData(inputData); MnCloth * nObj = NULL; inputNData.getObjectPtr(nObj); MFloatPointArray points; nObj->getPositions(points); unsigned int ii; for(ii=0;ii<points.length();ii++) { points[ii].y = (float) sin(points[ii].x + currTime.value()*4.0f*(3.1415f/180.0f)); } nObj->setPositions(points); delete nObj; data.setClean(plug); } else if ( plug == currentState ) { data.setClean(plug); } else if (plug == startState) { data.setClean(plug); } else { stat = MS::kUnknownParameter; } return stat; }
void Exporter::RecursiveJointExtraction(MFnTransform& joint, int parentIndex){ Bone output; output.parent = parentIndex; output.invBindPose = joint.transformation().asMatrixInverse().matrix; MItDependencyNodes matIt(MFn::kAnimCurve); while (!matIt.isDone()) { MFnAnimCurve animCurve(matIt.item()); if (!strcmp(animCurve.name().substring(0, joint.name().length() - 1).asChar(), joint.name().asChar())){ cout << animCurve.name().asChar() << endl; std::string type = animCurve.name().substring(joint.name().length(), animCurve.name().length()).asChar(); output.frames.resize(animCurve.time(animCurve.numKeys() - 1).value()); for (int i = 0; i < output.frames.size(); i++) { MTime time; time.setValue(i); output.frames[i].time = time.value(); if (!strcmp(type.c_str(), "_translateX")){ cout << animCurve.evaluate(time) << endl; output.frames[i].trans.x = animCurve.evaluate(time); } if (!strcmp(type.c_str(), "_translateY")){ cout << animCurve.evaluate(time) << endl; output.frames[i].trans.y = animCurve.evaluate(time); } if (!strcmp(type.c_str(), "_translateZ")){ cout << animCurve.evaluate(time) << endl; output.frames[i].trans.z = animCurve.evaluate(time); } if (!strcmp(type.c_str(), "_rotateX")){ cout << animCurve.evaluate(time) << endl; output.frames[i].rot.x = animCurve.evaluate(time); } if (!strcmp(type.c_str(), "_rotateY")){ cout << animCurve.evaluate(time) << endl; output.frames[i].rot.y = animCurve.evaluate(time); } if (!strcmp(type.c_str(), "_rotateZ")){ cout << animCurve.evaluate(time) << endl; output.frames[i].rot.z = animCurve.evaluate(time); } } } matIt.next(); } scene_.skeleton.push_back(output); int children = joint.childCount(); int parent = scene_.skeleton.size() - 1; for (int i = 0; i < children; i++) RecursiveJointExtraction(MFnTransform(joint.child(i)), parent); };
MStatus timeControl::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; MDataHandle hInTime = data.inputValue( aInTime ); MDataHandle hOffset = data.inputValue( aOffset ); MDataHandle hMult = data.inputValue( aMult ); MDataHandle hMinTime = data.inputValue( aMinTime ); MDataHandle hMaxTime = data.inputValue( aMaxTime ); MDataHandle hLimitAble = data.inputValue( aLimitAble ); MTime inTime = hInTime.asTime(); double offset = hOffset.asDouble(); double mult = hMult.asDouble(); double timeValue = inTime.value(); if( hLimitAble.asBool() ) { MTime minTime = hMinTime.asTime(); MTime maxTime = hMaxTime.asTime(); double minTimeValue = minTime.value(); double maxTimeValue = maxTime.value(); if( timeValue < minTimeValue ) timeValue = minTimeValue; if( timeValue > maxTimeValue ) timeValue = maxTimeValue; } timeValue += offset; timeValue *= mult; MTime outTime( timeValue ); MDataHandle hOutTime = data.outputValue( aOutTime ); hOutTime.set( outTime ); MDataHandle hWeight = data.inputValue( aWeight ); MDataHandle hOutWeight = data.outputValue( aOutWeight ); hOutWeight.set( hWeight.asDouble() ); data.setClean( plug ); return status; }
MStatus bruiseMapNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; if(plug == aoutput) { MObject ogrow = data.inputValue(agrowth).asMesh(); if(!ogrow.isNull()) m_base->setBase(ogrow); MObject oguide = data.inputValue(aguide).asMesh(); if(!oguide.isNull()) m_base->setGuide(oguide); //MMatrix mat = data.inputValue(aworldSpace).asMatrix(); MTime currentTime = data.inputValue(acurrenttime, &status).asTime(); int frame = (int)currentTime.value(); int startFrame = data.inputValue(astartframe, &status).asInt(); float bias = data.inputValue(aBias, &status).asFloat(); if(frame == startFrame) { int mapsize = data.inputValue(amapsize, &status).asInt(); m_base->init(mapsize); } int npt = m_base->dice(bias); MGlobal::displayInfo(MString(" bruise map n sample ")+npt); int isave = data.inputValue(asavemap, &status).asInt(); if(isave==1) { MString cache_path; MGlobal::executeCommand( MString ("string $p = `workspace -q -fn`"), cache_path); cache_path = cache_path + "/data/" + MFnDependencyNode(thisMObject()).name() + "."+frame+".exr"; MGlobal::displayInfo(MString("Saving ")+cache_path); MString uvname = data.inputValue(auvset).asString(); if(uvname == "") uvname = "map1"; m_base->save(bias, cache_path.asChar(), uvname); } data.setClean(plug); } return MS::kUnknownParameter; }
MStatus simpleEvaluationNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus returnStatus; if( plug == output ) { MDataHandle inputData = data.inputValue( input, &returnStatus ); if( returnStatus != MS::kSuccess ) { cerr << "ERROR getting data" << endl; } else { MDataHandle inputTimeData = data.inputValue( aTimeInput, &returnStatus ); if( returnStatus != MS::kSuccess ) { cerr << "ERROR getting data" << endl; } else { if ( ! cachedValueIsValid ) { MTime time = inputTimeData.asTime(); cachedValue = doExpensiveCalculation( inputData.asFloat() , (float) time.value() ); cachedValueIsValid = true; } MDataHandle outputHandle = data.outputValue( simpleEvaluationNode::output ); outputHandle.set( cachedValue ); data.setClean(plug); } } } else { return MS::kUnknownParameter; } return MS::kSuccess; }
MStatus AbcExport::doIt(const MArgList & args) { try { MStatus status; MTime oldCurTime = MAnimControl::currentTime(); MArgParser argData(syntax(), args, &status); if (argData.isFlagSet("help")) { MGlobal::displayInfo(util::getHelpText()); return MS::kSuccess; } bool verbose = argData.isFlagSet("verbose"); // If skipFrame is true, when going through the playback range of the // scene, as much frames are skipped when possible. This could cause // a problem for, time dependent solutions like // particle system / hair simulation bool skipFrame = true; if (argData.isFlagSet("dontSkipUnwrittenFrames")) skipFrame = false; double startEvaluationTime = DBL_MAX; if (argData.isFlagSet("preRollStartFrame")) { double startAt = 0.0; argData.getFlagArgument("preRollStartFrame", 0, startAt); startEvaluationTime = startAt; } unsigned int jobSize = argData.numberOfFlagUses("jobArg"); if (jobSize == 0) return status; // the frame range we will be iterating over for all jobs, // includes frames which are not skipped and the startAt offset std::set<double> allFrameRange; // this will eventually hold only the animated jobs. // its a list because we will be removing jobs from it std::list < AbcWriteJobPtr > jobList; for (unsigned int jobIndex = 0; jobIndex < jobSize; jobIndex++) { JobArgs jobArgs; MArgList jobArgList; argData.getFlagArgumentList("jobArg", jobIndex, jobArgList); MString jobArgsStr = jobArgList.asString(0); MStringArray jobArgsArray; { // parse the job arguments // e.g. -perFrameCallbackMel "print \"something\"" will be splitted to // [0] -perFrameCallbackMel // [1] print "something" enum State { kArgument, // parsing an argument (not quoted) kDoubleQuotedString, // parsing a double quoted string kSingleQuotedString, // parsing a single quoted string }; State state = kArgument; MString stringBuffer; for (unsigned int charIdx = 0; charIdx < jobArgsStr.numChars(); charIdx++) { MString ch = jobArgsStr.substringW(charIdx, charIdx); switch (state) { case kArgument: if (ch == " ") { // space terminates the current argument if (stringBuffer.length() > 0) { jobArgsArray.append(stringBuffer); stringBuffer.clear(); } // goto another argument state = kArgument; } else if (ch == "\"") { if (stringBuffer.length() > 0) { // double quote is part of the argument stringBuffer += ch; } else { // goto double quoted string state = kDoubleQuotedString; } } else if (ch == "'") { if (stringBuffer.length() > 0) { // single quote is part of the argument stringBuffer += ch; } else { // goto single quoted string state = kSingleQuotedString; } } else { stringBuffer += ch; } break; case kDoubleQuotedString: // double quote terminates the current string if (ch == "\"") { jobArgsArray.append(stringBuffer); stringBuffer.clear(); state = kArgument; } else if (ch == "\\") { // escaped character MString nextCh = (++charIdx < jobArgsStr.numChars()) ? jobArgsStr.substringW(charIdx, charIdx) : "\\"; if (nextCh == "n") stringBuffer += "\n"; else if (nextCh == "t") stringBuffer += "\t"; else if (nextCh == "r") stringBuffer += "\r"; else if (nextCh == "\\") stringBuffer += "\\"; else if (nextCh == "'") stringBuffer += "'"; else if (nextCh == "\"") stringBuffer += "\""; else stringBuffer += nextCh; } else { stringBuffer += ch; } break; case kSingleQuotedString: // single quote terminates the current string if (ch == "'") { jobArgsArray.append(stringBuffer); stringBuffer.clear(); state = kArgument; } else if (ch == "\\") { // escaped character MString nextCh = (++charIdx < jobArgsStr.numChars()) ? jobArgsStr.substringW(charIdx, charIdx) : "\\"; if (nextCh == "n") stringBuffer += "\n"; else if (nextCh == "t") stringBuffer += "\t"; else if (nextCh == "r") stringBuffer += "\r"; else if (nextCh == "\\") stringBuffer += "\\"; else if (nextCh == "'") stringBuffer += "'"; else if (nextCh == "\"") stringBuffer += "\""; else stringBuffer += nextCh; } else { stringBuffer += ch; } break; } } // the rest of the argument if (stringBuffer.length() > 0) { jobArgsArray.append(stringBuffer); } } // the frame range within this job std::vector< FrameRangeArgs > frameRanges(1); frameRanges.back().startTime = oldCurTime.value(); frameRanges.back().endTime = oldCurTime.value(); frameRanges.back().strideTime = 1.0; bool hasRange = false; bool hasRoot = false; bool sampleGeo = true; // whether or not to subsample geometry std::string fileName; bool asOgawa = true; unsigned int numJobArgs = jobArgsArray.length(); for (unsigned int i = 0; i < numJobArgs; ++i) { MString arg = jobArgsArray[i]; arg.toLowerCase(); if (arg == "-f" || arg == "-file") { if (i+1 >= numJobArgs) { MGlobal::displayError("File incorrectly specified."); return MS::kFailure; } fileName = jobArgsArray[++i].asChar(); } else if (arg == "-fr" || arg == "-framerange") { if (i+2 >= numJobArgs || !jobArgsArray[i+1].isDouble() || !jobArgsArray[i+2].isDouble()) { MGlobal::displayError("Frame Range incorrectly specified."); return MS::kFailure; } // this is not the first -frameRange argument, we are going // to add one more frame range to the frame range array. if (hasRange) { frameRanges.push_back(FrameRangeArgs()); } hasRange = true; frameRanges.back().startTime = jobArgsArray[++i].asDouble(); frameRanges.back().endTime = jobArgsArray[++i].asDouble(); // make sure start frame is smaller or equal to endTime if (frameRanges.back().startTime > frameRanges.back().endTime) { std::swap(frameRanges.back().startTime, frameRanges.back().endTime); } } else if (arg == "-frs" || arg == "-framerelativesample") { if (i+1 >= numJobArgs || !jobArgsArray[i+1].isDouble()) { MGlobal::displayError( "Frame Relative Sample incorrectly specified."); return MS::kFailure; } frameRanges.back().shutterSamples.insert( jobArgsArray[++i].asDouble()); } else if (arg == "-nn" || arg == "-nonormals") { jobArgs.noNormals = true; } else if (arg == "-pr" || arg == "-preroll") { frameRanges.back().preRoll = true; } else if (arg == "-ro" || arg == "-renderableonly") { jobArgs.excludeInvisible = true; } else if (arg == "-s" || arg == "-step") { if (i+1 >= numJobArgs || !jobArgsArray[i+1].isDouble()) { MGlobal::displayError("Step incorrectly specified."); return MS::kFailure; } frameRanges.back().strideTime = jobArgsArray[++i].asDouble(); } else if (arg == "-sl" || arg == "-selection") { jobArgs.useSelectionList = true; } else if (arg == "-sn" || arg == "-stripnamespaces") { if (i+1 >= numJobArgs || !jobArgsArray[i+1].isUnsigned()) { // the strip all namespaces case // so we pick a very LARGE number jobArgs.stripNamespace = 0xffffffff; } else { jobArgs.stripNamespace = jobArgsArray[++i].asUnsigned(); } } else if (arg == "-uv" || arg == "-uvwrite") { jobArgs.writeUVs = true; } else if (arg == "-wcs" || arg == "-writecolorsets") { jobArgs.writeColorSets = true; } else if (arg == "-wfs" || arg == "-writefacesets") { jobArgs.writeFaceSets = true; } else if (arg == "-wfg" || arg == "-wholeframegeo") { sampleGeo = false; } else if (arg == "-ws" || arg == "-worldspace") { jobArgs.worldSpace = true; } else if (arg == "-wuvs" || arg == "-writeuvsets") { jobArgs.writeUVSets = true; } else if (arg == "-wv" || arg == "-writevisibility") { jobArgs.writeVisibility = true; } else if (arg == "-as" || arg == "-autosubd") { jobArgs.autoSubd = true; } else if (arg == "-mfc" || arg == "-melperframecallback") { if (i+1 >= numJobArgs) { MGlobal::displayError( "melPerFrameCallback incorrectly specified."); return MS::kFailure; } jobArgs.melPerFrameCallback = jobArgsArray[++i].asChar(); } else if (arg == "-pfc" || arg == "-pythonperframecallback") { if (i+1 >= numJobArgs) { MGlobal::displayError( "pythonPerFrameCallback incorrectly specified."); return MS::kFailure; } jobArgs.pythonPerFrameCallback = jobArgsArray[++i].asChar(); } else if (arg == "-mpc" || arg == "-melpostjobcallback") { if (i+1 >= numJobArgs) { MGlobal::displayError( "melPostJobCallback incorrectly specified."); return MS::kFailure; } jobArgs.melPostCallback = jobArgsArray[++i].asChar(); } else if (arg == "-ppc" || arg == "-pythonpostjobcallback") { if (i+1 >= numJobArgs) { MGlobal::displayError( "pythonPostJobCallback incorrectly specified."); return MS::kFailure; } jobArgs.pythonPostCallback = jobArgsArray[++i].asChar(); } // geomArbParams - attribute filtering stuff else if (arg == "-atp" || arg == "-attrprefix") { if (i+1 >= numJobArgs) { MGlobal::displayError( "attrPrefix incorrectly specified."); return MS::kFailure; } jobArgs.prefixFilters.push_back(jobArgsArray[++i].asChar()); } else if (arg == "-a" || arg == "-attr") { if (i+1 >= numJobArgs) { MGlobal::displayError( "attr incorrectly specified."); return MS::kFailure; } jobArgs.attribs.insert(jobArgsArray[++i].asChar()); } // userProperties - attribute filtering stuff else if (arg == "-uatp" || arg == "-userattrprefix") { if (i+1 >= numJobArgs) { MGlobal::displayError( "userAttrPrefix incorrectly specified."); return MS::kFailure; } jobArgs.userPrefixFilters.push_back(jobArgsArray[++i].asChar()); } else if (arg == "-u" || arg == "-userattr") { if (i+1 >= numJobArgs) { MGlobal::displayError( "userAttr incorrectly specified."); return MS::kFailure; } jobArgs.userAttribs.insert(jobArgsArray[++i].asChar()); } else if (arg == "-rt" || arg == "-root") { if (i+1 >= numJobArgs) { MGlobal::displayError( "root incorrectly specified."); return MS::kFailure; } hasRoot = true; MString root = jobArgsArray[++i]; MSelectionList sel; if (sel.add(root) != MS::kSuccess) { MString warn = root; warn += " could not be select, skipping."; MGlobal::displayWarning(warn); continue; } unsigned int numRoots = sel.length(); for (unsigned int j = 0; j < numRoots; ++j) { MDagPath path; if (sel.getDagPath(j, path) != MS::kSuccess) { MString warn = path.fullPathName(); warn += " (part of "; warn += root; warn += " ) not a DAG Node, skipping."; MGlobal::displayWarning(warn); continue; } jobArgs.dagPaths.insert(path); } } else if (arg == "-ef" || arg == "-eulerfilter") { jobArgs.filterEulerRotations = true; } else if (arg == "-df" || arg == "-dataformat") { if (i+1 >= numJobArgs) { MGlobal::displayError( "dataFormat incorrectly specified."); return MS::kFailure; } MString dataFormat = jobArgsArray[++i]; dataFormat.toLowerCase(); if (dataFormat == "hdf") { asOgawa = false; } else if (dataFormat == "ogawa") { asOgawa = true; } } else { MString warn = "Ignoring unsupported flag: "; warn += jobArgsArray[i]; MGlobal::displayWarning(warn); } } // for i if (fileName == "") { MString error = "-file not specified."; MGlobal::displayError(error); return MS::kFailure; } { MString fileRule, expandName; MString alembicFileRule = "alembicCache"; MString alembicFilePath = "cache/alembic"; MString queryFileRuleCmd; queryFileRuleCmd.format("workspace -q -fre \"^1s\"", alembicFileRule); MString queryFolderCmd; queryFolderCmd.format("workspace -en `workspace -q -fre \"^1s\"`", alembicFileRule); // query the file rule for alembic cache MGlobal::executeCommand(queryFileRuleCmd, fileRule); if (fileRule.length() > 0) { // we have alembic file rule, query the folder MGlobal::executeCommand(queryFolderCmd, expandName); } else { // alembic file rule does not exist, create it MString addFileRuleCmd; addFileRuleCmd.format("workspace -fr \"^1s\" \"^2s\"", alembicFileRule, alembicFilePath); MGlobal::executeCommand(addFileRuleCmd); // save the workspace. maya may discard file rules on exit MGlobal::executeCommand("workspace -s"); // query the folder MGlobal::executeCommand(queryFolderCmd, expandName); } // resolve the expanded file rule if (expandName.length() == 0) { expandName = alembicFilePath; } // get the path to the alembic file rule MFileObject directory; directory.setRawFullName(expandName); MString directoryName = directory.resolvedFullName(); // make sure the cache folder exists if (!directory.exists()) { // create the cache folder MString createFolderCmd; createFolderCmd.format("sysFile -md \"^1s\"", directoryName); MGlobal::executeCommand(createFolderCmd); } // resolve the relative path MFileObject absoluteFile; absoluteFile.setRawFullName(fileName.c_str()); #if MAYA_API_VERSION < 201300 if (absoluteFile.resolvedFullName() != absoluteFile.expandedFullName()) { #else if (!MFileObject::isAbsolutePath(fileName.c_str())) { #endif // this is a relative path MString absoluteFileName = directoryName + "/" + fileName.c_str(); absoluteFile.setRawFullName(absoluteFileName); fileName = absoluteFile.resolvedFullName().asChar(); } else { fileName = absoluteFile.resolvedFullName().asChar(); } // check the path must exist before writing MFileObject absoluteFilePath; absoluteFilePath.setRawFullName(absoluteFile.path()); if (!absoluteFilePath.exists()) { MString error; error.format("Path ^1s does not exist!", absoluteFilePath.resolvedFullName()); MGlobal::displayError(error); return MS::kFailure; } // check the file is used by any AlembicNode in the scene MItDependencyNodes dgIter(MFn::kPluginDependNode); for (; !dgIter.isDone(); dgIter.next()) { MFnDependencyNode alembicNode(dgIter.thisNode()); if (alembicNode.typeName() != "AlembicNode") { continue; } MPlug abcFilePlug = alembicNode.findPlug("abc_File"); if (abcFilePlug.isNull()) { continue; } MFileObject alembicFile; alembicFile.setRawFullName(abcFilePlug.asString()); if (!alembicFile.exists()) { continue; } if (alembicFile.resolvedFullName() == absoluteFile.resolvedFullName()) { MString error = "Can't export to an Alembic file which is in use."; MGlobal::displayError(error); return MS::kFailure; } } std::ofstream ofs(fileName.c_str()); if (!ofs.is_open()) { MString error = MString("Can't write to file: ") + fileName.c_str(); MGlobal::displayError(error); return MS::kFailure; } ofs.close(); } // if -frameRelativeSample argument is not specified for a frame range, // we are assuming a -frameRelativeSample 0.0 for (std::vector<FrameRangeArgs>::iterator range = frameRanges.begin(); range != frameRanges.end(); ++range) { if (range->shutterSamples.empty()) range->shutterSamples.insert(0.0); } if (jobArgs.prefixFilters.empty()) { jobArgs.prefixFilters.push_back("ABC_"); } // the list of frame ranges for sampling std::vector<FrameRangeArgs> sampleRanges; std::vector<FrameRangeArgs> preRollRanges; for (std::vector<FrameRangeArgs>::const_iterator range = frameRanges.begin(); range != frameRanges.end(); ++range) { if (range->preRoll) preRollRanges.push_back(*range); else sampleRanges.push_back(*range); } // the list of frames written into the abc file std::set<double> geoSamples; std::set<double> transSamples; for (std::vector<FrameRangeArgs>::const_iterator range = sampleRanges.begin(); range != sampleRanges.end(); ++range) { for (double frame = range->startTime; frame <= range->endTime; frame += range->strideTime) { for (std::set<double>::const_iterator shutter = range->shutterSamples.begin(); shutter != range->shutterSamples.end(); ++shutter) { double curFrame = *shutter + frame; if (!sampleGeo) { double intFrame = (double)(int)( curFrame >= 0 ? curFrame + .5 : curFrame - .5); // only insert samples that are close to being an integer if (fabs(curFrame - intFrame) < 1e-4) { geoSamples.insert(curFrame); } } else { geoSamples.insert(curFrame); } transSamples.insert(curFrame); } } if (geoSamples.empty()) { geoSamples.insert(range->startTime); } if (transSamples.empty()) { transSamples.insert(range->startTime); } } bool isAcyclic = false; if (sampleRanges.empty()) { // no frame ranges or all frame ranges are pre-roll ranges hasRange = false; geoSamples.insert(frameRanges.back().startTime); transSamples.insert(frameRanges.back().startTime); } else { // check if the time range is even (cyclic) // otherwise, we will use acyclic // sub frames pattern std::vector<double> pattern( sampleRanges.begin()->shutterSamples.begin(), sampleRanges.begin()->shutterSamples.end()); std::transform(pattern.begin(), pattern.end(), pattern.begin(), std::bind2nd(std::plus<double>(), sampleRanges.begin()->startTime)); // check the frames against the pattern std::vector<double> timeSamples( transSamples.begin(), transSamples.end()); for (size_t i = 0; i < timeSamples.size(); i++) { // next pattern if (i % pattern.size() == 0 && i / pattern.size() > 0) { std::transform(pattern.begin(), pattern.end(), pattern.begin(), std::bind2nd(std::plus<double>(), sampleRanges.begin()->strideTime)); } // pattern mismatch, we use acyclic time sampling type if (timeSamples[i] != pattern[i % pattern.size()]) { isAcyclic = true; break; } } } // the list of frames to pre-roll std::set<double> preRollSamples; for (std::vector<FrameRangeArgs>::const_iterator range = preRollRanges.begin(); range != preRollRanges.end(); ++range) { for (double frame = range->startTime; frame <= range->endTime; frame += range->strideTime) { for (std::set<double>::const_iterator shutter = range->shutterSamples.begin(); shutter != range->shutterSamples.end(); ++shutter) { double curFrame = *shutter + frame; preRollSamples.insert(curFrame); } } if (preRollSamples.empty()) { preRollSamples.insert(range->startTime); } } if (jobArgs.dagPaths.size() > 1) { // check for validity of the DagPath relationships complexity : n^2 util::ShapeSet::const_iterator m, n; util::ShapeSet::const_iterator end = jobArgs.dagPaths.end(); for (m = jobArgs.dagPaths.begin(); m != end; ) { MDagPath path1 = *m; m++; for (n = m; n != end; n++) { MDagPath path2 = *n; if (util::isAncestorDescendentRelationship(path1,path2)) { MString errorMsg = path1.fullPathName(); errorMsg += " and "; errorMsg += path2.fullPathName(); errorMsg += " have an ancestor relationship."; MGlobal::displayError(errorMsg); return MS::kFailure; } } // for n } // for m } // no root is specified, and we aren't using a selection // so we'll try to translate the whole Maya scene by using all // children of the world as roots. else if (!hasRoot && !jobArgs.useSelectionList) { MSelectionList sel; #if MAYA_API_VERSION >= 201100 sel.add("|*", true); #else // older versions of Maya will not be able to find top level nodes // within namespaces sel.add("|*"); #endif unsigned int numRoots = sel.length(); for (unsigned int i = 0; i < numRoots; ++i) { MDagPath path; sel.getDagPath(i, path); jobArgs.dagPaths.insert(path); } } else if (hasRoot && jobArgs.dagPaths.empty()) { MString errorMsg = "No valid root nodes were specified."; MGlobal::displayError(errorMsg); return MS::kFailure; } else if (jobArgs.useSelectionList) { MSelectionList activeList; MGlobal::getActiveSelectionList(activeList); if (activeList.length() == 0) { MString errorMsg = "-selection specified but nothing is actively selected."; MGlobal::displayError(errorMsg); return MS::kFailure; } } AbcA::TimeSamplingPtr transTime, geoTime; if (hasRange) { if (isAcyclic) { // acyclic, uneven time sampling // e.g. [0.8, 1, 1.2], [2.8, 3, 3.2], .. not continuous // [0.8, 1, 1.2], [1.7, 2, 2.3], .. shutter different std::vector<double> samples( transSamples.begin(), transSamples.end()); std::transform(samples.begin(), samples.end(), samples.begin(), std::bind2nd(std::multiplies<double>(), util::spf())); transTime.reset(new AbcA::TimeSampling(AbcA::TimeSamplingType( AbcA::TimeSamplingType::kAcyclic), samples)); } else { // cyclic, even time sampling between time periods // e.g. [0.8, 1, 1.2], [1.8, 2, 2.2], ... std::vector<double> samples; double startTime = sampleRanges[0].startTime; double strideTime = sampleRanges[0].strideTime; for (std::set<double>::const_iterator shutter = sampleRanges[0].shutterSamples.begin(); shutter != sampleRanges[0].shutterSamples.end(); ++shutter) { samples.push_back((startTime + *shutter) * util::spf()); } if (samples.size() > 1) { Alembic::Util::uint32_t numSamples = static_cast<Alembic::Util::uint32_t>(samples.size()); transTime.reset( new AbcA::TimeSampling(AbcA::TimeSamplingType( numSamples, strideTime * util::spf()), samples)); } // uniform sampling else { transTime.reset(new AbcA::TimeSampling( strideTime * util::spf(), samples[0])); } } } else { // time ranges are not specified transTime.reset(new AbcA::TimeSampling()); } if (sampleGeo || !hasRange) { geoTime = transTime; } else { // sampling geo on whole frames if (isAcyclic) { // acyclic, uneven time sampling std::vector<double> samples( geoSamples.begin(), geoSamples.end()); // one more sample for setup() if (*transSamples.begin() != *geoSamples.begin()) samples.insert(samples.begin(), *transSamples.begin()); std::transform(samples.begin(), samples.end(), samples.begin(), std::bind2nd(std::multiplies<double>(), util::spf())); geoTime.reset(new AbcA::TimeSampling(AbcA::TimeSamplingType( AbcA::TimeSamplingType::kAcyclic), samples)); } else { double geoStride = sampleRanges[0].strideTime; if (geoStride < 1.0) geoStride = 1.0; double geoStart = *geoSamples.begin() * util::spf(); geoTime.reset(new AbcA::TimeSampling( geoStride * util::spf(), geoStart)); } } AbcWriteJobPtr job(new AbcWriteJob(fileName.c_str(), asOgawa, transSamples, transTime, geoSamples, geoTime, jobArgs)); jobList.push_front(job); // make sure we add additional whole frames, if we arent skipping // the inbetween ones if (!skipFrame && !allFrameRange.empty()) { double localMin = *(transSamples.begin()); std::set<double>::iterator last = transSamples.end(); last--; double localMax = *last; double globalMin = *(allFrameRange.begin()); last = allFrameRange.end(); last--; double globalMax = *last; // if the min of our current frame range is beyond // what we know about, pad a few more frames if (localMin > globalMax) { for (double f = globalMax; f < localMin; f++) { allFrameRange.insert(f); } } // if the max of our current frame range is beyond // what we know about, pad a few more frames if (localMax < globalMin) { for (double f = localMax; f < globalMin; f++) { allFrameRange.insert(f); } } } // right now we just copy over the translation samples since // they are guaranteed to contain all the geometry samples allFrameRange.insert(transSamples.begin(), transSamples.end()); // copy over the pre-roll samples allFrameRange.insert(preRollSamples.begin(), preRollSamples.end()); } // add extra evaluation run up, if necessary if (startEvaluationTime != DBL_MAX && !allFrameRange.empty()) { double firstFrame = *allFrameRange.begin(); for (double f = startEvaluationTime; f < firstFrame; ++f) { allFrameRange.insert(f); } } std::set<double>::iterator it = allFrameRange.begin(); std::set<double>::iterator itEnd = allFrameRange.end(); MComputation computation; computation.beginComputation(); // loop through every frame in the list, if a job has that frame in it's // list of transform or shape frames, then it will write out data and // call the perFrameCallback, if that frame is also the last one it has // to work on then it will also call the postCallback. // If it doesn't have this frame, then it does nothing for (; it != itEnd; it++) { if (verbose) { double frame = *it; MString info; info = frame; MGlobal::displayInfo(info); } MGlobal::viewFrame(*it); std::list< AbcWriteJobPtr >::iterator j = jobList.begin(); std::list< AbcWriteJobPtr >::iterator jend = jobList.end(); while (j != jend) { if (computation.isInterruptRequested()) return MS::kFailure; bool lastFrame = (*j)->eval(*it); if (lastFrame) { j = jobList.erase(j); } else j++; } } computation.endComputation(); // set the time back MGlobal::viewFrame(oldCurTime); return MS::kSuccess; } catch (Alembic::Util::Exception & e) { MString theError("Alembic Exception encountered: "); theError += e.what(); MGlobal::displayError(theError); return MS::kFailure; } catch (std::exception & e) { MString theError("std::exception encountered: "); theError += e.what(); MGlobal::displayError(theError); return MS::kFailure; } }
MStatus vxCache::doIt( const MArgList& args ) { MStatus status = parseArgs( args ); if( status != MS::kSuccess ) return status; MArgDatabase argData(syntax(), args); MAnimControl timeControl; MTime time = timeControl.currentTime(); int frame =int(time.value()); MString proj; MGlobal::executeCommand( MString ("string $p = `workspace -q -fn`"), proj ); MSelectionList selList; MGlobal::getActiveSelectionList ( selList ); MItSelectionList iter( selList ); MString cache_path = proj + "/data/"; MString cache_name; MString scene_name = "untitled"; worldSpace = false; if (argData.isFlagSet("-p")) argData.getFlagArgument("-p", 0, cache_path); if (argData.isFlagSet("-n")) argData.getFlagArgument("-n", 0, cache_name); if (argData.isFlagSet("-w")) argData.getFlagArgument("-w", 0, worldSpace); for ( ; !iter.isDone(); iter.next() ) { MDagPath meshPath; iter.getDagPath( meshPath ); meshPath.extendToShape(); MObject meshObj = meshPath.node(); MString surface = meshPath.partialPathName(); zWorks::validateFilePath(surface); char filename[512]; cache_name = surface; if(argData.isFlagSet("-sg")) sprintf( filename, "%s/%s.mcf", cache_path.asChar(), cache_name.asChar() ); else sprintf( filename, "%s/%s.%d.mcf", cache_path.asChar(), cache_name.asChar(), frame ); MDagPath surfDag; if ( meshPath.hasFn(MFn::kMesh)) { writeMesh(filename, meshPath, meshObj); MGlobal::displayInfo ( MString("vxCache writes ") + filename); } else MGlobal::displayError ( surface + "- Cannot find mesh to write!" ); } if ( selList.length() == 0 ) { MGlobal:: displayError ( "Nothing is selected!" ); return MS::kSuccess; } return MS::kSuccess; }
MObject LSystemNode::createMesh(const double & angle, const double & step, const MString & grammar, const MTime& time, MObject& outData, MStatus& stat) { //int numVertices, frame; //float cubeSize; //MFloatPointArray points; MPointArray points; MIntArray faceCounts; MIntArray faceConnects; MFnMesh meshFS; LSystem lsys; lsys.setDefaultAngle(angle); //angle lsys.setDefaultStep(step); //step size string gram = grammar.asChar(); //grammar lsys.loadProgramFromString(gram); std::vector<LSystem::Branch> branches; lsys.process((int)time.value(),branches); CylinderMesh*cm; for(int j = 0;j<branches.size();j++) { vec3 Bstart = branches[j].first; vec3 Bend = branches[j].second; MPoint b_start(Bstart[0],Bstart[1],Bstart[2]); MPoint b_end(Bend[0],Bend[1],Bend[2]); cm = new CylinderMesh(b_start,b_end); cm->appendToMesh(points,faceCounts,faceConnects); } /* // Scale the cube on the frame number, wrap every 10 frames. frame = (int)time.as( MTime::kFilm ); if (frame == 0) frame = 1; cubeSize = 0.5f * (float)( frame % 10); const int numFaces = 6; numVertices = 8; const int numFaceConnects = 24;*/ /* MFloatPoint vtx_1( -cubeSize, -cubeSize, -cubeSize ); MFloatPoint vtx_2( cubeSize, -cubeSize, -cubeSize ); MFloatPoint vtx_3( cubeSize, -cubeSize, cubeSize ); MFloatPoint vtx_4( -cubeSize, -cubeSize, cubeSize ); MFloatPoint vtx_5( -cubeSize, cubeSize, -cubeSize ); MFloatPoint vtx_6( -cubeSize, cubeSize, cubeSize ); MFloatPoint vtx_7( cubeSize, cubeSize, cubeSize ); MFloatPoint vtx_8( cubeSize, cubeSize, -cubeSize ); points.append( vtx_1 ); points.append( vtx_2 ); points.append( vtx_3 ); points.append( vtx_4 ); points.append( vtx_5 ); points.append( vtx_6 ); points.append( vtx_7 ); points.append( vtx_8 ); // Set up an array containing the number of vertices // for each of the 6 cube faces (4 verticies per face) // int face_counts[numFaces] = { 4, 4, 4, 4, 4, 4 }; MIntArray faceCounts( face_counts, numFaces ); // Set up and array to assign vertices from points to each face // int face_connects[ numFaceConnects ] = { 0, 1, 2, 3, 4, 5, 6, 7, 3, 2, 6, 5, 0, 3, 5, 4, 0, 4, 7, 1, 1, 7, 6, 2 }; MIntArray faceConnects( face_connects, numFaceConnects ); MObject newMesh = meshFS.create(numVertices, numFaces, points, faceCounts, faceConnects, outData, &stat); return newMesh;*/ MObject newMesh = meshFS.create(points.length() ,faceCounts.length(),points,faceCounts ,faceConnects,outData,&stat); return newMesh; }
MStatus LSystemNode::compute(const MPlug& plug, MDataBlock& data) { MStatus returnStatus; if (plug == outputMesh) { /* Get time */ MDataHandle timeData = data.inputValue( time, &returnStatus ); McheckErr(returnStatus, "Error getting time data handle\n"); MTime time = timeData.asTime(); MDataHandle angleData = data.inputValue( angle, &returnStatus ); McheckErr(returnStatus, "Error getting time data handle\n"); double angle_value = angleData.asDouble(); MDataHandle stepsData = data.inputValue( steps, &returnStatus ); McheckErr(returnStatus, "Error getting time data handle\n"); double steps_value = stepsData.asDouble(); MDataHandle grammarData = data.inputValue( grammar, &returnStatus ); McheckErr(returnStatus, "Error getting time data handle\n"); MString grammar_value = grammarData.asString(); /* Get output object */ MDataHandle outputHandle = data.outputValue(outputMesh, &returnStatus); McheckErr(returnStatus, "ERROR getting polygon data handle\n"); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&returnStatus); McheckErr(returnStatus, "ERROR creating outputData"); MFnMesh myMesh; MPointArray points; MIntArray faceCounts; MIntArray faceConnects; //MString grammar = ("F\\nF->F[+F]F[-F]F"); CylinderMesh *cm; LSystem system; system.loadProgramFromString(grammar_value.asChar()); system.setDefaultAngle(angle_value); system.setDefaultStep(steps_value); std::vector<LSystem::Branch> branches; system.process(time.value(), branches); int k = branches.size(); for(int j = 0; j < branches.size(); j++) { //1. find the position for start and end point of current branch //2. generate a cylinder MPoint start(branches[j].first[0],branches[j].first[1],branches[j].first[2]); MPoint end(branches[j].second[0],branches[j].second[1],branches[j].second[2]); cm = new CylinderMesh(start, end); cm->appendToMesh(points, faceCounts, faceConnects); } MObject newMesh = myMesh.create(points.length(), faceCounts.length(), points, faceCounts, faceConnects, newOutputData, &returnStatus); McheckErr(returnStatus, "ERROR creating new mesh"); outputHandle.set(newOutputData); data.setClean( plug ); } else return MS::kUnknownParameter; return MS::kSuccess; }
MStatus fishVizNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; MObject arbitaryMesh = data.inputValue(aInMesh).asMesh(); MDoubleArray ptc_time_offset; MDoubleArray ptc_amplitude; MDoubleArray ptc_bend; MDoubleArray ptc_scale; MDoubleArray masses; MString cacheName = data.inputValue(acachename, &status).asString(); MTime currentTime = data.inputValue(atime, &status).asTime(); cacheName = cacheName+"."+250*int(currentTime.value())+".pdc"; pdcFile* fpdc = new pdcFile(); if(fpdc->load(cacheName.asChar())==1) { //MGlobal::displayInfo(MString("FishViz loaded cache file: ")+cacheName); fpdc->readPositions(ptc_positions, ptc_velocities, ptc_ups, ptc_views, ptc_time_offset, ptc_amplitude, ptc_bend, ptc_scale, masses); } else MGlobal::displayWarning(MString("FishViz cannot open cache file: ")+cacheName); if(currentTime.value()!=int(currentTime.value())) { float delta_t = currentTime.value()-int(currentTime.value()); for(int i=0; i<fpdc->getParticleCount(); i++) { ptc_positions[i] += ptc_velocities[i]*delta_t/24.0f; } } delete fpdc; double flapping = zGetDoubleAttr(data, aFlapping); double bending= zGetDoubleAttr(data, aBending); double oscillate= zGetDoubleAttr(data, aOscillate); double length = zGetDoubleAttr(data, aLength); m_fish_length = length; double frequency = zGetDoubleAttr(data, aFrequency); unsigned num_bones = zGetIntAttr(data, aNBone); unsigned int nptc = ptc_positions.length(); MPointArray vertices; MATRIX44F mat44, mat_bone; XYZ vert, front, up, side; MDataHandle outputHandle = data.outputValue(outMesh, &status); zCheckStatus(status, "ERROR getting polygon data handle\n"); if(m_num_fish != nptc || m_num_bone != num_bones) { m_num_bone = num_bones; m_num_fish = nptc; unsigned int vertex_count; unsigned int face_count; MIntArray pcounts; MIntArray pconnect; unsigned inmeshnv, inmeshnp; MPointArray pinmesh; MIntArray count_inmesh; MIntArray connect_inmesh; zWorks::extractMeshParams(arbitaryMesh, inmeshnv, inmeshnp, pinmesh, count_inmesh, connect_inmesh); vertex_count = inmeshnv * nptc; face_count = inmeshnp * nptc; for(unsigned int i=0; i<nptc; i++) { // calculate the bone transformations poseBones(length, num_bones, ptc_time_offset[i], frequency, ptc_amplitude[i], ptc_bend[i], flapping, bending, oscillate); front.x = ptc_views[i].x; front.y = ptc_views[i].y; front.z = ptc_views[i].z; up.x = ptc_ups[i].x; up.y = ptc_ups[i].y; up.z = ptc_ups[i].z; side = front.cross(up); side.normalize(); up = side.cross(front); up.normalize(); mat44.setIdentity(); mat44.setOrientations(side, up, front); mat44.scale(ptc_scale[i]); mat44.setTranslation(ptc_positions[i].x, ptc_positions[i].y, ptc_positions[i].z); for(unsigned int j=0; j<inmeshnv; j++) { vert.x = pinmesh[j].x; vert.y = pinmesh[j].y; vert.z = pinmesh[j].z; int bone_id; if(vert.z>0) bone_id = 0; else if(-vert.z>length) bone_id = num_bones-1; else bone_id = int(-vert.z/length*(num_bones-1)); mat_bone = m_pBone->getBoneById(bone_id); vert.z -= -length/(num_bones-1)*bone_id; mat_bone.transform(vert); mat44.transform(vert); vertices.append(MPoint(vert.x, vert.y, vert.z)); } for(unsigned int j=0; j<inmeshnp; j++) { pcounts.append(count_inmesh[j]); } } int acc=0; for(unsigned int i=0; i<nptc; i++) { for(unsigned int j=0; j<connect_inmesh.length(); j++) { pconnect.append(connect_inmesh[j]+acc); } acc += inmeshnv; } MObject m_mesh = outputHandle.asMesh(); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&status); zCheckStatusNR(status, "ERROR creating outputData"); MFnMesh meshFn; m_mesh= meshFn.create( vertex_count, // number of vertices face_count, // number of polygons vertices, // The points pcounts, // # of vertex for each poly pconnect, // Vertices index for each poly newOutputData, // Dependency graph data object &status ); zCheckStatusNR(status, "ERROE creating mesh"); // Update surface // outputHandle.set(newOutputData); } else { MObject m_mesh = outputHandle.asMesh(); MFnMesh meshFn(m_mesh); unsigned inmeshnv, inmeshnp; MPointArray pinmesh; MIntArray count_inmesh; MIntArray connect_inmesh; zWorks::extractMeshParams(arbitaryMesh, inmeshnv, inmeshnp, pinmesh, count_inmesh, connect_inmesh); vertices.setLength(nptc*inmeshnv); int acc=0; for(unsigned int i=0; i<nptc; i++) { // calculate the bone transformations poseBones(length, num_bones, ptc_time_offset[i], frequency, ptc_amplitude[i], ptc_bend[i], flapping, bending, oscillate); front.x = ptc_views[i].x; front.y = ptc_views[i].y; front.z = ptc_views[i].z; up.x = ptc_ups[i].x; up.y = ptc_ups[i].y; up.z = ptc_ups[i].z; side = front.cross(up); side.normalize(); up = side.cross(front); up.normalize(); mat44.setIdentity(); mat44.setOrientations(side, up, front); mat44.scale(ptc_scale[i]); mat44.setTranslation(ptc_positions[i].x, ptc_positions[i].y, ptc_positions[i].z); for(unsigned int j=0; j<inmeshnv; j++) { vert.x = pinmesh[j].x; vert.y = pinmesh[j].y; vert.z = pinmesh[j].z; int bone_id; if(vert.z>0) bone_id = 0; else if(-vert.z>length) bone_id = num_bones-1; else bone_id = int(-vert.z/length*(num_bones-1)); mat_bone = m_pBone->getBoneById(bone_id); vert.z -= -length/(num_bones-1)*bone_id; mat_bone.transform(vert); mat44.transform(vert); vertices[j+acc] = MPoint(vert.x, vert.y, vert.z); } acc += inmeshnv; } meshFn.setPoints(vertices); outputHandle.set(meshFn.object()); } //delete fmat; data.setClean( plug ); return MS::kSuccess; }
MStatus PTCMapCmd::doIt( const MArgList& args) { MStatus status = parseArgs( args ); if( status != MS::kSuccess ) return status; MArgDatabase argData(syntax(), args); MAnimControl timeControl; MTime time = timeControl.currentTime(); int frame =int(time.value()); MString proj; MGlobal::executeCommand( MString ("string $p = `workspace -q -fn`"), proj ); MString cache_path = proj + "/data"; MString cache_name = "foo"; MString cache_attrib; double cache_mindist = 0.1; int max_level = 3; double root_size = 32; MString dem_trans = "nil"; double cloud_os = 0.05; MString key_trans = "nil"; MString eye_trans = "nil"; if (argData.isFlagSet("-p")) argData.getFlagArgument("-p", 0, cache_path); if (argData.isFlagSet("-n")) argData.getFlagArgument("-n", 0, cache_name); if (argData.isFlagSet("-a")) argData.getFlagArgument("-a", 0, cache_attrib); if (argData.isFlagSet("-mnd")) argData.getFlagArgument("-mnd", 0, cache_mindist); if (argData.isFlagSet("-ml")) argData.getFlagArgument("-ml", 0, max_level); if (argData.isFlagSet("-rs")) argData.getFlagArgument("-rs", 0, root_size); if (argData.isFlagSet("-t")) argData.getFlagArgument("-t", 0, dem_trans); if(argData.isFlagSet("-o")) argData.getFlagArgument("-o", 0, cloud_os); if(argData.isFlagSet("-tk")) argData.getFlagArgument("-tk", 0, key_trans); if(argData.isFlagSet("-te")) argData.getFlagArgument("-te", 0, eye_trans); float def_area = root_size; int last = 0; while(last < max_level-2) { def_area /= 2; last++; } def_area = 1.0f; //def_area *= def_area; // get bounding box center MDagPath p_bbox; zWorks::getTypedPathByName(MFn::kTransform, dem_trans, p_bbox); MObject o_bbox = p_bbox.transform(); float m_space[4][4]; m_space[0][0]=1; m_space[0][1]=0; m_space[0][2]=0; m_space[1][0]=0; m_space[1][1]=1; m_space[1][2]=0; m_space[2][0]=0; m_space[2][1]=0; m_space[2][2]=1; m_space[3][0]=0; m_space[3][1]=0; m_space[3][2]=0; if(o_bbox.isNull()) MGlobal::displayWarning("Cannot find pmap dimension, use default space."); else zWorks::getTransformWorldNoScale(p_bbox.partialPathName(), m_space); XYZ root_center(m_space[3][0], m_space[3][1], m_space[3][2]); // get key light dir MDagPath p_key; zWorks::getTypedPathByName(MFn::kTransform, key_trans, p_key); MObject o_key = p_key.transform(); m_space[0][0]=1; m_space[0][1]=0; m_space[0][2]=0; m_space[1][0]=0; m_space[1][1]=1; m_space[1][2]=0; m_space[2][0]=0; m_space[2][1]=0; m_space[2][2]=1; m_space[3][0]=0; m_space[3][1]=0; m_space[3][2]=0; if(o_key.isNull()) MGlobal::displayWarning("Cannot find key camera, use default space."); else zWorks::getTransformWorldNoScale(p_key.partialPathName(), m_space); XYZ key_dir(m_space[2][0], m_space[2][1], m_space[2][2]); key_dir.normalize(); // get view dir MDagPath p_eye; zWorks::getTypedPathByName(MFn::kTransform, eye_trans, p_eye); MObject o_eye = p_eye.transform(); m_space[0][0]=1; m_space[0][1]=0; m_space[0][2]=0; m_space[1][0]=0; m_space[1][1]=1; m_space[1][2]=0; m_space[2][0]=0; m_space[2][1]=0; m_space[2][2]=1; m_space[3][0]=0; m_space[3][1]=0; m_space[3][2]=0; if(o_eye.isNull()) MGlobal::displayWarning("Cannot find render camera, use default space."); else zWorks::getTransformWorldNoScale(p_eye.partialPathName(), m_space); XYZ view_dir(-m_space[2][0], -m_space[2][1], -m_space[2][2]); view_dir.normalize(); // additional attribs MStringArray attribArray; cache_attrib.split('.', attribArray); MSelectionList slist; MGlobal::getActiveSelectionList( slist ); MItSelectionList list( slist, MFn::kParticle, &status ); if (MS::kSuccess != status) { displayError( "Could not create selection list iterator"); return status; } if (list.isDone()) { displayError( "No particles selected" ); return MS::kSuccess; } MDagPath fDagPath; MObject component; unsigned npt = 0,acc = 0; for(; !list.isDone(); list.next()) { list.getDagPath (fDagPath, component); MFnParticleSystem ps( fDagPath ); npt += ps.count(); } if(npt < 1) { MGlobal::displayInfo(" zero particle: do nothing "); return MS::kSuccess; } std::list<AParticle *> particles; RGRID *buf = new RGRID[npt]; unsigned *idxb = new unsigned[npt]; float *opab = new float[npt]; float *ageb = new float[npt]; list.reset(); for(; !list.isDone(); list.next()) { list.getDagPath (fDagPath, component); MFnParticleSystem ps( fDagPath ); MVectorArray positions; ps.position( positions ); MVectorArray velarr; ps.velocity( velarr ); MIntArray ids; ps.particleIds(ids); MVectorArray cols; ps.rgb(cols); MDoubleArray opas; ps.opacity(opas); MDoubleArray ages; ps.opacity(ages); for(unsigned i=0; i<positions.length(); i++,acc++ ) { buf[acc].pos.x = positions[i].x; buf[acc].pos.y = positions[i].y; buf[acc].pos.z = positions[i].z; buf[acc].nor.x = velarr[i].x; buf[acc].nor.y = velarr[i].y; buf[acc].nor.z = velarr[i].z; buf[acc].area = def_area; if(ps.hasRgb()) { buf[acc].col.x = cols[i].x; buf[acc].col.y = cols[i].y; buf[acc].col.z = cols[i].z; } else buf[acc].col = XYZ(1,1,1); idxb[acc] = ids[i]; if(ps.hasOpacity ()) opab[acc] = opas[i]; else opab[acc] = 1.f; ageb[acc] = ages[i]; AParticle *pt = new AParticle(); pt->pos.x = positions[i].x; pt->pos.y = positions[i].y; pt->pos.z = positions[i].z; pt->r = def_area; particles.push_back(pt); } } /* Z3DTexture* tree = new Z3DTexture(); tree->setGrid(buf, npt); tree->constructTree(root_center, root_size, max_level); tree->setGridIdData(idxb, npt); tree->setGridOpacityData(opab, npt); tree->setGridAgeData(ageb, npt); MGlobal::displayInfo(MString(" num grid ")+ tree->getNumGrid()); MGlobal::displayInfo(MString(" num voxel ")+ tree->getNumVoxel()); MGlobal::displayInfo(MString(" num leaf ")+ tree->getNumLeaf()); MGlobal::displayInfo(MString(" max level ")+ tree->getMaxLevel()); MGlobal::displayInfo(" calculating voxel volume occlusion..."); tree->occlusionVolume(cloud_os, key_dir, view_dir); MGlobal::displayInfo(" done"); MGlobal::displayInfo(" updating grid distance to neighbour..."); tree->distanceToNeighbour(cache_mindist); MGlobal::displayInfo(" done"); char filename[512]; sprintf( filename, "%s/%s.%d.pmap", cache_path.asChar(), cache_name.asChar(), frame ); MGlobal::displayInfo(MString("PTCMap saved ") + filename); tree->save(filename); delete tree; */ if(!particles.empty()) { GPUOctree *data = new GPUOctree(); data->create(root_center, root_size, 8, particles); MGlobal::displayInfo(MString(" num voxel ")+ data->getNumVoxel()+ MString(" minvar ")+ data->getMinVariation()+ MString(" max level ")+ data->getMaxLevel()+ MString(" filter size ")+ def_area); char filename[512]; sprintf( filename, "%s/%s.%d", cache_path.asChar(), cache_name.asChar(), frame ); data->dumpIndirection(filename); delete data; particles.clear(); } return MS::kSuccess; }
bool RenderGlobals::getDefaultGlobals() { MSelectionList defaultGlobals; defaultGlobals.add("defaultRenderGlobals"); if( defaultGlobals.length() == 0 ) { Logging::debug("defaultRenderGlobals not found. Stopping."); return false; } MCommonRenderSettingsData data; MRenderUtil::getCommonRenderSettings(data); MObject node; defaultGlobals.getDependNode(0, node); MFnDependencyNode fnRenderGlobals(node); MTime tv = MAnimControl::currentTime(); this->currentFrameNumber = (float)(tv.value()); tv = data.frameStart; this->startFrame = (float)(tv.value()); tv = data.frameEnd; this->endFrame = (float)(tv.value()); tv = data.frameBy; this->byFrame = (float)(tv.value()); // check if we are in a batch render mode or if we are rendering from UI if( MGlobal::mayaState() == MGlobal::kBatch ) { this->inBatch = true; if( data.isAnimated() ) { Logging::debug(MString("animation on, rendering frame sequence from ") + this->startFrame + " to " + this->endFrame); // these are the frames that are supposed to be rendered in batch mode this->doAnimation = true; for( double frame = this->startFrame; frame <= this->endFrame; frame += this->byFrame) this->frameList.push_back((float)frame); }else{ Logging::debug(MString("animation off, rendering current frame")); this->frameList.push_back(this->currentFrameNumber ); this->doAnimation = false; } }else{ // we are rendering from the UI so only render the current frame this->inBatch = false; this->frameList.push_back(this->currentFrameNumber ); this->doAnimation = false; // at the moment, if rendering comes from UI dont do animation } this->imgHeight = data.height; this->imgWidth = data.width; this->pixelAspect = data.pixelAspectRatio; this->regionLeft = 0; this->regionRight = this->imgWidth; this->regionBottom = 0; this->regionTop = this->imgHeight; regionLeft = getIntAttr("left", fnRenderGlobals, 0); regionRight = getIntAttr("rght", fnRenderGlobals, imgWidth); regionBottom = getIntAttr("bot", fnRenderGlobals, 0); regionTop = getIntAttr("top", fnRenderGlobals, imgHeight); getBool(MString("enableDefaultLight"), fnRenderGlobals, this->createDefaultLight); getString(MString("preRenderMel"), fnRenderGlobals, this->preFrameScript); getString(MString("postRenderMel"), fnRenderGlobals, this->postFrameScript); getString(MString("preRenderLayerMel"), fnRenderGlobals, this->preRenderLayerScript); getString(MString("postRenderLayerMel"), fnRenderGlobals, this->postRenderLayerScript); MFnDependencyNode depFn(getRenderGlobalsNode()); this->maxTraceDepth = getIntAttr("maxTraceDepth", depFn, 4); this->doMb = getBoolAttr("doMotionBlur", depFn, false); this->doDof = getBoolAttr("doDof", depFn, false); this->motionBlurRange = getFloatAttr("motionBlurRange", depFn, 0.4f); this->motionBlurType = 0; // center this->xftimesamples = getIntAttr("xftimesamples", depFn, 2); this->geotimesamples = getIntAttr("geotimesamples", depFn, 2); this->createDefaultLight = false; this->renderType = RenderType::FINAL; this->exportSceneFile = getBoolAttr("exportSceneFile", depFn, false); this->adaptiveSampling = getBoolAttr("adaptiveSampling", depFn, false); this->imageName = getStringAttr("imageName", depFn, ""); this->basePath = getStringAttr("basePath", depFn, ""); this->exportSceneFileName = getStringAttr("exportSceneFileName", depFn, ""); this->imagePath = getStringAttr("imagePath", depFn, ""); this->threads = getIntAttr("threads", depFn, 4); this->translatorVerbosity = getEnumInt("translatorVerbosity", depFn); this->rendererVerbosity = getEnumInt("rendererVerbosity", depFn); this->useSunLightConnection = getBoolAttr("useSunLightConnection", depFn, false); this->tilesize = getIntAttr("tileSize", depFn, 64); this->sceneScale = getFloatAttr("sceneScale", depFn, 1.0f); this->filterSize = getFloatAttr("filterSize", depFn, 3.0f); this->good = true; return true; }
MStatus preview(const MArgList& args,bool useVertexColor) { //单实例先清除 if(MaterialSet::getSingletonPtr()) MaterialSet::getSingletonPtr()->clear(); char tempPath[MAX_PATH]; GetTempPath(MAX_PATH, tempPath); std::string tempFileName(tempPath); ExportOptions::instance().m_outFilePath = tempFileName.c_str(); tempFileName += "\\"; tempFileName += _T("maya.mz"); ExportOptions::instance().m_outFile = tempFileName.c_str(); ExportOptions::instance().clipList.clear(); MTime kTimeMin = MAnimControl::animationStartTime(); //整个场景的起始帧 MTime kTimeMax = MAnimControl::animationEndTime(); //整个场景的结束帧 clipInfo clip; clip.name = "Animation"; clip.startFrame = (int)kTimeMin.value(); clip.endFrame = (int)kTimeMax.value(); clip.stepFrame = 1; ExportOptions::instance().clipList.push_back(clip); ExportOptions::instance().exportAnims = true; ExportOptions::instance().exportVertexColour = useVertexColor; /*BindPoseTool bindPoseTool; bindPoseTool.GoIntoBindPose();*/ MWriter writer; writer.read(); MStatus status = writer.write(); #ifdef RELEASEDEBUG #define DLL_NAME "MayaPreview_rd.exe" #elif _DEBUG #define DLL_NAME "MayaPreview_d.exe" #else #define DLL_NAME "MayaPreview.exe" #endif if(status == MS::kSuccess) { HWND hWnd = FindWindowEx(0,0,0,"MayaPreview"); //if(hWnd) //{ // SendMessage(hWnd,WM_CLOSE,0,0); // hWnd = 0; //} if(!hWnd) { static const std::string tMaxProgramName("Maya.exe"); char path[257]; GetModuleFileName(GetModuleHandle(tMaxProgramName.c_str()),path,256); std::string parentPath(path); parentPath.erase(parentPath.size() - tMaxProgramName.size(), tMaxProgramName.size()); std::string previewProgramPath(parentPath + "preview\\" + DLL_NAME); if(!ShellExecute(0,"open",previewProgramPath.c_str(),"","",SW_SHOW)) { MessageBox(0,previewProgramPath.c_str(),"Can't Find MayaPreview Program",0); return MS::kFailure; } hWnd = FindWindowEx(0,0,0,"MayaPreview"); DWORD tick = GetTickCount(); while(!hWnd) { DWORD tickNow = GetTickCount(); if(tickNow - tick > 3000)break; Sleep(1); hWnd = FindWindowEx(0,0,0,"MayaPreview"); } } if(hWnd) { SendMessage(hWnd,WM_USER + 128,0,0); SetActiveWindow(hWnd); SetForegroundWindow(hWnd); BringWindowToTop(hWnd); } } /*bindPoseTool .UndoGoIntoBindPose();*/ return MS::kSuccess; }
bool RenderGlobals::getDefaultGlobals() { MSelectionList defaultGlobals; defaultGlobals.add("defaultRenderGlobals"); if( defaultGlobals.length() == 0 ) { logger.debug("defaultRenderGlobals not found. Stopping."); return false; } MCommonRenderSettingsData data; MRenderUtil::getCommonRenderSettings(data); MObject node; defaultGlobals.getDependNode(0, node); MFnDependencyNode fnRenderGlobals(node); MTime tv = MAnimControl::currentTime(); this->currentFrameNumber = (float)(tv.value()); tv = data.frameStart; this->startFrame = (float)(tv.value()); tv = data.frameEnd; this->endFrame = (float)(tv.value()); tv = data.frameBy; this->byFrame = (float)(tv.value()); // check if we are in a batch render mode or if we are rendering from UI if( MGlobal::mayaState() == MGlobal::kBatch ) { this->inBatch = true; if( data.isAnimated() ) { logger.debug(MString("animation on, rendering frame sequence from ") + this->startFrame + " to " + this->endFrame); // these are the frames that are supposed to be rendered in batch mode this->doAnimation = true; for( double frame = this->startFrame; frame <= this->endFrame; frame += this->byFrame) this->frameList.push_back((float)frame); }else{ logger.debug(MString("animation off, rendering current frame")); this->frameList.push_back(this->currentFrameNumber ); this->doAnimation = false; } }else{ // we are rendering from the UI so only render the current frame this->inBatch = false; this->frameList.push_back(this->currentFrameNumber ); this->doAnimation = false; // at the moment, if rendering comes from UI dont do animation } this->imgHeight = data.height; this->imgWidth = data.width; this->pixelAspect = data.pixelAspectRatio; getBool(MString("enableDefaultLight"), fnRenderGlobals, this->createDefaultLight); this->useRenderRegion = false; getBool(MString("useRenderRegion"), fnRenderGlobals, useRenderRegion); this->regionLeft = 0; this->regionRight = this->imgWidth; this->regionBottom = 0; this->regionTop = this->imgHeight; getInt(MString("left"), fnRenderGlobals, regionLeft); getInt(MString("rght"), fnRenderGlobals, regionRight); getInt(MString("bot"), fnRenderGlobals, regionBottom); getInt(MString("top"), fnRenderGlobals, regionTop); getString(MString("preRenderMel"), fnRenderGlobals, this->preFrameScript); getString(MString("postRenderMel"), fnRenderGlobals, this->postFrameScript); getString(MString("preRenderLayerMel"), fnRenderGlobals, this->preRenderLayerScript); getString(MString("postRenderLayerMel"), fnRenderGlobals, this->postRenderLayerScript); this->good = true; return true; }
MStatus ExportACache::doIt( const MArgList& args ) { MStatus status = parseArgs( args ); if( status != MS::kSuccess ) return status; MArgDatabase argData(syntax(), args); MAnimControl timeControl; MTime time = timeControl.currentTime(); int frame =int(time.value()); MString proj; MGlobal::executeCommand( MString ("string $p = `workspace -q -fn`"), proj ); MSelectionList selList; MGlobal::getActiveSelectionList ( selList ); if ( selList.length() == 0 ) { MGlobal:: displayError ( "Nothing is selected!" ); return MS::kSuccess; } MItSelectionList iter( selList ); MString cache_path = proj + "/data/"; MString cache_name; MString scene_name = "untitled"; MString sscat("spaceBS"); MString seye("spaceBS"); if (argData.isFlagSet("-p")) argData.getFlagArgument("-p", 0, cache_path); if (argData.isFlagSet("-t")) argData.getFlagArgument("-t", 0, scene_name); m_space[0][0]=1; m_space[0][1]=0; m_space[0][2]=0; m_space[1][0]=0; m_space[1][1]=1; m_space[1][2]=0; m_space[2][0]=0; m_space[2][1]=0; m_space[2][2]=1; m_space[3][0]=0; m_space[3][1]=0; m_space[3][2]=0; m_eye[0][0]=1; m_eye[0][1]=0; m_eye[0][2]=0; m_eye[1][0]=0; m_eye[1][1]=1; m_eye[1][2]=0; m_eye[2][0]=0; m_eye[2][1]=0; m_eye[2][2]=1; m_eye[3][0]=0; m_eye[3][1]=0; m_eye[3][2]=0; if (argData.isFlagSet("-bc")) { argData.getFlagArgument("-bc", 0, sscat); // get back light space MDagPath p_backscat; AHelper::getTypedPathByName(MFn::kTransform, sscat, p_backscat); MObject o_backscat = p_backscat.transform(); if(o_backscat.isNull()) MGlobal::displayWarning("Cannot find backscat camera, use default space."); else AHelper::getTransformWorldNoScale(p_backscat.partialPathName(), m_space); } if (argData.isFlagSet("-ec")) { argData.getFlagArgument("-ec", 0, seye); // get eye space AHelper::getTypedPathByName(MFn::kTransform, seye, p_eye); MObject o_eye = p_eye.transform(); if(o_eye.isNull()) MGlobal::displayWarning("Cannot find eye camera, use default space."); else AHelper::getTransformWorldNoScale(p_eye.partialPathName(), m_eye); } m_mesh_list.clear(); m_nurbs_list.clear(); for ( ; !iter.isDone(); iter.next() ) { MDagPath meshPath; iter.getDagPath( meshPath ); if( meshPath.hasFn(MFn::kMesh)) m_mesh_list.append(meshPath); if( meshPath.hasFn(MFn::kNurbsSurface)) m_nurbs_list.append(meshPath); } int istart = 1, iend = 1; if(argData.isFlagSet("-fs")) argData.getFlagArgument("-fs", 0, istart); if(argData.isFlagSet("-fe")) argData.getFlagArgument("-fe", 0, iend); // log on start if(frame == istart) MGlobal::displayInfo( MString("acache ") + scene_name + " to " + cache_path); char file_name[512]; sprintf( file_name, "%s/%s.%d.scene", cache_path.asChar(), scene_name.asChar(), frame ); if(frame == istart) save(file_name, frame, 1); else save(file_name, frame, 0); MGlobal::displayInfo( MString("writes frame ") + frame); if(argData.isFlagSet("-ej")) { MString jobparam; argData.getFlagArgument("-ej", 0, jobparam); std::string sjob = file_name; SHelper::cutByFirstDot(sjob); std::string stitle = sjob; sjob = sjob + ".txt"; std::ofstream ffjob; ffjob.open(sjob.c_str(), ios::out); char job_line[1024]; for(int i=istart; i<= iend; i++) { sprintf(job_line, "%s %s.%i.scene\n", jobparam.asChar(), stitle.c_str(), i); ffjob.write((char*)job_line, strlen(job_line)); } ffjob.close(); MGlobal::displayInfo(MString("writes external job script: ") + sjob.c_str()); } return MS::kSuccess; }
MStatus wingVizNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; if(plug == aoutval) { //double dtime = data.inputValue( aframe ).asDouble(); MTime currentTime = data.inputValue(atime, &status).asTime(); float ns = data.inputValue(anoisize).asFloat(); float nf = data.inputValue(anoifreq).asFloat(); int nd = data.inputValue(anoiseed).asInt(); MObject ogrow = data.inputValue(agrowth).asNurbsSurfaceTransformed(); //MArrayDataHandle hArray = data.inputArrayValue(agrowth); //int n_obs = hArray.elementCount(); //MObjectArray obslist; //for(int iter=0; iter<n_obs; iter++) //{ // obslist.append(hArray.inputValue().asNurbsSurfaceTransformed()); // hArray.next(); //} //if(!ogrow.isNull()) m_base->setGrow(ogrow); m_base->setNoise(ns, nf, nd); m_base->setTime(currentTime.value()); m_base->setNurbs(ogrow); //m_base->setWind(m_wind); /*int frame = (int)currentTime.value(); i_show_v = 0; if(data.inputValue(amaxframe, &status).asInt() == 1) { i_show_v = 1; char file_name[512]; sprintf( file_name, "%s/%s.%d.xvn", m_cachename.asChar(), MFnDependencyNode(thisMObject()).name().asChar(), frame ); int start = data.inputValue(aminframe, &status).asInt(); if(start == frame) { m_frame_pre = start; //m_base->init(); m_base->save(file_name); } else if(m_frame_pre+1 == frame) { m_frame_pre++; //m_base->update(); m_base->save(file_name); } }*/ } if(plug== outMesh) { MObject ogrow = data.inputValue(agrowth).asNurbsSurfaceTransformed(); m_base->setNurbs(ogrow); float w0 = data.inputValue(ashaft0).asFloat(); float w1 = data.inputValue(ashaft1).asFloat(); float fw0 = data.inputValue(awidth0).asFloat(); float fw1 = data.inputValue(awidth1).asFloat(); float e0 = data.inputValue(aedge0).asFloat(); float e1 = data.inputValue(aedge1).asFloat(); float t0 = data.inputValue(atwist0).asFloat(); float t1 = data.inputValue(atwist1).asFloat(); int r = data.inputValue(areverse).asInt(); int s = data.inputValue(astep).asInt(); m_base->setReverse(r); m_base->setFeatherWidth(fw0, fw1); m_base->setFeatherEdge(e0, e1); m_base->setShaftWidth(w0, w1); m_base->setFeatherTwist(t0, t1); m_base->setStep(s); MObject outMeshData = m_base->createFeather(); //zDisplayFloat3(m_base->getSeed(), m_base->getSeed1(), m_base->getFract()); MDataHandle meshh = data.outputValue(outMesh, &status); meshh.set(outMeshData); data.setClean(plug); } if(plug== aouttexcoordoffsetpp) { MDoubleArray coeff_array; m_base->getTexcoordOffset(coeff_array); MFnDoubleArrayData coeffFn; MObject coeffOutputData = coeffFn.create( coeff_array, &status ); MDataHandle coeffh = data.outputValue( plug, &status); coeffh.set(coeffOutputData); data.setClean(plug); } return MS::kUnknownParameter; }
MStatus depthMap::doIt( const MArgList& args ) { MStatus status = parseArgs( args ); if( status != MS::kSuccess ) return status; MArgDatabase argData(syntax(), args); MAnimControl timeControl; MTime time = timeControl.currentTime(); int frame =int(time.value()); MString scene_name, camera_name, title; if (argData.isFlagSet("-n")) argData.getFlagArgument("-n", 0, title); else return MS::kFailure; if (argData.isFlagSet("-sc")) argData.getFlagArgument("-sc", 0, scene_name); else return MS::kFailure; if (argData.isFlagSet("-ca")) argData.getFlagArgument("-ca", 0, camera_name); else return MS::kFailure; m_eye[0][0]=1; m_eye[0][1]=0; m_eye[0][2]=0; m_eye[0][3]=0; m_eye[1][0]=0; m_eye[1][1]=1; m_eye[1][2]=0; m_eye[1][3]=0; m_eye[2][0]=0; m_eye[2][1]=0; m_eye[2][2]=1; m_eye[2][3]=0; m_eye[3][0]=0; m_eye[3][1]=0; m_eye[3][2]=0; m_eye[3][3]=1; // get eye space zWorks::getTypedPathByName(MFn::kTransform, camera_name, p_eye); MObject o_eye = p_eye.transform(); if(o_eye.isNull()) MGlobal::displayWarning("Cannot find eye camera, use default space."); else zWorks::getTransformWorldNoScale(p_eye.partialPathName(), m_eye); m_eye[0][0] *=-1; m_eye[0][1] *=-1; m_eye[0][2] *=-1; m_eye[2][0] *=-1; m_eye[2][1] *=-1; m_eye[2][2] *=-1; p_eye.extendToShape(); MFnCamera feye(p_eye); double fov = feye.horizontalFieldOfView(); int map_w = 1024, map_h = 1024; float* data = new float[map_w * map_h]; for(int i=0; i<map_w * map_h; i++) data[i] = 10e6; string sscene = scene_name.asChar(); zGlobal::changeFrameNumber(sscene, frame); MGlobal::displayInfo ( MString(" calculating ") + sscene.c_str()); FXMLScene* fscene = new FXMLScene(); if(fscene->load(sscene.c_str()) != 1) { MGlobal::displayWarning(" cannot open scene, do nothing."); return MS::kFailure; } fscene->depthMap(data, map_w, map_h, fov, m_eye); zGlobal::cutByLastSlash(sscene); sscene = sscene + "/" + title.asChar() + ".1.exr"; zGlobal::changeFrameNumber(sscene, frame); //zGlobal::changeFilenameExtension(sscene, "exr"); MGlobal::displayInfo ( MString(" saving ") + sscene.c_str()); M44f amat(m_eye[0][0], m_eye[0][1], m_eye[0][2], m_eye[0][3], m_eye[1][0], m_eye[1][1], m_eye[1][2], m_eye[1][3], m_eye[2][0], m_eye[2][1], m_eye[2][2], m_eye[2][3], m_eye[3][0], m_eye[3][1], m_eye[3][2], m_eye[3][3] ); ZFnEXR::saveCameraNZ(data, amat, fov, sscene.c_str(), map_w, map_h); delete[] data; delete fscene; return MS::kSuccess; }
bool atomExport::setUpCache(MSelectionList &sList, std::vector<atomCachedPlugs *> &cachedPlugs,atomAnimLayers &animLayers, bool sdk, bool constraint, bool layers, std::set<std::string> &attrStrings, atomTemplateReader &templateReader, MTime &startTime, MTime &endTime, MAngle::Unit angularUnit, MDistance::Unit linearUnit) { if(endTime<startTime) return false; //should never happen but just in case. unsigned int numObjects = sList.length(); cachedPlugs.resize(numObjects); double dStart = startTime.value(); double dEnd = endTime.value() + (.0000001); //little nudge in case of round off errors MTime::Unit unit = startTime.unit(); double tickStep = MTime(1.0,unit).value(); unsigned int numItems = ((unsigned int)((dEnd - dStart)/tickStep)) + 1; bool somethingIsCached = false; //if nothing get's cached no reason to run computation loop for (unsigned int i = 0; i < numObjects; i++) { atomCachedPlugs *plug = NULL; //make sure it's a NULL, and preset it in case we skip this node cachedPlugs[i] = plug; MDagPath path; MObject node; MString name; if (sList.getDagPath (i, path) == MS::kSuccess) { node = path.node(); name = path.partialPathName(); } else if (sList.getDependNode (i, node) == MS::kSuccess) { if (!node.hasFn (MFn::kDependencyNode)) { continue; } MFnDependencyNode fnNode (node); name = fnNode.name(); } if(node.isNull()==false) { if(i< animLayers.length()) { MPlugArray plugs; animLayers.getPlugs(i,plugs); std::set<std::string> tempAttrStrings; atomTemplateReader tempTemplateReader; plug = new atomCachedPlugs(name,node,plugs,sdk,constraint,layers, tempAttrStrings,tempTemplateReader,numItems,angularUnit, linearUnit); if(plug->hasCached() ==false) delete plug; else { cachedPlugs[i] = plug; somethingIsCached = true; } } else { if(templateReader.findNode(name)== false) { continue; } MSelectionList localList; localList.add(node); MPlugArray animatablePlugs; MAnimUtil::findAnimatablePlugs(localList,animatablePlugs); plug = new atomCachedPlugs(name,node,animatablePlugs,sdk,constraint,layers,attrStrings,templateReader,numItems,angularUnit, linearUnit); if(plug->hasCached() ==false) delete plug; else { cachedPlugs[i] = plug; somethingIsCached = true; } } } } bool computationFinished = true; //if no interrupt happens we will finish the computation if(somethingIsCached) { bool hasActiveProgress = false; if (MProgressWindow::reserve()) { hasActiveProgress = true; MProgressWindow::setInterruptable(true); MProgressWindow::startProgress(); MProgressWindow::setProgressRange(0, numObjects); MProgressWindow::setProgress(0); MStatus stringStat; MString msg = MStringResource::getString(kBakingProgress, stringStat); if(stringStat == MS::kSuccess) MProgressWindow::setTitle(msg); } unsigned int count =0; for(double tick = dStart; tick <= dEnd; tick += tickStep) { if(hasActiveProgress) MProgressWindow::setProgress(count); MTime time(tick,unit); MDGContext ctx(time); for(unsigned int z = 0; z< cachedPlugs.size(); ++z) { if(cachedPlugs[z]) cachedPlugs[z]->calculateValue(ctx,count); } if (hasActiveProgress && MProgressWindow::isCancelled()) { computationFinished = false; break; } ++count; } if(hasActiveProgress) MProgressWindow::endProgress(); } return computationFinished; }
MStatus AbcExport::doIt(const MArgList & args) { MStatus status; MTime oldCurTime = MAnimControl::currentTime(); MArgParser argData(syntax(), args, &status); if (status != MS::kSuccess) return status; unsigned int numberOfArguments = args.length(); MString msg; msg += "AbcExport [options] tranlation_jobs_description_string\n\n"; msg += "Options:\n"; msg += "-h / help Print this message.\n"; msg += "\n"; msg += "-sa / startAt float (default: 0.0f)\n"; msg += "The frame to start scene evaluation at. This is used to set\n"; msg += "the starting frame for time dependent translations and can\n"; msg += "be used to add run-up that isn't actually translated.\n"; msg += "\n"; msg += "-sf / skipFrame boolean (default: false)\n"; msg += "When evaluating multiple translate jobs, this flag decides\n"; msg += "whether or not to skip frame if possible.\n"; msg += "\n"; msg += "-sl / selection\n"; msg += "If this flag is present: if tranlation_jobs_description_string\n"; msg += "is empty, write out all nodes from the active selection list;\n"; msg += "if tranlation_jobs_description_string is not empty, write out\n"; msg += "only the nodes in the active selection list.\n"; msg += "\n"; msg += "-d / debug Print debug log\n"; msg += "\n"; msg += "(Each translation job is seperated by ;)\n"; msg += "\n"; msg += "per translation job optional flags:\n"; msg += "\n"; msg += "range float startTime float endTime\n"; msg += "The frame range to write.\n"; msg += "\n"; msg += "uv\n"; msg += "If set, AbcExport will bake the current uv set of polygons\n"; msg += "and subD meshes into property \"st\" on the nodes.\n"; msg += "By default this flag is not set.\n"; msg += "\n"; msg += "shutterOpen float (default: 0.0)\n"; msg += "Motion blur starting time.\n"; msg += "\n"; msg += "shutterClose float (default: 0.0)\n"; msg += "Motion blur end time\n"; msg += "\n"; msg += "numSamples unsigned int (default: 2)\n"; msg += "The number of times to sample within a given frame with\n"; msg += "motion blur applied. If shutterOpen is equal to\n"; msg += "shutterClose then numSamples is ignored.\n"; msg += "\n"; msg += "noSampleGeo\n"; msg += "If set, only write out geometry on whole frames, not\n"; msg += "subframes. This flag is not set by default.\n"; msg += "Transforms may still be written out on subframes.\n"; msg += "\n"; msg += "attrPrefix string (default: SPT_)\n"; msg += "Prefix filter for determining which attributes to write out\n"; msg += "\n"; msg += "attrs string\n"; msg += "Comma seperated list of attributes to write out, these\n"; msg += "attributes will ignore the attr prefix filter.\n"; msg += "\n"; msg += "writeVisibility bool (default: false)\n"; msg += "Whether or not to write the visibility state to the file.\n"; msg += "If false then visibility is not written and everything is\n"; msg += "assumed to be visible.\n"; msg += "\n"; msg += "worldSpace\n"; msg += "If set, the root nodes will be stored in world space.\n"; msg += "By default it is stored in local space.\n"; msg += "\n"; msg += "melPerFrameCallback string (default: "")\n"; msg += "When each frame (and the static frame) is evaluated the\n"; msg += "string specified is evaluated as a Mel command.\n"; msg += "See below for special processing rules.\n"; msg += "Example: melPerFrameCallback print(\"#FRAME#\")\n"; msg += "\n"; msg += "melPostCallback string (default: "")\n"; msg += "When the translation has finished the string specified is\n"; msg += "evaluated as a Mel command.\n"; msg += "See below for special processing rules.\n"; msg += "Example: melPostCallback print(\"Done!\")\n"; msg += "\n"; msg += "pythonPerFrameCallback string (default: "")\n"; msg += "When each frame (and the static frame) is evaluated the\n"; msg += "string specified is evaluated as a python command.\n"; msg += "See below for special processing rules.\n"; msg += "Example: pythonPerFrameCallback print(\"#FRAME#\")\n"; msg += "\n"; msg += "pythonPostCallback string (default: "")\n"; msg += "When the translation has finished the string specified is\n"; msg += "evaluated as a python command.\n"; msg += "See below for special processing rules.\n"; msg += "Example: pythonPostCallback print(\"Done!\")\n"; msg += "\n"; msg += "On the callbacks, special tokens are replaced with other\n"; msg += "data, these tokens and what they are replaced with are as\n"; msg += "follows:\n"; msg += "\n"; msg += "#FRAME# replaced with the frame number being evaluated, if\n"; msg += "the static frame is being evaluated then #FRAME# is not\n"; msg += "replaced. #FRAME# is ignored in the post callbacks.\n"; msg += "\n"; msg += "#BOUNDS# replaced with the bounding box values in minX minY\n"; msg += "minZ maxX maxY maxZ space seperated order.\n"; msg += "\n"; msg += "#BOUNDSARRAY# replaced with the bounding box values as\n"; msg += "above, but in array form. In Mel:\n"; msg += "In Mel: {minX, minY, minZ, maxX, maxY, maxZ}\n"; msg += "In Python: [minX, minY, minZ, maxX, maxY, maxZ]"; msg += "\n"; msg += "Command Examples:\n"; msg += "AbcExport -d -sf \"range 1 24 test_hi test_lo /tmp/test.abc\"\n"; msg += "AbcExport \"worldSpace test_hi /tmp/test_hi.abc\"\n"; msg += "AbcExport \"range 1 24 shutterOpen 0.0 shutterClose 0.5 "; msg += "numSamples 2 test_hi test_lo /tmp/test.abc\"\n"; msg += "AbcExport -d \"range 101 700 test_hi /tmp/test.abc; range 10"; msg += " 55 test_lo /tmp/test1.abc\"\n"; msg += "\n"; msg += "Note that multiple nodes can be written to the same file,\n"; msg += "but these nodes should not have any parenting relationships\n"; msg += "or the job will not be written out.\n"; if (argData.isFlagSet("help")) { MGlobal::displayInfo(msg); return MS::kSuccess; } bool debug = argData.isFlagSet("debug"); // If skipFrame is true, when going through the playback range of the // scene, as much frames are skipped when possible. This could cause // a problem for, time dependent solutions like // particle system / hair simulation bool skipFrame = false; if (argData.isFlagSet("skipFrame")) skipFrame = true; bool useSelectionList = false; if (argData.isFlagSet("selection")) useSelectionList = true; double startEvaluationTime = FLT_MAX; if (argData.isFlagSet("startAt")) { double startAt = 0.0; argData.getFlagArgument("startAt", 0, startAt); startEvaluationTime = startAt; } // Very rudimentary argument parser: no syntax checking at all !!! MString argStr; // status = argData.getCommandArgument(0, argStr); argStr = args.asString(numberOfArguments-1, &status); MStringArray jobStringArray; status = argStr.split(';', jobStringArray); unsigned int jobSize = jobStringArray.length(); if (jobSize == 0) return status; // the frame range we will be iterating over for all jobs, // includes frames which are not skipped and the startAt offset std::set<double> allFrameRange; // this will eventually hold only the animated jobs. // its a list because we will be removing jobs from it std::list < AbcWriteJobPtr > jobList; for (unsigned int jobIndex = 0; jobIndex < jobSize; jobIndex++) { unsigned int argc = 0; // parse the string MString tstr = jobStringArray[jobIndex]; MStringArray strArr; status = tstr.split(' ', strArr); unsigned int length = strArr.length(); double startTime = oldCurTime.value(); double endTime = oldCurTime.value(); double shutterOpen = 0.0; double shutterClose = 0.0; int numSamples = 1; bool sampleGeo = true; // whether or not to subsample geometry bool worldSpace = false; bool writeVisibility = false; bool writeUVs = false; // DAG path array of nodes to be written out as root nodes in the file util::ShapeSet dagPath; // name of the abc file the job will be written into std::string fileName; // the list of frames written into the abc file std::set<double> geoSamples; std::set<double> transSamples; std::string melPerFrameCallback; std::string melPostCallback; std::string pythonPerFrameCallback; std::string pythonPostCallback; // attribute filtering stuff std::string prefixFilter = "SPT_"; std::set<std::string> attribsSet; // parser for each job while (argc < length) { if (strArr[argc] == "range") // range start end { // guard against overruns if (argc + 2 >= length) return MS::kFailure; // looking for two floating point numbers util::isFloat(strArr[argc+1], msg); util::isFloat(strArr[argc+2], msg); startTime = floor(strArr[argc+1].asDouble()); endTime = ceil(strArr[argc+2].asDouble()); // make sure start frame is smaller or equal to endTime if (startTime > endTime) { double temp = startTime; startTime = endTime; endTime = temp; } argc += 3; } else if (strArr[argc] == "uv") { writeUVs = true; argc++; } else if (strArr[argc] == "shutterOpen") { if (argc + 1 >= length) return MS::kFailure; util::isFloat(strArr[argc+1], msg); shutterOpen = strArr[argc+1].asDouble(); argc += 2; } else if (strArr[argc] == "shutterClose") { if (argc + 1 >= length) return MS::kFailure; util::isFloat(strArr[argc+1], msg); shutterClose = strArr[argc+1].asDouble(); argc += 2; } else if (strArr[argc] == "numSamples") { if (argc + 1 >= length) return MS::kFailure; util::isUnsigned(strArr[argc+1], msg); numSamples = strArr[argc+1].asInt(); argc += 2; } else if (strArr[argc] == "writeVisibility") { writeVisibility = true; argc++; } else if (strArr[argc] == "worldSpace") { worldSpace = true; argc++; } else if (strArr[argc] == "noSampleGeo") { sampleGeo = false; argc++; } else if (strArr[argc] == "melPerFrameCallback") { if (argc + 1 >= length) return MS::kFailure; melPerFrameCallback = strArr[argc+1].asChar(); argc += 2; } else if (strArr[argc] == "melPostCallback") { if (argc + 1 >= length) return MS::kFailure; melPostCallback = strArr[argc+1].asChar(); argc += 2; } else if (strArr[argc] == "pythonPerFrameCallback") { if (argc + 1 >= length) return MS::kFailure; pythonPerFrameCallback = strArr[argc+1].asChar(); argc += 2; } else if (strArr[argc] == "pythonPostCallback") { if (argc + 1 >= length) return MS::kFailure; pythonPostCallback = strArr[argc+1].asChar(); argc += 2; } else if (strArr[argc] == "attrPrefix") { if (argc + 1 >= length) return MS::kFailure; prefixFilter = strArr[argc+1].asChar(); argc += 2; } else if (strArr[argc] == "attrs") { if (argc + 1 >= length) return MS::kFailure; MString attrString = strArr[argc+1]; MStringArray attribs; attrString.split(',', attribs); unsigned int attribsLength = attrString.length(); for (unsigned int i = 0; i < attribsLength; ++i) { MString & attrib = attribs[i]; if (attrib != "" && attrib != "visibility") { attribsSet.insert(attrib.asChar()); } } argc += 2; } else // assume in the order of node names and then abc file name { for (; argc < length-1; argc++) { MSelectionList sel; if (!sel.add(strArr[argc])) { MString warn = "Could not select "; warn += strArr[argc]; warn += ". Skipping..."; MGlobal::displayWarning(warn); continue; } MDagPath path; if (!sel.getDagPath(0, path)) { MGlobal::displayWarning( "Not a DAG Node. Skipping... "); continue; } dagPath.insert(path); } // check for validity of the DagPath relationships // complexity : n^2 bool isAncestor = false; if (dagPath.size() > 1) { util::ShapeSet::iterator m, n; const util::ShapeSet::iterator end = dagPath.end(); for (m = dagPath.begin(); m != end; ) { MDagPath path1 = *m; m++; for (n = m; n != end; n++) { MDagPath path2 = *n; if (util::isAncestorDescendentRelationship(path1, path2)) isAncestor = true; } // for n } // for m } if (isAncestor == true) return MS::kFailure; if (argc >= length) return MS::kFailure; fileName = strArr[argc++].asChar(); } } std::set <double> origSamples; for (double f = startTime; f <= endTime; f++) origSamples.insert(f); transSamples = origSamples; geoSamples = origSamples; Alembic::AbcCoreAbstract::v1::chrono_t fps24 = 1/24.0; Alembic::AbcCoreAbstract::v1::TimeSamplingType transTime(fps24); Alembic::AbcCoreAbstract::v1::TimeSamplingType geoTime(fps24); // post process, add extra motion blur samples if (numSamples > 1 && shutterOpen < shutterClose) { transTime = Alembic::AbcCoreAbstract::v1::TimeSamplingType( numSamples, fps24); // if we are't subsampling the geometry, leave it as uniform if (sampleGeo) geoTime = transTime; std::set<double> offsetSamples; offsetSamples.insert(shutterOpen); offsetSamples.insert(shutterClose); double offset = (shutterClose - shutterOpen) / (numSamples-1); double curVal = shutterOpen + offset; for (int i = 0; i < numSamples - 2; ++i, curVal += offset) { offsetSamples.insert(curVal); } // Add an extra leading or trailing frame on an // integer boundary for the rest of the pipeline double floorVal = floor(startTime + shutterOpen); double ceilVal = ceil(endTime + shutterClose); transSamples.insert(floorVal); transSamples.insert(ceilVal); geoSamples.insert(floorVal); geoSamples.insert(ceilVal); std::set<double>::iterator samp = origSamples.begin(); std::set<double>::iterator sampEnd = origSamples.end(); for (; samp != sampEnd; ++samp) { double curSamp = *samp; std::set<double>::iterator offset = offsetSamples.begin(); std::set<double>::iterator offsetEnd = offsetSamples.end(); for (; offset != offsetEnd; ++offset) { double curVal = curSamp + (*offset); double rndVal = roundf(curVal); // if the value is close enough to the integer value // insert the integer value if (fabs(curVal - rndVal) < 1e-4) { transSamples.insert(rndVal); // ignore geometry sampling flag because it is a whole // frame and for some reason we always want to // translate the whole frames geoSamples.insert(rndVal); } else if (sampleGeo) { transSamples.insert(curVal); geoSamples.insert(curVal); } else { // we aren't include subsampled geometry transSamples.insert(curVal); } } // for offset } // for samp } // if we need to apply motion blur AbcWriteJobPtr job(new AbcWriteJob(dagPath, fileName.c_str(), useSelectionList, worldSpace, writeVisibility, writeUVs, transSamples, transTime, geoSamples, geoTime, melPerFrameCallback, melPostCallback, pythonPerFrameCallback, pythonPostCallback, prefixFilter, attribsSet)); jobList.push_front(job); // make sure we add additional whole frames, if we arent skipping // the inbetween ones if (!skipFrame && !allFrameRange.empty() && !transSamples.empty()) { double localMin = *(transSamples.begin()); std::set<double>::iterator last = transSamples.end(); last--; double localMax = *last; double globalMin = *(allFrameRange.begin()); last = allFrameRange.end(); last--; double globalMax = *last; // if the min of our current frame range is beyond // what we know about, pad a few more frames if (localMin > globalMax) { for (double f = globalMax; f < localMin; f++) { allFrameRange.insert(f); } } // if the max of our current frame range is beyond // what we know about, pad a few more frames if (localMax < globalMin) { for (double f = localMax; f < globalMin; f++) { allFrameRange.insert(f); } } } // right now we just copy over the translation samples since // they are guaranteed to contain all the geometry samples if (!transSamples.empty()) allFrameRange.insert(transSamples.begin(), transSamples.end()); } // ================ end of argument parsing ========================= // add extra evaluation run up, if necessary if (startEvaluationTime != FLT_MAX && !allFrameRange.empty()) { double firstFrame = *allFrameRange.begin(); for (double f = startEvaluationTime; f < firstFrame; ++f) { allFrameRange.insert(f); } } std::set<double>::iterator it = allFrameRange.begin(); std::set<double>::iterator itEnd = allFrameRange.end(); // loop through every frame in the list, if a job has that frame in it's // list of transform or shape frames, then it will write out data and // call the perFrameCallback, if that frame is also the last one it has // to work on then it will also call the postCallback. // If it doesn't have this frame, then it does nothing for (; it != itEnd; it++) { if (debug) { double frame = *it; MString info; info = frame; MGlobal::displayInfo(info); } MGlobal::viewFrame(*it); std::list< AbcWriteJobPtr >::iterator j = jobList.begin(); std::list< AbcWriteJobPtr >::iterator jend = jobList.end(); while (j != jend) { bool lastFrame = (*j)->eval(*it); // if (lastFrame) { j = jobList.erase(j); } else j++; } } // set the time back MGlobal::viewFrame(oldCurTime); return MS::kSuccess; }