// // Selects objects within the user defined area, then process them // MStatus meshRemapTool::doRelease( MEvent & event ) { char buf[1024]; // Perform the base actions MStatus stat = MPxSelectionContext::doRelease(event); // Get the list of selected items MGlobal::getActiveSelectionList( fSelectionList ); // // If there's nothing selected, don't worry about it, just return // if( fSelectionList.length() != 1 ) { MGlobal::displayWarning( "Components must be selected one at a time" ); return MS::kSuccess; } // // Get the selection's details, we must have exactly one component selected // MObject component; MDagPath path; MItSelectionList selectionIt (fSelectionList, MFn::kComponent); MStringArray selections; selectionIt.getStrings( selections ); if( selections.length() != 1 ) { MGlobal::displayError( "Components must be selected one at a time" ); return MS::kSuccess; } if (selectionIt.isDone ()) { MGlobal::displayError( "Selected Item not a component" ); return MS::kSuccess; } if( selectionIt.getDagPath (path, component) != MStatus::kSuccess ) { MGlobal::displayError( "Can't get path for selection"); return MS::kSuccess; } if (!path.node().hasFn(MFn::kMesh) && !(path.node().hasFn(MFn::kTransform) && path.hasFn(MFn::kMesh))) { MGlobal::displayError( " Invalid type! Only a mesh or its transform can be specified." ); return MS::kSuccess; } MItMeshVertex fIt ( path, component, &stat ); if( stat != MStatus::kSuccess ) { MGlobal::displayError( " MItMeshVertex failed"); return MStatus::kFailure; } if (fIt.count() != 1 ) { sprintf(buf, " Invalid selection '%s'. Vertices must be picked one at a time.", selections[0].asChar() ); MGlobal::displayError( buf ); return MS::kSuccess; } else { sprintf(buf, "Accepting vertex '%s'", selections[0].asChar() ); MGlobal::displayInfo( buf ); } // // Now that we know it's valid, process the selection, the first 3 items are the source, the second // 3 define the target // if( fNumSelectedPoints < 3 ) { fSelectedPathSrc.append( path ); fSelectedComponentSrc.append( component ); } else { fSelectedPathDst.append( path ); fSelectedComponentDst.append( component ); } // // When each of the source/target are defined, process them. An error/invalid selection will restart the selection for // that particular mesh. // if( fNumSelectedPoints == 2 ) { if( ( stat = meshMapUtils::validateFaceSelection( fSelectedPathSrc, fSelectedComponentSrc, &fSelectedFaceSrc, &fSelectVtxSrc ) ) != MStatus::kSuccess ) { MGlobal::displayError("Selected vertices don't define a unique face on source mesh"); reset(); return stat; } } // // Once the target is defined, invoke the command // if( fNumSelectedPoints == 5 ) { if( ( stat = meshMapUtils::validateFaceSelection( fSelectedPathDst, fSelectedComponentDst, &fSelectedFaceDst, &fSelectVtxDst ) ) != MStatus::kSuccess ) { MGlobal::displayError("Selected vertices don't define a unique face on source mesh"); reset(); return stat; } fCmd = new meshRemapCommand; fCmd->setSeedInfo( true, fSelectedPathSrc[0], fSelectedFaceSrc, fSelectVtxSrc[0], fSelectVtxSrc[1] ); fCmd->setSeedInfo( false, fSelectedPathDst[0], fSelectedFaceDst, fSelectVtxDst[0], fSelectVtxDst[1] ); fCmd->redoIt(); // // Empty the selection list since the reodering may move the user's current selection on screen // MSelectionList empty; MGlobal::setActiveSelectionList( empty ); MGlobal::displayInfo( "Mesh remapping complete" ); // // Start again, get new meshes // reset(); } else { // // We don't have all the details yet, just move to the next item // fNumSelectedPoints++; } helpStateHasChanged(); return stat; }
void maTranslator::getAddAttrCmds(const MObject& node, MStringArray& cmds) { // // Run through the node's attributes. // MFnDependencyNode nodeFn(node); unsigned int numAttrs = nodeFn.attributeCount(); unsigned int i; for (i = 0; i < numAttrs; i++) { // // Use the attribute ordering which Maya uses when doing I/O. // MObject attr = nodeFn.reorderedAttribute(i); // // If this attribute has been added since the node was created, // then we may want to write out an addAttr statement for it. // if (nodeFn.isNewAttribute(attr)) { MFnAttribute attrFn(attr); // // If the attribute has a parent then ignore it because it will // be processed when we process the parent. // MStatus status; attrFn.parent(&status); if (status == MS::kNotFound) { // // If the attribute is a compound, then we can do its entire // tree at once. // MFnCompoundAttribute cAttrFn(attr, &status); if (status) { MStringArray newCmds; cAttrFn.getAddAttrCmds(newCmds); unsigned int numCommands = newCmds.length(); unsigned int c; for (c = 0; c < numCommands; c++) { if (newCmds[c] != "") cmds.append(newCmds[c]); } } else { MString newCmd = attrFn.getAddAttrCmd(); if (newCmd != "") cmds.append(newCmd); } } } } }
MStatus animImport::reader( const MFileObject& file, const MString& options, FileAccessMode mode) { MStatus status = MS::kFailure; MString fileName = file.fullName(); #if defined (OSMac_) char fname[MAXPATHLEN]; strcpy (fname, fileName.asChar()); ifstream animFile(fname); #else ifstream animFile(fileName.asChar()); #endif // Parse the options. The options syntax is in the form of // "flag=val;flag1=val;flag2=val" // MString pasteFlags; if (options.length() > 0) { // Set up the flags for the paste command. // const MString flagTargetTime("targetTime"); const MString flagTime("time"); const MString flagCopies("copies"); const MString flagOption("option"); const MString flagConnect("connect"); MString copyValue; MString flagValue; MString connectValue; MString timeValue; // Start parsing. // MStringArray optionList; MStringArray theOption; options.split(';', optionList); unsigned nOptions = optionList.length(); for (unsigned i = 0; i < nOptions; i++) { theOption.clear(); optionList[i].split('=', theOption); if (theOption.length() < 1) { continue; } if (theOption[0] == flagCopies && theOption.length() > 1) { copyValue = theOption[1];; } else if (theOption[0] == flagOption && theOption.length() > 1) { flagValue = theOption[1]; } else if (theOption[0] == flagConnect && theOption.length() > 1) { if (theOption[1].asInt() != 0) { connectValue += theOption[1]; } } else if (theOption[0] == flagTime && theOption.length() > 1) { timeValue += theOption[1]; } } if (copyValue.length() > 0) { pasteFlags += " -copies "; pasteFlags += copyValue; pasteFlags += " "; } if (flagValue.length() > 0) { pasteFlags += " -option \""; pasteFlags += flagValue; pasteFlags += "\" "; } if (connectValue.length() > 0) { pasteFlags += " -connect "; pasteFlags += connectValue; pasteFlags += " "; } if (timeValue.length() > 0) { bool useQuotes = !timeValue.isDouble(); pasteFlags += " -time "; if (useQuotes) pasteFlags += "\""; pasteFlags += timeValue; if (useQuotes) pasteFlags += "\""; pasteFlags += " "; } } if (mode == kImportAccessMode) { status = importAnim(animFile, pasteFlags); } animFile.close(); return status; }
MStatus AlembicExportCommand::doIt(const MArgList &args) { ESS_PROFILE_SCOPE("AlembicExportCommand::doIt"); MStatus status = MS::kFailure; MTime currentAnimStartTime = MAnimControl::animationStartTime(), currentAnimEndTime = MAnimControl::animationEndTime(), oldCurTime = MAnimControl::currentTime(), curMinTime = MAnimControl::minTime(), curMaxTime = MAnimControl::maxTime(); MArgParser argData(syntax(), args, &status); if (argData.isFlagSet("help")) { // TODO: implement help for this command // MGlobal::displayInfo(util::getHelpText()); return MS::kSuccess; } unsigned int jobCount = argData.numberOfFlagUses("jobArg"); MStringArray jobStrings; if (jobCount == 0) { // TODO: display dialog MGlobal::displayError("[ExocortexAlembic] No jobs specified."); MPxCommand::setResult( "Error caught in AlembicExportCommand::doIt: no job specified"); return status; } else { // get all of the jobstrings for (unsigned int i = 0; i < jobCount; i++) { MArgList jobArgList; argData.getFlagArgumentList("jobArg", i, jobArgList); jobStrings.append(jobArgList.asString(0)); } } // create a vector to store the jobs std::vector<AlembicWriteJob *> jobPtrs; double minFrame = 1000000.0; double maxFrame = -1000000.0; double maxSteps = 1; double maxSubsteps = 1; // init the curve accumulators AlembicCurveAccumulator::Initialize(); try { // for each job, check the arguments bool failure = false; for (unsigned int i = 0; i < jobStrings.length(); ++i) { double frameIn = 1.0; double frameOut = 1.0; double frameSteps = 1.0; double frameSubSteps = 1.0; MString filename; bool purepointcache = false; bool normals = true; bool uvs = true; bool facesets = true; bool bindpose = true; bool dynamictopology = false; bool globalspace = false; bool withouthierarchy = false; bool transformcache = false; bool useInitShadGrp = false; bool useOgawa = false; // Later, will need to be changed! // Each frames to export can manually be specified via the "frames" parameter. // This allow for very specific frames to be exported. // In our case (Squeeze Studio) this allow the animator to export only specific subframes. // The advantage of exporting specific subframes instead of using the "substep" parameter is that the animator don't have to // fix all the flipping occuring in a rig when trying to work with substeps. MDoubleArray frames; MStringArray objectStrings; std::vector<std::string> prefixFilters; std::set<std::string> attributes; std::vector<std::string> userPrefixFilters; std::set<std::string> userAttributes; MObjectArray objects; std::string search_str, replace_str; // process all tokens of the job MStringArray tokens; jobStrings[i].split(';', tokens); for (unsigned int j = 0; j < tokens.length(); j++) { MStringArray valuePair; tokens[j].split('=', valuePair); if (valuePair.length() != 2) { MGlobal::displayWarning( "[ExocortexAlembic] Skipping invalid token: " + tokens[j]); continue; } const MString &lowerValue = valuePair[0].toLowerCase(); if (lowerValue == "in") { frameIn = valuePair[1].asDouble(); } else if (lowerValue == "out") { frameOut = valuePair[1].asDouble(); } else if (lowerValue == "step") { frameSteps = valuePair[1].asDouble(); } else if (lowerValue == "substep") { frameSubSteps = valuePair[1].asDouble(); } else if (lowerValue == "normals") { normals = valuePair[1].asInt() != 0; } else if (lowerValue == "uvs") { uvs = valuePair[1].asInt() != 0; } else if (lowerValue == "facesets") { facesets = valuePair[1].asInt() != 0; } else if (lowerValue == "bindpose") { bindpose = valuePair[1].asInt() != 0; } else if (lowerValue == "purepointcache") { purepointcache = valuePair[1].asInt() != 0; } else if (lowerValue == "dynamictopology") { dynamictopology = valuePair[1].asInt() != 0; } else if (lowerValue == "globalspace") { globalspace = valuePair[1].asInt() != 0; } else if (lowerValue == "withouthierarchy") { withouthierarchy = valuePair[1].asInt() != 0; } else if (lowerValue == "transformcache") { transformcache = valuePair[1].asInt() != 0; } else if (lowerValue == "filename") { filename = valuePair[1]; } else if (lowerValue == "objects") { // try to find each object valuePair[1].split(',', objectStrings); } else if (lowerValue == "useinitshadgrp") { useInitShadGrp = valuePair[1].asInt() != 0; } // search/replace else if (lowerValue == "search") { search_str = valuePair[1].asChar(); } else if (lowerValue == "replace") { replace_str = valuePair[1].asChar(); } else if (lowerValue == "ogawa") { useOgawa = valuePair[1].asInt() != 0; } else if(lowerValue == "frames") { MStringArray strFrames; valuePair[1].split(',', strFrames); for(unsigned int i=0;i<strFrames.length();i++) { double frame = strFrames[i].asDouble(); frames.append(frame); } } else if (lowerValue == "attrprefixes") { splitListArg(valuePair[1], prefixFilters); } else if (lowerValue == "attrs") { splitListArg(valuePair[1], attributes); } else if (lowerValue == "userattrprefixes") { splitListArg(valuePair[1], userPrefixFilters); } else if (lowerValue == "userattrs") { splitListArg(valuePair[1], userAttributes); } else { MGlobal::displayWarning( "[ExocortexAlembic] Skipping invalid token: " + tokens[j]); continue; } } // now check the object strings for (unsigned int k = 0; k < objectStrings.length(); k++) { MSelectionList sl; MString objectString = objectStrings[k]; sl.add(objectString); MDagPath dag; for (unsigned int l = 0; l < sl.length(); l++) { sl.getDagPath(l, dag); MObject objRef = dag.node(); if (objRef.isNull()) { MGlobal::displayWarning("[ExocortexAlembic] Skipping object '" + objectStrings[k] + "', not found."); break; } // get all parents MObjectArray parents; // check if this is a camera bool isCamera = false; for (unsigned int m = 0; m < dag.childCount(); ++m) { MFnDagNode child(dag.child(m)); MFn::Type ctype = child.object().apiType(); if (ctype == MFn::kCamera) { isCamera = true; break; } } if (dag.node().apiType() == MFn::kTransform && !isCamera && !globalspace && !withouthierarchy) { MDagPath ppath = dag; while (!ppath.node().isNull() && ppath.length() > 0 && ppath.isValid()) { parents.append(ppath.node()); if (ppath.pop() != MStatus::kSuccess) { break; } } } else { parents.append(dag.node()); } // push all parents in while (parents.length() > 0) { bool found = false; for (unsigned int m = 0; m < objects.length(); m++) { if (objects[m] == parents[parents.length() - 1]) { found = true; break; } } if (!found) { objects.append(parents[parents.length() - 1]); } parents.remove(parents.length() - 1); } // check all of the shapes below if (!transformcache) { sl.getDagPath(l, dag); for (unsigned int m = 0; m < dag.childCount(); m++) { MFnDagNode child(dag.child(m)); if (child.isIntermediateObject()) { continue; } objects.append(child.object()); } } } } // check if we have incompatible subframes if (maxSubsteps > 1.0 && frameSubSteps > 1.0) { const double part = (frameSubSteps > maxSubsteps) ? (frameSubSteps / maxSubsteps) : (maxSubsteps / frameSubSteps); if (abs(part - floor(part)) > 0.001) { MString frameSubStepsStr, maxSubstepsStr; frameSubStepsStr.set(frameSubSteps); maxSubstepsStr.set(maxSubsteps); MGlobal::displayError( "[ExocortexAlembic] You cannot combine substeps " + frameSubStepsStr + " and " + maxSubstepsStr + " in one export. Aborting."); return MStatus::kInvalidParameter; } } // remember the min and max values for the frames if (frameIn < minFrame) { minFrame = frameIn; } if (frameOut > maxFrame) { maxFrame = frameOut; } if (frameSteps > maxSteps) { maxSteps = frameSteps; } if (frameSteps > 1.0) { frameSubSteps = 1.0; } if (frameSubSteps > maxSubsteps) { maxSubsteps = frameSubSteps; } // check if we have a filename if (filename.length() == 0) { MGlobal::displayError("[ExocortexAlembic] No filename specified."); for (size_t k = 0; k < jobPtrs.size(); k++) { delete (jobPtrs[k]); } MPxCommand::setResult( "Error caught in AlembicExportCommand::doIt: no filename " "specified"); return MStatus::kFailure; } // construct the frames if they are not already provided if (frames.length() == 0) { const double frameIncr = frameSteps / frameSubSteps; for (double frame = frameIn; frame <= frameOut; frame += frameIncr) { frames.append(frame); } } AlembicWriteJob *job = new AlembicWriteJob(filename, objects, frames, useOgawa, prefixFilters, attributes, userPrefixFilters, userAttributes); job->SetOption("exportNormals", normals ? "1" : "0"); job->SetOption("exportUVs", uvs ? "1" : "0"); job->SetOption("exportFaceSets", facesets ? "1" : "0"); job->SetOption("exportInitShadGrp", useInitShadGrp ? "1" : "0"); job->SetOption("exportBindPose", bindpose ? "1" : "0"); job->SetOption("exportPurePointCache", purepointcache ? "1" : "0"); job->SetOption("exportDynamicTopology", dynamictopology ? "1" : "0"); job->SetOption("indexedNormals", "1"); job->SetOption("indexedUVs", "1"); job->SetOption("exportInGlobalSpace", globalspace ? "1" : "0"); job->SetOption("flattenHierarchy", withouthierarchy ? "1" : "0"); job->SetOption("transformCache", transformcache ? "1" : "0"); // check if the search/replace strings are valid! if (search_str.length() ? !replace_str.length() : replace_str.length()) // either search or // replace string is // missing or empty! { ESS_LOG_WARNING( "Missing search or replace parameter. No strings will be " "replaced."); job->replacer = SearchReplace::createReplacer(); } else { job->replacer = SearchReplace::createReplacer(search_str, replace_str); } // check if the job is satifsied if (job->PreProcess() != MStatus::kSuccess) { MGlobal::displayError("[ExocortexAlembic] Job skipped. Not satisfied."); delete (job); failure = true; break; } // push the job to our registry MGlobal::displayInfo("[ExocortexAlembic] Using WriteJob:" + jobStrings[i]); jobPtrs.push_back(job); } if (failure) { for (size_t k = 0; k < jobPtrs.size(); k++) { delete (jobPtrs[k]); } return MS::kFailure; } // compute the job count unsigned int jobFrameCount = 0; for (size_t i = 0; i < jobPtrs.size(); i++) jobFrameCount += (unsigned int)jobPtrs[i]->GetNbObjects() * (unsigned int)jobPtrs[i]->GetFrames().size(); // now, let's run through all frames, and process the jobs const double frameRate = MTime(1.0, MTime::kSeconds).as(MTime::uiUnit()); const double incrSteps = maxSteps / maxSubsteps; double frame; double nextFrame = minFrame + incrSteps; /* for (double frame = minFrame; frame <= maxFrame; frame += incrSteps, nextFrame += incrSteps) { MAnimControl::setCurrentTime(MTime(frame / frameRate, MTime::kSeconds)); MAnimControl::setAnimationEndTime( MTime(nextFrame / frameRate, MTime::kSeconds)); MAnimControl::playForward(); // this way, it forces Maya to play exactly // one frame! and particles are updated! AlembicCurveAccumulator::StartRecordingFrame(); for (size_t i = 0; i < jobPtrs.size(); i++) { MStatus status = jobPtrs[i]->Process(frame); if (status != MStatus::kSuccess) { MGlobal::displayError("[ExocortexAlembic] Job aborted :" + jobPtrs[i]->GetFileName()); for (size_t k = 0; k < jobPtrs.size(); k++) { delete (jobPtrs[k]); } restoreOldTime(currentAnimStartTime, currentAnimEndTime, oldCurTime, curMinTime, curMaxTime); return status; } } AlembicCurveAccumulator::StopRecordingFrame(); } */ // Collect all job frames std::vector<double> all_frames; for(size_t i=0;i<jobPtrs.size();i++) { const std::vector<double> jobFrames = jobPtrs[i]->GetFrames(); for (unsigned int j=0;j<jobFrames.size();++j) { all_frames.push_back(jobFrames[j]); } } // Force Maya to play the animation in sequence. This way particles are updated. unsigned int num_frames_to_export = all_frames.size(); all_frames.push_back(all_frames[num_frames_to_export -1] + incrSteps); for (unsigned int i=0;i<num_frames_to_export;++i) { frame = all_frames[i]; nextFrame = all_frames[i+1]; // debuging MString msg = "Exporting frame "; msg += frame; msg += ". Next is "; msg += nextFrame; MGlobal::displayInfo(msg); MAnimControl::setCurrentTime(MTime(frame/frameRate,MTime::kSeconds)); MAnimControl::setAnimationEndTime( MTime(nextFrame/frameRate,MTime::kSeconds) ); MAnimControl::playForward(); // this way, it forces Maya to play exactly one frame! and particles are updated! AlembicCurveAccumulator::StartRecordingFrame(); for(size_t i=0;i<jobPtrs.size();i++) { MStatus status = jobPtrs[i]->Process(frame); if(status != MStatus::kSuccess) { MGlobal::displayError("[ExocortexAlembic] Job aborted :"+jobPtrs[i]->GetFileName()); for(size_t k=0;k<jobPtrs.size();k++) { delete(jobPtrs[k]); } restoreOldTime(currentAnimStartTime, currentAnimEndTime, oldCurTime, curMinTime, curMaxTime); return status; } } AlembicCurveAccumulator::StopRecordingFrame(); } } catch (...) { MGlobal::displayError( "[ExocortexAlembic] Jobs aborted, force closing all archives!"); for (std::vector<AlembicWriteJob *>::iterator beg = jobPtrs.begin(); beg != jobPtrs.end(); ++beg) { (*beg)->forceCloseArchive(); } restoreOldTime(currentAnimStartTime, currentAnimEndTime, oldCurTime, curMinTime, curMaxTime); MPxCommand::setResult("Error caught in AlembicExportCommand::doIt"); status = MS::kFailure; } MAnimControl::stop(); AlembicCurveAccumulator::Destroy(); // restore the animation start/end time and the current time! restoreOldTime(currentAnimStartTime, currentAnimEndTime, oldCurTime, curMinTime, curMaxTime); // delete all jobs for (size_t k = 0; k < jobPtrs.size(); k++) { delete (jobPtrs[k]); } // remove all known archives deleteAllArchives(); return status; }
// Custom parsing to support array argument. Not using MSyntax. MStatus skinClusterWeights::parseArgs( const MArgList& args ) { MStatus status = MS::kSuccess; MObject node; MDagPath dagPath; MSelectionList selList; editUsed = true; queryUsed = false; unsigned int i, nth = 0; unsigned int numArgs = args.length(); while(status == MS::kSuccess && nth < numArgs-1) { MString inputString = args.asString(nth, &status); if (status != MS::kSuccess) { MGlobal::displayError("skinClusterWeights syntax error"); return status; } if (inputString == kEditFlag || inputString == kEditFlagLong) { editUsed = true; queryUsed = false; nth++; continue; } if (inputString == kQueryFlag || inputString == kQueryFlagLong) { queryUsed = true; editUsed = false; nth++; continue; } if (inputString == kInfluenceFlag || inputString == kInfluenceFlagLong) { nth++; MStringArray stringArray = args.asStringArray(nth, &status); selList.clear(); for (i = 0; i < stringArray.length(); i++) { selList.add(stringArray[i]); } for (i = 0; i < selList.length(); i++) { status = selList.getDagPath(i, dagPath); if (status == MS::kSuccess && dagPath.hasFn(MFn::kTransform)) { influenceArray.append(dagPath); } else { MGlobal::displayError(inputString + " is not a valid influence object.\n"); return status; } } nth++; continue; } if (inputString == kSkinClusterFlag || inputString == kSkinClusterFlagLong) { nth++; MStringArray stringArray = args.asStringArray(nth, &status); selList.clear(); for (i = 0; i < stringArray.length(); i++) { selList.add(stringArray[i]); } for (i = 0; i < selList.length(); i++) { status = selList.getDependNode(i, node); if (status == MS::kSuccess && node.hasFn(MFn::kSkinClusterFilter)) { skinClusterArray.append(node); } else { MGlobal::displayError(inputString + " is not a valid skinCluster.\n"); return status; } } nth++; continue; } if (inputString == kWeightFlag || inputString == kWeightFlagLong) { nth++; weightArray = args.asDoubleArray(nth, &status); if (status != MS::kSuccess) { MGlobal::displayError("error while parsing weight array"); } nth++; continue; } if (inputString == kAssignAllToSingleFlag || inputString == kAssignAllToSingleFlagLong) { assignAllToSingle = true; nth++; continue; } MGlobal::displayError("invalid command syntax at " + inputString); return MS::kFailure; } // parse command objects // nth should equals to numArgs-1 at this point geometryArray = args.asStringArray(nth, &status); if (status != MS::kSuccess) { MGlobal::displayError("Command object invalid"); return status; } if (queryUsed) { if (assignAllToSingle) { MGlobal::displayWarning("-as/-assignAllToSingle is ignored with query flag"); } if (weightArray.length() > 0) { MGlobal::displayWarning("-w/-weights is ignored with query flag"); } } return status; }
void Helper4::addVariableSS(const std::string& param_name_as, const std::string& param_type_as, const std::string& param_name_maya ) { //std::string ss_name(getSurfaceShaderName(m_nodename,m_ss_model)); asr::ParamArray ss_params; { std::string param_value; const std::string plugName(param_name_maya); MString fullPlugName((m_nodename+"."+plugName).c_str()); int connected = liquidmaya::ShaderMgr::getSingletonPtr()->convertibleConnection(fullPlugName.asChar()); if(connected ==0) { if( isType("color", param_type_as) ) { MDoubleArray val; val.setLength(3); IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", val)); param_value = m_nodename+"_"+plugName; createColor3(m_assembly->colors(), param_value.c_str(), val[0], val[1], val[2]); } else if( isType("scalar", param_type_as) ) { MDoubleArray val; val.setLength(3); IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", val)); //val contains (r,b,g) value, but I only use val[0] for 'scalar' MString strVal0; strVal0.set(val[0]); param_value = strVal0.asChar(); } else if( isType("string", param_type_as)) { MString val; IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", val)); param_value = val.asChar(); } else { liquidMessage2(messageWarning,"only [color],[scalar],[string] are handled for an unconnected plug in Surface Shader. " "the plug of %s is unhandled.", fullPlugName.asChar()); param_value = "unhandled"; } } else if(connected == 1)//the plug is linked in. { if( isType("texture_instance", param_type_as) ) { MStringArray srcPlug; IfMErrorWarn(MGlobal::executeCommand("listConnections -source true -plugs true \""+fullPlugName+"\"", srcPlug)); assert(srcPlug.length()==1); MStringArray src; srcPlug[0].split('.',src); MString srcNode(src[0]); if( is2DTexture(srcNode) || is3DTexture(srcNode) ) { //visitFile(srcNode.asChar()); param_value = getTextureInstanceName(srcNode.asChar()); }else{ liquidMessage2(messageWarning,"only [texture2D],[texture3D] are handled for a texture_instance connected-in plug in Surface Shader." "the plug of %s is unhandled.", fullPlugName.asChar()); param_value = "unhandled"; } } else{ liquidMessage2(messageWarning,"only [texture_instance] is handled for a connected-in plug in Surface Shader." "the plug of %s is unhandled.", fullPlugName.asChar()); param_value = "unhandled"; } }else{ liquidMessage2(messageWarning,"[%s] is connected out.", fullPlugName.asChar()); } // addVariableSS(param_name_as, param_value); } }
// Load texture data from a texture node MStatus Material::loadTexture(MFnDependencyNode* pTexNode,TexOpType& opType,MStringArray& uvsets,ParamList& params) { Texture tex; // Get texture filename MString filename, absFilename; MRenderUtil::exactFileTextureName(pTexNode->object(),absFilename); filename = absFilename.substring(absFilename.rindex('/')+1,absFilename.length()-1); MString command = "toNativePath(\""; command += absFilename; command += "\")"; MGlobal::executeCommand(command,absFilename); tex.absFilename = absFilename; tex.filename = filename; tex.uvsetIndex = 0; tex.uvsetName = ""; // Set texture operation type tex.opType = opType; // Get connections to uvCoord attribute of texture node MPlugArray texSrcPlugs; pTexNode->findPlug("uvCoord").connectedTo(texSrcPlugs,true,false); // Get place2dtexture node (if connected) MFnDependencyNode* pPlace2dTexNode = NULL; for (int j=0; j<texSrcPlugs.length(); j++) { if (texSrcPlugs[j].node().hasFn(MFn::kPlace2dTexture)) { pPlace2dTexNode = new MFnDependencyNode(texSrcPlugs[j].node()); continue; } } // Get uvChooser node (if connected) MFnDependencyNode* pUvChooserNode = NULL; if (pPlace2dTexNode) { MPlugArray placetexSrcPlugs; pPlace2dTexNode->findPlug("uvCoord").connectedTo(placetexSrcPlugs,true,false); for (int j=0; j<placetexSrcPlugs.length(); j++) { if (placetexSrcPlugs[j].node().hasFn(MFn::kUvChooser)) { pUvChooserNode = new MFnDependencyNode(placetexSrcPlugs[j].node()); continue; } } } // Get uvset index if (pUvChooserNode) { bool foundMesh = false; bool foundUvset = false; MPlug uvsetsPlug = pUvChooserNode->findPlug("uvSets"); MPlugArray uvsetsSrcPlugs; for (int i=0; i<uvsetsPlug.evaluateNumElements() && !foundMesh; i++) { uvsetsPlug[i].connectedTo(uvsetsSrcPlugs,true,false); for (int j=0; j<uvsetsSrcPlugs.length() && !foundMesh; j++) { if (uvsetsSrcPlugs[j].node().hasFn(MFn::kMesh)) { uvsetsSrcPlugs[j].getValue(tex.uvsetName); for (int k=0; k<uvsets.length() && !foundUvset; k++) { if (uvsets[k] == tex.uvsetName) { tex.uvsetIndex = k; foundUvset = true; } } } } } } // Get texture options from Place2dTexture node if (pPlace2dTexNode) { // Get address mode //U bool wrapU, mirrorU; pPlace2dTexNode->findPlug("wrapU").getValue(wrapU); pPlace2dTexNode->findPlug("mirrorU").getValue(mirrorU); if (mirrorU) tex.am_u = TAM_MIRROR; else if (wrapU) tex.am_u = TAM_WRAP; else tex.am_u = TAM_CLAMP; // V bool wrapV,mirrorV; pPlace2dTexNode->findPlug("wrapV").getValue(wrapV); pPlace2dTexNode->findPlug("mirrorV").getValue(mirrorV); if (mirrorV) tex.am_v = TAM_MIRROR; else if (wrapV) tex.am_v = TAM_WRAP; else tex.am_v = TAM_CLAMP; // Get texture scale double covU,covV; pPlace2dTexNode->findPlug("coverageU").getValue(covU); pPlace2dTexNode->findPlug("coverageV").getValue(covV); tex.scale_u = covU; if (fabs(tex.scale_u) < PRECISION) tex.scale_u = 0; tex.scale_v = covV; if (fabs(tex.scale_v) < PRECISION) tex.scale_v = 0; // Get texture scroll double transU,transV; pPlace2dTexNode->findPlug("translateFrameU").getValue(transU); pPlace2dTexNode->findPlug("translateFrameV").getValue(transV); tex.scroll_u = -0.5 * (covU-1.0)/covU - transU/covU; if (fabs(tex.scroll_u) < PRECISION) tex.scroll_u = 0; tex.scroll_v = 0.5 * (covV-1.0)/covV + transV/covV; if (fabs(tex.scroll_v) < PRECISION) tex.scroll_v = 0; // Get texture rotation double rot; pPlace2dTexNode->findPlug("rotateFrame").getValue(rot); tex.rot = -rot; if (fabs(rot) < PRECISION) tex.rot = 0; } // add texture to material texture list m_textures.push_back(tex); // free up memory if (pUvChooserNode) delete pUvChooserNode; if (pPlace2dTexNode) delete pPlace2dTexNode; return MS::kSuccess; }
// // Selects objects within the user defined area, then process them // MStatus meshRemapTool::doRelease( MEvent & event ) { char buf[1024]; // Perform the base actions MStatus stat = MPxSelectionContext::doRelease(event); // Get the list of selected items MGlobal::getActiveSelectionList( fSelectionList ); // // Get the selection's details, we must have exactly one component selected // MObject component; MDagPath path; MItSelectionList selectionIt (fSelectionList, MFn::kComponent); MStringArray selections; selectionIt.getStrings( selections ); // There are valid cases where only the meshes are selected. if( selections.length() == 0 ) { // Handling the case where the user's workflow is // 1) select src mesh, select vtx1, vtx2, vtx3 (i.e. fNumSelectedPoints == 0) // 2) select dst mesh, select vtx1, vtx2, vtx3 (i.e. fNumSelectedPoints == 3) if( fNumSelectedPoints == 0 || fNumSelectedPoints == 3 ) { MItSelectionList selectionDag (fSelectionList, MFn::kDagNode); if (!selectionDag.isDone() && selectionDag.getDagPath(path) == MS::kSuccess) { path.extendToShape(); // return true there is exactly one mesh selected if (path.hasFn(MFn::kMesh)) { selectionDag.next(); if (selectionDag.isDone()) { // If this is the destination mesh, make sure that // it doesn't have history. if (fNumSelectedPoints == 3) { return checkForHistory(path); } return MS::kSuccess; } } } } // Handling the case where the user is doing the auto remap, i.e. // select src mesh, and then dst mesh when fNumSelectedPoints == 0. if( fNumSelectedPoints == 0 ) { MItSelectionList selectionDag (fSelectionList, MFn::kDagNode); if (!selectionDag.isDone() && selectionDag.getDagPath(path) == MS::kSuccess) { path.extendToShape(); // Confirm first selection is a mesh if (path.hasFn(MFn::kMesh)) { selectionDag.next(); if (!selectionDag.isDone() && selectionDag.getDagPath(path) == MS::kSuccess) { path.extendToShape(); // Confirm second selection is a mesh if (path.hasFn(MFn::kMesh)) { selectionDag.next(); // Confirm there are exactly 2 selections if (selectionDag.isDone()) { // Make sure that the destination mesh // doesn't have history. return checkForHistory(path); } } } } } } } if( selections.length() != 1 ) { MGlobal::displayError( "Must select exactly one vertex" ); return MS::kSuccess; } if (selectionIt.isDone ()) { MGlobal::displayError( "Selected item not a vertex" ); return MS::kSuccess; } if( selectionIt.getDagPath (path, component) != MStatus::kSuccess ) { MGlobal::displayError( "Must select a mesh or its vertex" ); return MS::kSuccess; } if (!path.node().hasFn(MFn::kMesh) && !(path.node().hasFn(MFn::kTransform) && path.hasFn(MFn::kMesh))) { MGlobal::displayError( "Must select a mesh or its transform" ); return MS::kSuccess; } // If this is the first vertex of the destination mesh, make sure that // it doesn't have history. if ((fNumSelectedPoints == 3) && (checkForHistory(path) != MS::kSuccess)) { return MS::kSuccess; } MItMeshVertex fIt ( path, component, &stat ); if( stat != MStatus::kSuccess ) { MGlobal::displayError( "MItMeshVertex failed"); return MStatus::kFailure; } if (fIt.count() != 1 ) { sprintf(buf, "Invalid selection '%s'. Vertices must be picked one at a time.", selections[0].asChar() ); MGlobal::displayError( buf ); return MS::kSuccess; } else { sprintf(buf, "Accepting vertex '%s'", selections[0].asChar() ); MGlobal::displayInfo( buf ); } // // Now that we know it's valid, process the selection, the first 3 items are the source, the second // 3 define the target // if( fNumSelectedPoints < 3 ) { fSelectedPathSrc.append( path ); fSelectedComponentSrc.append( component ); } else { fSelectedPathDst.append( path ); fSelectedComponentDst.append( component ); } // // When each of the source/target are defined, process them. An error/invalid selection will restart the selection for // that particular mesh. // if( fNumSelectedPoints == 2 ) { if( ( stat = meshMapUtils::validateFaceSelection( fSelectedPathSrc, fSelectedComponentSrc, &fSelectedFaceSrc, &fSelectVtxSrc ) ) != MStatus::kSuccess ) { MGlobal::displayError("Selected vertices don't define a unique face on source mesh"); reset(); return stat; } } // // Once the target is defined, invoke the command // if( fNumSelectedPoints == 5 ) { if( ( stat = meshMapUtils::validateFaceSelection( fSelectedPathDst, fSelectedComponentDst, &fSelectedFaceDst, &fSelectVtxDst ) ) != MStatus::kSuccess ) { MGlobal::displayError("Selected vertices don't define a unique face on destination mesh"); reset(); return stat; } executeCmd(); } else { // // We don't have all the details yet, just move to the next item // fNumSelectedPoints++; } helpStateHasChanged(); return stat; }
MStatus AlembicNode::compute(const MPlug & plug, MDataBlock & dataBlock) { MStatus status; // update the frame number to be imported MDataHandle speedHandle = dataBlock.inputValue(mSpeedAttr, &status); double speed = speedHandle.asDouble(); MDataHandle offsetHandle = dataBlock.inputValue(mOffsetAttr, &status); double offset = offsetHandle.asDouble(); MDataHandle timeHandle = dataBlock.inputValue(mTimeAttr, &status); MTime t = timeHandle.asTime(); double inputTime = t.as(MTime::kSeconds); double fps = getFPS(); // scale and offset inputTime. inputTime = computeAdjustedTime(inputTime, speed, offset/fps); // this should be done only once per file if (mFileInitialized == false) { mFileInitialized = true; //Get list of input filenames MFnDependencyNode depNode(thisMObject()); MPlug layerFilesPlug = depNode.findPlug("abc_layerFiles"); MFnStringArrayData fnSAD( layerFilesPlug.asMObject() ); MStringArray storedFilenames = fnSAD.array(); //Legacy support for single-filename input if( storedFilenames.length() == 0 ) { MFileObject fileObject; MDataHandle dataHandle = dataBlock.inputValue(mAbcFileNameAttr); fileObject.setRawFullName(dataHandle.asString()); MString fileName = fileObject.resolvedFullName(); storedFilenames.append( fileName ); } std::vector<std::string> abcFilenames; for(unsigned int i = 0; i < storedFilenames.length(); i++) abcFilenames.push_back( storedFilenames[i].asChar() ); Alembic::Abc::IArchive archive; Alembic::AbcCoreFactory::IFactory factory; factory.setPolicy(Alembic::Abc::ErrorHandler::kQuietNoopPolicy); archive = factory.getArchive( abcFilenames ); if (!archive.valid()) { MString theError = "Error opening these alembic files: "; const unsigned int numFilenames = storedFilenames.length(); for( unsigned int i = 0; i < numFilenames; i++ ) { theError += storedFilenames[ i ]; if( i != (numFilenames - 1) ) theError += ", "; } printError(theError); } // initialize some flags for plug update mSubDInitialized = false; mPolyInitialized = false; // When an alembic cache will be imported at the first time using // AbcImport, we need to set mIncludeFilterAttr (filterHandle) to be // mIncludeFilterString for later use. When we save a maya scene(.ma) // mIncludeFilterAttr will be saved. Then when we load the saved // .ma file, mIncludeFilterString will be set to be mIncludeFilterAttr. MDataHandle includeFilterHandle = dataBlock.inputValue(mIncludeFilterAttr, &status); MString& includeFilterString = includeFilterHandle.asString(); if (mIncludeFilterString.length() > 0) { includeFilterHandle.set(mIncludeFilterString); dataBlock.setClean(mIncludeFilterAttr); } else if (includeFilterString.length() > 0) { mIncludeFilterString = includeFilterString; } MDataHandle excludeFilterHandle = dataBlock.inputValue(mExcludeFilterAttr, &status); MString& excludeFilterString = excludeFilterHandle.asString(); if (mExcludeFilterString.length() > 0) { excludeFilterHandle.set(mExcludeFilterString); dataBlock.setClean(mExcludeFilterAttr); } else if (excludeFilterString.length() > 0) { mExcludeFilterString = excludeFilterString; } MFnDependencyNode dep(thisMObject()); MPlug allSetsPlug = dep.findPlug("allColorSets"); CreateSceneVisitor visitor(inputTime, !allSetsPlug.isNull(), MObject::kNullObj, CreateSceneVisitor::NONE, "", mIncludeFilterString, mExcludeFilterString); visitor.walk(archive); if (visitor.hasSampledData()) { // information retrieved from the hierarchy traversal // and given to AlembicNode to provide update visitor.getData(mData); mData.getFrameRange(mSequenceStartTime, mSequenceEndTime); MDataHandle startFrameHandle = dataBlock.inputValue(mStartFrameAttr, &status); startFrameHandle.set(mSequenceStartTime*fps); MDataHandle endFrameHandle = dataBlock.inputValue(mEndFrameAttr, &status); endFrameHandle.set(mSequenceEndTime*fps); } } // Retime MDataHandle cycleHandle = dataBlock.inputValue(mCycleTypeAttr, &status); short playType = cycleHandle.asShort(); inputTime = computeRetime(inputTime, mSequenceStartTime, mSequenceEndTime, playType); clamp<double>(mSequenceStartTime, mSequenceEndTime, inputTime); // update only when the time lapse is big enough if (fabs(inputTime - mCurTime) > 0.00001) { mOutRead = std::vector<bool>(mOutRead.size(), false); mCurTime = inputTime; } if (plug == mOutPropArrayAttr) { if (mOutRead[0]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[0] = true; unsigned int propSize = static_cast<unsigned int>(mData.mPropList.size()); if (propSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutPropArrayAttr, &status); unsigned int outHandleIndex = 0; MDataHandle outHandle; // for all of the nodes with sampled attributes for (unsigned int i = 0; i < propSize; i++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(); } else { continue; } if (mData.mPropList[i].mArray.valid()) { readProp(mCurTime, mData.mPropList[i].mArray, outHandle); } else if (mData.mPropList[i].mScalar.valid()) { // for visibility only if (mData.mPropList[i].mScalar.getName() == Alembic::AbcGeom::kVisibilityPropertyName) { Alembic::Util::int8_t visVal = 1; mData.mPropList[i].mScalar.get(&visVal, Alembic::Abc::ISampleSelector(mCurTime, Alembic::Abc::ISampleSelector::kNearIndex )); outHandle.setGenericBool(visVal != 0, false); } else { // for all scalar props readProp(mCurTime, mData.mPropList[i].mScalar, outHandle); } } outArrayHandle.next(); } outArrayHandle.setAllClean(); } } else if (plug == mOutTransOpArrayAttr ) { if (mOutRead[1]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[1] = true; unsigned int xformSize = static_cast<unsigned int>(mData.mXformList.size()); if (xformSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutTransOpArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutTransOpArrayAttr); MDataHandle outHandle; unsigned int outHandleIndex = 0; for (unsigned int i = 0; i < xformSize; i++) { std::vector<double> sampleList; if (mData.mIsComplexXform[i]) { readComplex(mCurTime, mData.mXformList[i], sampleList); } else { Alembic::AbcGeom::XformSample samp; read(mCurTime, mData.mXformList[i], sampleList, samp); } unsigned int sampleSize = (unsigned int)sampleList.size(); for (unsigned int j = 0; j < sampleSize; j++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(&status); } else continue; outArrayHandle.next(); outHandle.set(sampleList[j]); } } outArrayHandle.setAllClean(); } } else if (plug == mOutLocatorPosScaleArrayAttr ) { if (mOutRead[8]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[8] = true; unsigned int locSize = static_cast<unsigned int>(mData.mLocList.size()); if (locSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutLocatorPosScaleArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutLocatorPosScaleArrayAttr); MDataHandle outHandle; unsigned int outHandleIndex = 0; for (unsigned int i = 0; i < locSize; i++) { std::vector< double > sampleList; read(mCurTime, mData.mLocList[i], sampleList); unsigned int sampleSize = (unsigned int)sampleList.size(); for (unsigned int j = 0; j < sampleSize; j++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(&status); } else continue; outArrayHandle.next(); outHandle.set(sampleList[j]); } } outArrayHandle.setAllClean(); } } else if (plug == mOutSubDArrayAttr) { if (mOutRead[2]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutSubDArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[2] = true; unsigned int subDSize = static_cast<unsigned int>(mData.mSubDList.size()); if (subDSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutSubDArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < subDSize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFnMesh fnMesh(obj); readSubD(mCurTime, fnMesh, obj, mData.mSubDList[j], mSubDInitialized); outHandle.set(obj); } } mSubDInitialized = true; outArrayHandle.setAllClean(); } // for the case where we don't have any nodes, we want to make sure // to push out empty meshes on our connections, this can happen if // the input file was offlined, currently we only need to do this for // meshes as Nurbs, curves, and the other channels don't crash Maya else { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutSubDArrayAttr, &status); if (outArrayHandle.elementCount() > 0) { do { MDataHandle outHandle = outArrayHandle.outputValue(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFloatPointArray emptyVerts; MIntArray emptyCounts; MIntArray emptyConnects; MFnMesh emptyMesh; emptyMesh.create(0, 0, emptyVerts, emptyCounts, emptyConnects, obj); outHandle.set(obj); } } while (outArrayHandle.next() == MS::kSuccess); } mSubDInitialized = true; outArrayHandle.setAllClean(); } } else if (plug == mOutPolyArrayAttr) { if (mOutRead[3]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutPolyArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[3] = true; unsigned int polySize = static_cast<unsigned int>(mData.mPolyMeshList.size()); if (polySize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutPolyArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < polySize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFnMesh fnMesh(obj); readPoly(mCurTime, fnMesh, obj, mData.mPolyMeshList[j], mPolyInitialized); outHandle.set(obj); } } mPolyInitialized = true; outArrayHandle.setAllClean(); } // for the case where we don't have any nodes, we want to make sure // to push out empty meshes on our connections, this can happen if // the input file was offlined, currently we only need to do this for // meshes as Nurbs, curves, and the other channels don't crash Maya else { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutPolyArrayAttr, &status); if (outArrayHandle.elementCount() > 0) { do { MDataHandle outHandle = outArrayHandle.outputValue(&status); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFloatPointArray emptyVerts; MIntArray emptyCounts; MIntArray emptyConnects; MFnMesh emptyMesh; emptyMesh.create(0, 0, emptyVerts, emptyCounts, emptyConnects, obj); outHandle.set(obj); } } while (outArrayHandle.next() == MS::kSuccess); } mPolyInitialized = true; outArrayHandle.setAllClean(); } } else if (plug == mOutCameraArrayAttr) { if (mOutRead[4]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[4] = true; unsigned int cameraSize = static_cast<unsigned int>(mData.mCameraList.size()); if (cameraSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutCameraArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutCameraArrayAttr); double angleConversion = 1.0; switch (MAngle::uiUnit()) { case MAngle::kRadians: angleConversion = 0.017453292519943295; break; case MAngle::kAngMinutes: angleConversion = 60.0; break; case MAngle::kAngSeconds: angleConversion = 3600.0; break; default: break; } MDataHandle outHandle; unsigned int index = 0; for (unsigned int cameraIndex = 0; cameraIndex < cameraSize; cameraIndex++) { Alembic::AbcGeom::ICamera & cam = mData.mCameraList[cameraIndex]; std::vector<double> array; read(mCurTime, cam, array); for (unsigned int dataIndex = 0; dataIndex < array.size(); dataIndex++, index++) { // skip over sparse elements if (index != outArrayHandle.elementIndex()) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); // not shutter angle index, so not an angle if (dataIndex != 11) { outHandle.set(array[dataIndex]); } else { outHandle.set(array[dataIndex] * angleConversion); } } // for the per camera data handles } // for each camera outArrayHandle.setAllClean(); } } else if (plug == mOutNurbsSurfaceArrayAttr) { if (mOutRead[5]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsSurfaceArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[5] = true; unsigned int nSurfaceSize = static_cast<unsigned int>(mData.mNurbsList.size()); if (nSurfaceSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsSurfaceArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < nSurfaceSize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) continue; outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kNurbsSurface)) { readNurbs(mCurTime, mData.mNurbsList[j], obj); outHandle.set(obj); } } outArrayHandle.setAllClean(); } } else if (plug == mOutNurbsCurveGrpArrayAttr) { if (mOutRead[6]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsCurveGrpArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[6] = true; unsigned int nCurveGrpSize = static_cast<unsigned int>(mData.mCurvesList.size()); if (nCurveGrpSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsCurveGrpArrayAttr, &status); MDataHandle outHandle; std::vector<MObject> curvesObj; for (unsigned int i = 0; i < nCurveGrpSize; ++i) { readCurves(mCurTime, mData.mCurvesList[i], mData.mNumCurves[i], curvesObj); } std::size_t numChild = curvesObj.size(); // not the best way to do this // only reading bunches of curves based on the connections would be // more efficient when there is a bunch of broken connections for (unsigned int i = 0; i < numChild; i++) { if (outArrayHandle.elementIndex() != i) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); status = outHandle.set(curvesObj[i]); } outArrayHandle.setAllClean(); } } else { return MS::kUnknownParameter; } dataBlock.setClean(plug); return status; }
MStatus rtgTranslator::writer ( const MFileObject & fileObject, const MString & options, MPxFileTranslator::FileAccessMode mode) { char LTmpStr[MAXPATHLEN]; unsigned int i; int LN; const MString fname = fileObject.fullName (); MString extension; MString baseFileName; int TimeSlider = 0; int AnimEnabled = 0; // Lets strip off the known extension of .rtg if it is there. extension.set (".rtg"); int extLocation = fileObject.name ().rindex ('.'); if (extLocation > 0 && fileObject.name ().substring (extLocation, fileObject.name ().length () - 1) == extension) { baseFileName = fileObject.name ().substring (0, extLocation - 1); } else { baseFileName = fileObject.name (); extension.clear (); } DtExt_SceneInit( (char *)baseFileName.asChar() ); // Lets now do all of the option processing if (options.length () > 0) { //Start parsing. MStringArray optionList; MStringArray theOption; options.split (';', optionList); //break out all the options. for ( i = 0; i < optionList.length (); ++i) { theOption.clear (); optionList[i].split ('=', theOption); if (theOption.length () > 1) { if (theOption[0] == MString ("v18compatible")) { rtg_v18_compatible = (int) (theOption[1].asInt() ); } else if (theOption[0] == MString ("timeslider")) { TimeSlider = (int) (theOption[1].asInt ()); } else if (theOption[0] == MString ("animEnabled")) { AnimEnabled = (int) (theOption[1].asInt ()); } else if (theOption[0] == MString ("animStart")) { DtFrameSetStart( (int) (theOption[1].asInt ()) ); } else if (theOption[0] == MString ("animEnd")) { DtFrameSetEnd( (int) (theOption[1].asInt ()) ); } else if (theOption[0] == MString ("animStep")) { DtFrameSetBy( (int) (theOption[1].asInt ()) ); } else if (theOption[0] == MString ("hrcType")) { switch ( theOption[1].asInt () - 1) { case VRHRC_FLAT: DtExt_setOutputTransforms (kTRANSFORMMINIMAL); DtExt_setParents (0); break; case VRHRC_WORLD: DtExt_setOutputTransforms (kTRANSFORMNONE); DtExt_setParents (0); break; case VRHRC_FULL: default: DtExt_setOutputTransforms (kTRANSFORMALL); DtExt_setParents (1); break; } } else if (theOption[0] == MString ("joints")) { // Allow user to specify if the hierarchy should include // NULL geometry nodes - usually joints DtExt_setJointHierarchy( theOption[1].asInt() ); } else if (theOption[0] == MString ("exportSel")) { switch ( theOption[1].asInt () - 1) { case VRSEL_ALL: DtExt_setWalkMode (ALL_Nodes); break; case VRSEL_ACTIVE: DtExt_setWalkMode (ACTIVE_Nodes); break; case VRSEL_PICKED: DtExt_setWalkMode (PICKED_Nodes); break; } } else if (theOption[0] == MString ("texsample")) { // Allow user to specify if the textures should be sampled // with the Texture Placement options DtExt_setSoftTextures ( theOption[1].asInt() ); } else if (theOption[0] == MString ("texevaluate")) { // Allow the user to specify if the tex should be eval with // convertSolidTx command or read in if is a file texture. DtExt_setInlineTextures( theOption[1].asInt() ); } else if (theOption[0] == MString ("texoriginal")) { // Allow the user to specify if the tex should be eval at all. DtExt_setOriginalTexture( theOption[1].asInt() ); } else if (theOption[0] == MString ("Xtexres")) { // Set the X size of the texture swatches to use DtExt_setXTextureRes ( theOption[1].asInt () ); } else if (theOption[0] == MString ("Ytexres")) { // Set the Y size of the texture swatches to use DtExt_setYTextureRes ( theOption[1].asInt () ); } else if (theOption[0] == MString ("MaxXtexres")) { // Set the Max X size of the texture swatches to use DtExt_setMaxXTextureRes( theOption[1].asInt () ); } else if (theOption[0] == MString ("MaxYtexres")) { // Set the Max Y size of the texture swatches to use DtExt_setMaxYTextureRes( theOption[1].asInt () ); } else if (theOption[0] == MString ("precision")) { //VR_Precision = theOption[1].asInt (); } else if (theOption[0] == MString ("verbose")) { // DtExt_setDebug ( theOption[1].asInt () ); } else if (theOption[0] == MString ("debug")) { int levelG = DtExt_Debug(); if ( (int) (theOption[1].asInt () ) ) levelG |= DEBUG_GEOMAT; else levelG &= ~DEBUG_GEOMAT; DtExt_setDebug( levelG ); } else if (theOption[0] == MString ("debugC")) { int levelC = DtExt_Debug(); if ( (int) (theOption[1].asInt () ) ) levelC |= DEBUG_CAMERA; else levelC &= ~DEBUG_CAMERA; DtExt_setDebug( levelC ); } else if (theOption[0] == MString ("debugL")) { int levelL = DtExt_Debug(); if ( (int) (theOption[1].asInt () ) ) levelL |= DEBUG_LIGHT; else levelL &= ~DEBUG_LIGHT; DtExt_setDebug( levelL ); } else if (theOption[0] == MString ("reversed")) { DtExt_setWinding( theOption[1].asInt() ); } else if (theOption[0] == MString ("tesselation")) { if ( theOption[1].asInt() == 2 ) { DtExt_setTesselate( kTESSQUAD ); } else { DtExt_setTesselate( kTESSTRI ); } // // Now come the translator specific options // } else if (theOption[0] == MString ("imageformat")) { rtg_output_image_format = theOption[1].asInt(); } else if (theOption[0] == MString ("fileformat")) { rtg_output_file_format = theOption[1].asInt(); } else if (theOption[0] == MString ("vnormals")) { rtg_output_vert_norms = theOption[1].asInt(); } else if (theOption[0] == MString ("vcolors")) { rtg_output_vert_colors = theOption[1].asInt(); } else if (theOption[0] == MString ("tcoords")) { rtg_output_tex_coords = theOption[1].asInt(); } else if (theOption[0] == MString ("pnormals")) { rtg_output_poly_norms = theOption[1].asInt(); } else if (theOption[0] == MString ("idxcnt")) { rtg_show_index_counters = theOption[1].asInt(); } else if (theOption[0] == MString ("anglesdeg")) { rtg_output_degrees = theOption[1].asInt(); } else if (theOption[0] == MString ("materials")) { rtg_output_materials = theOption[1].asInt(); } else if (theOption[0] == MString ("multitexture")) { DtExt_setMultiTexture( theOption[1].asInt() ); } else if (theOption[0] == MString ("mdecomp")) { rtg_output_decomp = theOption[1].asInt(); } else if (theOption[0] == MString ("pivoth")) { rtg_output_pivots = theOption[1].asInt(); } else if (theOption[0] == MString ("transforms")) { rtg_output_transforms = theOption[1].asInt(); } else if (theOption[0] == MString ("ltransforms")) { rtg_output_local = theOption[1].asInt(); } else if (theOption[0] == MString ("animation")) { rtg_output_animation = theOption[1].asInt(); } else if (theOption[0] == MString ("allnodes")) { rtg_output_all_nodes = theOption[1].asInt(); } else if (theOption[0] == MString ("script")) { scriptToRun = theOption[1]; } else if (theOption[0] == MString ("scriptAppend")) { scriptAppend = (int)(theOption[1].asInt() ); } } } } // Lets see how we entered this plug-in, either with the export all // or export selection flag set. if ( mode == MPxFileTranslator::kExportActiveAccessMode ) { DtExt_setWalkMode ( ACTIVE_Nodes ); } // Lets check the TimeSlider control now: if ( TimeSlider ) { MTime start( MAnimControl::minTime().value(), MTime::uiUnit() ); DtFrameSetStart( (int) start.value() ); MTime end( MAnimControl::maxTime().value(), MTime::uiUnit() ); DtFrameSetEnd( (int) end.value() ); } // Now see if the animation is really enabled. // Else we will set the end frame to the beginning frame automatically if ( !AnimEnabled ) { DtFrameSetEnd( DtFrameGetStart() ); } // Find out where the file is supposed to end up. MDt_GetPathName ((char *) (fname.asChar ()), LTmpStr, MAXPATHLEN); LN = (int)strlen (LTmpStr); if (LTmpStr[LN - 1] == '/') LTmpStr[LN - 1] = '\0'; DtSetDirectory (LTmpStr); // Now lets setup some paths to do basic texture file searching // for those textures with relative paths MStringArray wSpacePaths; MStringArray rPaths; MString usePath; MString separator; MGlobal::executeCommand( "workspace -q -rd", wSpacePaths ); MGlobal::executeCommand( "workspace -q -rtl", rPaths ); if ( DtExt_getTextureSearchPath() ) separator.set( "|" ); else separator.set( "" ); for (i = 0; i < wSpacePaths.length (); ++i) { for ( unsigned int j = 0; j < rPaths.length(); j++ ) { usePath = usePath + separator + wSpacePaths[i] + MString( "/" ) + rPaths[j]; separator.set( "|" ); if ( rPaths[j] == MString( "sourceImages" ) ) usePath = usePath + separator + wSpacePaths[i] + MString( "/" ) + MString( "sourceimages" ); } } DtExt_addTextureSearchPath( (char *)usePath.asChar() ); // Now we can setup the database from the wire file geometry. // This is where all the Maya data are retrieved, cached, and processed. // // Say that we want to have camera info DtExt_setOutputCameras( 1 ); //Now we can setup the database from the wire file geometry DtExt_dbInit(); DtFrameSet( DtFrameGetStart() ); // Now do the export rtgExport(); // Now lets see if the user wants something else to be done if ( 0 < scriptToRun.length() ) { if ( scriptAppend ) { scriptToRun += MString( " " ) + MString( LTmpStr ); } system( scriptToRun.asChar() ); } // Clean house. // DtExt_CleanUp(); return MS::kSuccess; }
MStatus getLight::readLight(yafaray::yafrayInterface_t &yI) { MStatus stat; bool hasYafLight=0; MString listPoint("ls -type yafPointLight"); MStringArray pointResult; MGlobal::executeCommand(listPoint, pointResult); if(pointResult.length()>0) { hasYafLight=1; for(unsigned int i=0;i<pointResult.length();i++) { //test output cout<<pointResult[i].asChar()<<endl; MSelectionList list; MGlobal::getSelectionListByName(pointResult[i],list); for(unsigned int index=0;index<list.length();index++) { MDagPath pointPath; list.getDagPath(index,pointPath); MObject pointTransNode=pointPath.transform(); MFnTransform pointTrans(pointTransNode); MGlobal::displayInfo(pointTrans.name()); MVector transP=pointTrans.getTranslation(MSpace::kTransform); //test output //this is the position of the point light cout<<"============test light==========="<<endl; cout<<transP.x<<transP.y<<transP.z<<endl; MObject pointDepNode; list.getDependNode(index,pointDepNode); MFnDependencyNode pointDepFn(pointDepNode); yI.paramsClearAll(); yI.paramsSetString("type","pointlight"); yI.paramsSetPoint("from",transP.x,transP.y,transP.z); MObject pointColor; pointDepFn.findPlug("LightColor").getValue(pointColor); MFnNumericData pointData(pointColor); float pcR,pcG,pcB; pointData.getData(pcR,pcG,pcB); yI.paramsSetColor("color",pcR,pcG,pcB); float pointPower; pointDepFn.findPlug("Power").getValue(pointPower); yI.paramsSetFloat("power",pointPower); cout<<"================point light=============="<<endl; cout<<pointDepFn.name().asChar()<<endl; yI.createLight(pointDepFn.name().asChar()); } } } //sphere light MString listSphere("ls -type yafSphereLight"); MStringArray sphereResult; MGlobal::executeCommand(listSphere, sphereResult); if(sphereResult.length()>0) { hasYafLight=1; for(unsigned int i=0;i<sphereResult.length();i++) { //test output cout<<sphereResult[i].asChar()<<endl; MSelectionList list; MGlobal::getSelectionListByName(sphereResult[i],list); for(unsigned int index=0;index<list.length();index++) { MDagPath spherePath; list.getDagPath(index,spherePath); MObject sphereTransNode=spherePath.transform(); MFnTransform sphereTrans(sphereTransNode); MVector transP=sphereTrans.getTranslation(MSpace::kTransform); MFnDagNode sphereFn(spherePath); MObject sphereColor; sphereFn.findPlug("LightColor").getValue(sphereColor); MFnNumericData sphereData(sphereColor); float sphereR,sphereG,sphereB; sphereData.getData(sphereR,sphereG,sphereB); float power; sphereFn.findPlug("Power").getValue(power); int samples; sphereFn.findPlug("Samples").getValue(samples); float radius; sphereFn.findPlug("Radius").getValue(radius); //check if draw geometry needed bool makeGeo; sphereFn.findPlug("MakeGeometry").getValue(makeGeo); if (makeGeo) { int u=24; int v=48; yI.paramsClearAll(); yI.paramsSetString("type","light_mat"); yI.paramsSetFloat("power",power); yI.paramsSetColor("color",sphereR,sphereG,sphereB); yafaray::material_t *lightMat=yI.createMaterial(sphereFn.name().asChar()); int sphereID=makeSphere(yI,u,v,transP.x,transP.y,transP.z,radius,lightMat); yI.paramsSetInt("object",sphereID); } yI.paramsClearAll(); yI.paramsSetString("type","spherelight"); yI.paramsSetPoint("from",transP.x, transP.y,transP.z); yI.paramsSetColor("color",sphereR,sphereG,sphereB); yI.paramsSetFloat("power",power); yI.paramsSetInt("samples",samples); yI.paramsSetFloat("radius",radius); cout<<"================sphere light=============="<<endl; cout<<sphereFn.name().asChar()<<endl; yI.createLight(sphereFn.name().asChar()); } } } MString listSun("ls -type yafSunLight"); MStringArray sunResult; MGlobal::executeCommand(listSun,sunResult); if (sunResult.length()>0) { hasYafLight=1; for (unsigned int i=0;i<sunResult.length();i++) { //test output cout<<sunResult[i].asChar()<<endl; MSelectionList list; MGlobal::getSelectionListByName(sunResult[i],list); for(unsigned int index=0;index<list.length();index++) { MDagPath sunPath; list.getDagPath(index,sunPath); MObject sunTransNode=sunPath.transform(); MFnTransform sunTrans(sunTransNode); MTransformationMatrix sunMatrix=sunTrans.transformation(); MMatrix sMatrix=sunMatrix.asMatrix(); MVector transP=sunTrans.getTranslation(MSpace::kTransform); MPoint direction1(0.0,0.0,0.0); MPoint direction2(0.0,0.0,1.0); MPoint direction=direction1-direction2; direction*=sMatrix; yI.paramsClearAll(); yI.paramsSetString("type","sunlight"); MFnDagNode sunFn(sunPath); yI.paramsSetPoint("from",transP.x, transP.y,transP.z); yI.paramsSetPoint("direction",direction.x,direction.y,direction.z); MObject sunColor; sunFn.findPlug("LightColor").getValue(sunColor); MFnNumericData sunData(sunColor); float sunR,sunG,sunB; sunData.getData(sunR,sunG,sunB); yI.paramsSetColor("color",sunR,sunG,sunB); float power; sunFn.findPlug("Power").getValue(power); yI.paramsSetFloat("power",power); int samples; sunFn.findPlug("Samples").getValue(samples); yI.paramsSetInt("samples",samples); float angle; sunFn.findPlug("Angle").getValue(angle); yI.paramsSetFloat("angle",angle); cout<<"================sun light=============="<<endl; cout<<sunFn.name().asChar()<<endl; yI.createLight(sunFn.name().asChar()); } } } //spot light MString listSpot("ls -type yafSpotLight"); MStringArray spotResult; MGlobal::executeCommand(listSpot, spotResult); if(spotResult.length()>0) { hasYafLight=1; for(unsigned int i=0;i<spotResult.length();i++) { //test output cout<<spotResult[i].asChar()<<endl; MSelectionList list; MGlobal::getSelectionListByName(spotResult[i],list); for(unsigned int index=0;index<list.length();index++) { MDagPath spotPath; list.getDagPath(index,spotPath); MObject spotTransNode=spotPath.transform(); MFnTransform spotTrans(spotTransNode); MTransformationMatrix spotMatrix=spotTrans.transformation(); MMatrix sMatrix=spotMatrix.asMatrix(); MVector transP=spotTrans.getTranslation(MSpace::kTransform); MPoint direction1(0.0,0.0,0.0); MPoint direction2(0.0,-1.0,0.0); MPoint direction=direction2-direction1; direction*=sMatrix; yI.paramsClearAll(); yI.paramsSetString("type","spotlight"); MFnDagNode spotFn(spotPath); yI.paramsSetPoint("from",transP.x, transP.y,transP.z); yI.paramsSetPoint("to",direction.x,direction.y,direction.z); MObject spotColor; spotFn.findPlug("LightColor").getValue(spotColor); MFnNumericData spotData(spotColor); float spotR,spotG,spotB; spotData.getData(spotR,spotG,spotB); yI.paramsSetColor("color",spotR,spotG,spotB); float power; spotFn.findPlug("Power").getValue(power); yI.paramsSetFloat("power",power); float coneAngle; spotFn.findPlug("ConeAngle").getValue(coneAngle); yI.paramsSetFloat("cone_angle",coneAngle); float blend; spotFn.findPlug("PenumbraDistance").getValue(blend); yI.paramsSetFloat("blend",blend); bool softShadows; spotFn.findPlug("SoftShadows").getValue(softShadows); yI.paramsSetBool("soft_shadows",softShadows); float fuzzyness; spotFn.findPlug("ShadowFuzzyness").getValue(fuzzyness); yI.paramsSetFloat("shadowFuzzyness",fuzzyness); bool photonOnly; spotFn.findPlug("PhotonOnly").getValue(photonOnly); yI.paramsSetBool("photon_only",photonOnly); int samples; spotFn.findPlug("Samples").getValue(samples); yI.paramsSetInt("samples",samples); cout<<"================spot light=============="<<endl; cout<<spotFn.name().asChar()<<endl; yI.createLight(spotFn.name().asChar()); } } } //directional lights MString listDirectional("ls -type yafDirectionalLight"); MStringArray dirResult; MGlobal::executeCommand(listDirectional,dirResult); if(dirResult.length()>0) { hasYafLight=1; for (unsigned int i=0; i<dirResult.length(); i++) { MSelectionList list; MGlobal::getSelectionListByName(dirResult[i],list); for(unsigned int index=0;index<list.length();index++) { MDagPath dirShapePath; list.getDagPath(index,dirShapePath); MFnTransform dirTransform(dirShapePath.transform()); MTransformationMatrix dirTransMatrix=dirTransform.transformation(); MMatrix dirMatrix=dirTransMatrix.asMatrix(); MPoint direction1(0,0,0); MPoint direction2(0,0,-1); MPoint direction=direction1-direction2; direction*=dirMatrix; yI.paramsClearAll(); yI.paramsSetString("type","directional"); yI.paramsSetPoint("direction",direction.x, direction.y, direction.z); MFnDagNode dirShapeFn(dirShapePath); MObject dirColor; dirShapeFn.findPlug("LightColor").getValue(dirColor); MFnNumericData dirData(dirColor); float dirR,dirG,dirB; dirData.getData(dirR,dirG,dirB); yI.paramsSetColor("color",dirR,dirG,dirB); float power; dirShapeFn.findPlug("Power").getValue(power); yI.paramsSetFloat("power",power); bool infinite; dirShapeFn.findPlug("Infinite").getValue(infinite); yI.paramsSetBool("infinite",infinite); float radius; dirShapeFn.findPlug("Radius").getValue(radius); yI.paramsSetFloat("radius",radius); MVector dirP=dirTransform.getTranslation(MSpace::kTransform); yI.paramsSetPoint("from",dirP.x,dirP.y,dirP.z); cout<<"================directional light=============="<<endl; cout<<dirShapeFn.name().asChar()<<endl; yI.createLight(dirShapeFn.name().asChar()); } } } //area lights MString listArea("ls -type yafAreaLight"); MStringArray areaResult; MGlobal::executeCommand(listArea, areaResult); if(areaResult.length()>0) { hasYafLight=1; for(unsigned int i=0;i<areaResult.length();i++) { MSelectionList list; MGlobal::getSelectionListByName(areaResult[i],list); for(unsigned int index=0;index<list.length();index++) { MDagPath areaShapePath; list.getDagPath(index,areaShapePath); //areaTransform is the transform node of this light, all the location information is here MFnTransform areaTransform(areaShapePath.transform()); MTransformationMatrix areaTransMatrix=areaTransform.transformation(); MMatrix areaMatrix=areaTransMatrix.asMatrix(); //this is the shape node of the light, all the attribute is here MPoint corner(-1.0,-1.0,0); MPoint point1(-1.0,1.0,0); MPoint point2(1.0,1.0,0); MPoint point3(1.0,-1.0,0); corner*=areaMatrix; point1*=areaMatrix; point2*=areaMatrix; point3*=areaMatrix; MVector areaP=areaTransform.getTranslation(MSpace::kTransform); MFnDagNode areaShapeFn(areaShapePath); int samples; areaShapeFn.findPlug("Samples").getValue(samples); MObject areaColor; areaShapeFn.findPlug("LightColor").getValue(areaColor); MFnNumericData areaData(areaColor); float areaR,areaG,areaB; areaData.getData(areaR,areaG,areaB); float power; areaShapeFn.findPlug("Power").getValue(power); bool makeGeo; areaShapeFn.findPlug("MakeGeometry").getValue(makeGeo); if (makeGeo==1) { //create light yI.paramsClearAll(); yI.paramsSetString("type","light_mat"); yI.paramsSetFloat("power",power); yI.paramsSetColor("color",areaR,areaG,areaB); yafaray::material_t * lightMat=yI.createMaterial(areaShapeFn.name().asChar()); //create geometry yI.paramsClearAll(); int areaID=yI.getNextFreeID(); yI.startGeometry(); yI.startTriMesh(areaID,4,2,false,false); yI.addVertex(corner.x,corner.y,corner.z); yI.addVertex(point1.x,point1.y,point1.z); yI.addVertex(point2.x,point2.y,point2.z); yI.addVertex(point3.x,point3.y,point3.z); yI.addTriangle(0,1,2,lightMat); yI.addTriangle(0,2,3,lightMat); yI.endTriMesh(); yI.endGeometry(); yI.paramsSetInt("object",areaID); } yI.paramsClearAll(); yI.paramsSetString("type","arealight"); cout<<"===============area light=============="<<endl; yI.paramsSetInt("samples",samples); yI.paramsSetPoint("corner",corner.x, corner.y, corner.z); yI.paramsSetPoint("point1",point1.x, point1.y, point1.z); yI.paramsSetPoint("point2",point3.x, point3.y, point3.z); yI.paramsSetPoint("from",areaP.x, areaP.y, areaP.z); yI.paramsSetColor("color",areaR,areaG,areaB); yI.paramsSetFloat("power",power); cout<<areaShapeFn.name().asChar()<<endl; yI.createLight(areaShapeFn.name().asChar()); } } } //if there is no light in the scene, create a default one //but this one will not be available if users create new ones if (hasYafLight==false) { yI.paramsClearAll(); yI.paramsSetString("type","directional"); //use camera direction and position so that default light always can be seen no matter where user watch from //M3dView currentView=M3dView::active3dView(); //MDagPath cameraPath; //MFnCamera currentCam(cameraPath); //MVector lightPosition=currentCam.eyePoint(MSpace::kWorld); //MVector lightDirection=currentCam.viewDirection(MSpace::kWorld); //currentView.getCamera(cameraPath); yI.paramsSetPoint("direction",0.0,0.0,1.0); yI.paramsSetPoint("from",0.0,0.0,0.0); yI.paramsSetColor("color",0.8f,0.8f,0.8f); yI.paramsSetFloat("power",1.0f); yI.paramsSetBool("infinite",true); yI.paramsSetFloat("radius",1.0f); yI.createLight("yafDefaultLight1"); yI.paramsClearAll(); yI.paramsSetString("type","directional"); yI.paramsSetPoint("direction",1.0,0.0,-1.0); yI.paramsSetPoint("from",0.0,0.0,0.0); yI.paramsSetColor("color",0.8f,0.8f,0.8f); yI.paramsSetFloat("power",1.0f); yI.paramsSetBool("infinite",true); yI.paramsSetFloat("radius",1.0f); yI.createLight("yafDefaultLight2"); MGlobal::displayWarning("(yafaray) you haven't created your own light yet!"); } return stat; }
// // Selects objects within the user defined area, then process them // MStatus meshReorderTool::doRelease( MEvent & event ) { char buf[1024]; // Perform the base actions MStatus stat = MPxSelectionContext::doRelease(event); // Get the list of selected items MGlobal::getActiveSelectionList( fSelectionList ); // // If there's nothing selected, don't worry about it, just return // if( fSelectionList.length() != 1 ) { MGlobal::displayWarning( "Components must be selected one at a time" ); return MS::kSuccess; } // // Get the selection's details, we must have exactly one component selected // MObject component; MDagPath path; MItSelectionList selectionIt (fSelectionList, MFn::kComponent); MStringArray selections; selectionIt.getStrings( selections ); if( selections.length() != 1 ) { MGlobal::displayError( "Must select exactly one vertex" ); return MS::kSuccess; } if (selectionIt.isDone ()) { MGlobal::displayError( "Selected item not a vertex" ); return MS::kSuccess; } if( selectionIt.getDagPath (path, component) != MStatus::kSuccess ) { MGlobal::displayError( "Must select a mesh or its vertex"); return MS::kSuccess; } if (!path.node().hasFn(MFn::kMesh) && !(path.node().hasFn(MFn::kTransform) && path.hasFn(MFn::kMesh))) { MGlobal::displayError( "Must select a mesh or its transform" ); return MS::kSuccess; } MFnMesh meshFn(path); MPlug historyPlug = meshFn.findPlug("inMesh", true); if (historyPlug.isDestination()) { MGlobal::displayError( "Mesh has history. Its geometry cannot be modified" ); return MS::kSuccess; } MItMeshVertex fIt ( path, component, &stat ); if( stat != MStatus::kSuccess ) { MGlobal::displayError( "MItMeshVertex failed"); return MStatus::kFailure; } if (fIt.count() != 1 ) { sprintf(buf, " Invalid selection '%s'. Vertices must be picked one at a time.", selections[0].asChar() ); MGlobal::displayError( buf ); return MS::kSuccess; } else { sprintf(buf, "Accepting vertex '%s'", selections[0].asChar() ); MGlobal::displayInfo( buf ); } // // Now that we know it's valid, process the selection // fSelectedPathSrc.append( path ); fSelectedComponentSrc.append( component ); // // When each of the mesh defined, process it. An error/invalid selection will restart the selection for // that particular mesh. // if( fNumSelectedPoints == 2 ) { if( ( stat = meshMapUtils::validateFaceSelection( fSelectedPathSrc, fSelectedComponentSrc, &fSelectedFaceSrc, &fSelectVtxSrc ) ) != MStatus::kSuccess ) { MGlobal::displayError("Must select vertices from the same face of a mesh"); reset(); return stat; } char cmdString[200]; sprintf(cmdString, "meshReorder %s.vtx[%d] %s.vtx[%d] %s.vtx[%d]", fSelectedPathSrc[0].partialPathName().asChar(), fSelectVtxSrc[0], fSelectedPathSrc[1].partialPathName().asChar(), fSelectVtxSrc[1], fSelectedPathSrc[2].partialPathName().asChar(), fSelectVtxSrc[2]); stat = MGlobal::executeCommand(cmdString, true, true); if (stat) { MGlobal::displayInfo( "Mesh reordering complete" ); } // // Empty the selection list since the reodering may move the user's current selection on screen // MSelectionList empty; MGlobal::setActiveSelectionList( empty ); // // Start again, get new meshes // reset(); } else { // // We don't have all the details yet, just move to the next item // fNumSelectedPoints++; } helpStateHasChanged( event ); return stat; }
liqRibCurvesData::liqRibCurvesData( MObject curveGroup ) : nverts(), CVs(), NuCurveWidth() { CM_TRACE_FUNC("liqRibCurvesData::liqRibCurvesData("<<curveGroup.apiTypeStr()<<")"); LIQDEBUGPRINTF( "-> creating nurbs curve group\n" ); MStatus status( MS::kSuccess ); MFnDagNode fnDag( curveGroup, &status ); MFnDagNode fnTrans( fnDag.parent( 0 ) ); MSelectionList groupList; groupList.add( fnTrans.partialPathName() ); MDagPath groupPath; groupList.getDagPath( 0, groupPath ); MMatrix m( groupPath.inclusiveMatrix() ); MStringArray curveList; MObjectArray curveObj; MDagPathArray curveDag; // using the transforms not the nurbsCurves so instances are supported MGlobal::executeCommand( MString( "ls -dag -type transform " ) + fnTrans.partialPathName(), curveList ); for( unsigned i( 0 ); i < curveList.length(); i++ ) { MSelectionList list; list.add( curveList[i] ); MObject curveNode; MDagPath path; list.getDependNode( 0, curveNode ); list.getDagPath( 0, path ); MFnDagNode fnCurve( curveNode ); MObject shape( fnCurve.child( 0 ) ); if( shape.hasFn( MFn::kNurbsCurve ) ) { curveObj.append( curveNode ); curveDag.append( path ); } } if( liqglo.liqglo_renderAllCurves ) ncurves = curveObj.length(); else ncurves = 0; if( !ncurves ) return; nverts = shared_array< RtInt >( new RtInt[ ncurves ] ); unsigned cvcount( 0 ); unsigned long curvePts(0); for( unsigned i( 0 ); i < ncurves; i++ ) { MFnDagNode fnDag( curveObj[i] ); MFnNurbsCurve fnCurve( fnDag.child( 0 ) ); nverts[i] = fnCurve.numCVs() + 4; cvcount += nverts[i]; } CVs = shared_array< RtFloat >( new RtFloat[ cvcount * 3 ] ); unsigned k( 0 ); for( unsigned i( 0 ); i < ncurves; i++ ) { MFnDagNode fnCurve( curveObj[i] ); MMatrix mCurve( curveDag[i].inclusiveMatrix() ); mCurve -= m; mCurve += MMatrix::identity; MObject oCurveChild( fnCurve.child( 0 ) ); MItCurveCV curveIt( oCurveChild ); MPoint pt = curveIt.position(); pt *= mCurve; CVs[k++] = (float)pt.x; CVs[k++] = (float)pt.y; CVs[k++] = (float)pt.z; CVs[k++] = (float)pt.x; CVs[k++] = (float)pt.y; CVs[k++] = (float)pt.z; for( curveIt.reset(); !curveIt.isDone(); curveIt.next() ) { pt = curveIt.position(); pt *= mCurve; CVs[k++] = (float)pt.x; CVs[k++] = (float)pt.y; CVs[k++] = (float)pt.z; } CVs[k++] = (float)pt.x; CVs[k++] = (float)pt.y; CVs[k++] = (float)pt.z; CVs[k++] = (float)pt.x; CVs[k++] = (float)pt.y; CVs[k++] = (float)pt.z; } liqTokenPointer pointsPointerPair; pointsPointerPair.set( "P", rPoint, cvcount ); pointsPointerPair.setDetailType( rVertex ); pointsPointerPair.setTokenFloats( CVs ); // Warning: CVs shares ownership with of its data with pointsPointerPair now! // Saves us from redundant copying as long as we know what we are doing tokenPointerArray.push_back( pointsPointerPair ); // constant width or not float baseWidth( .1 ), tipWidth( .1 ); bool constantWidth( false ); liquidGetPlugValue( fnDag, "liquidCurveBaseWidth", baseWidth, status ); liquidGetPlugValue( fnDag, "liquidCurveTipWidth", tipWidth, status ); if( tipWidth == baseWidth ) constantWidth = true; if ( constantWidth ) { liqTokenPointer pConstWidthPointerPair; pConstWidthPointerPair.set( "constantwidth", rFloat ); pConstWidthPointerPair.setDetailType( rConstant ); pConstWidthPointerPair.setTokenFloat( 0, baseWidth ); tokenPointerArray.push_back( pConstWidthPointerPair ); } else { NuCurveWidth = shared_array< RtFloat >( new RtFloat[ cvcount - ncurves * 2 ] ); k = 0; for( unsigned i( 0 ); i < ncurves; i++ ) { // easy way just linear - might have to be refined MItCurveCV itCurve( curveObj[i] ); NuCurveWidth[k++] = baseWidth; NuCurveWidth[k++] = baseWidth; for( unsigned n( 3 ); n < nverts[i] - 3; n++ ) { float difference = tipWidth - baseWidth; if( difference < 0 ) difference *= -1; float basew ( baseWidth ); if( baseWidth > tipWidth ) NuCurveWidth[k++] = basew - ( n - 2 ) * difference / ( nverts[i] - 5 ); else NuCurveWidth[k++] = basew + ( n - 2 ) * difference / ( nverts[i] - 5 ); } NuCurveWidth[k++] = tipWidth; NuCurveWidth[k++] = tipWidth; } liqTokenPointer widthPointerPair; widthPointerPair.set( "width", rFloat, cvcount - ncurves * 2 ); widthPointerPair.setDetailType( rVarying ); widthPointerPair.setTokenFloats( NuCurveWidth ); tokenPointerArray.push_back( widthPointerPair ); } addAdditionalSurfaceParameters( curveGroup ); }
/* Utility method to update shader parameters based on available lighting information. */ static void updateLightShader( MHWRender::MShaderInstance *shaderInstance, const MHWRender::MDrawContext & context, const MSelectionList * lightList ) { if (!shaderInstance) return; // Check pass context information to see if we are in a shadow // map update pass. If so do nothing. // const MHWRender::MPassContext & passCtx = context.getPassContext(); const MStringArray & passSem = passCtx.passSemantics(); bool handlePass = true; for (unsigned int i=0; i<passSem.length() && handlePass; i++) { // Handle special pass drawing. // if (passSem[i] == MHWRender::MPassContext::kShadowPassSemantic) { handlePass = false; } } if (!handlePass) return; // // Perform light shader update with lighting information // If the light list is not empty then use that light's information. // Otherwise choose the first appropriate light which can cast shadows. // // Defaults in case there are no lights // bool globalShadowsOn = false; bool localShadowsOn = false; bool shadowDirty = false; MFloatVector direction(0.0f, 0.0f, 1.0f); float lightIntensity = 0.0f; // If no lights then black out the light float lightColor[3] = { 0.0f, 0.0f, 0.0f }; MStatus status; // Scan to find the first N lights that has a direction component in it // It's possible we find no lights. // MHWRender::MDrawContext::LightFilter considerAllSceneLights = MHWRender::MDrawContext::kFilteredIgnoreLightLimit; unsigned int lightCount = context.numberOfActiveLights(considerAllSceneLights); if (lightCount) { MFloatArray floatVals; MIntArray intVals; MHWRender::MTextureAssignment shadowResource; shadowResource.texture = NULL; MHWRender::MSamplerStateDesc samplerDesc; MMatrix shadowViewProj; float shadowColor[3] = { 0.0f, 0.0f, 0.0f }; unsigned int i=0; bool foundDirectional = false; for (i=0; i<lightCount && !foundDirectional ; i++) { MHWRender::MLightParameterInformation *lightParam = context.getLightParameterInformation( i, considerAllSceneLights ); if (lightParam) { // Prune against light list if any. if (lightList && lightList->length()) { if (!lightList->hasItem(lightParam->lightPath())) continue; } MStringArray params; lightParam->parameterList(params); for (unsigned int p=0; p<params.length(); p++) { MString pname = params[p]; MHWRender::MLightParameterInformation::StockParameterSemantic semantic = lightParam->parameterSemantic( pname ); switch (semantic) { // Pick a few light parameters to pick up as an example case MHWRender::MLightParameterInformation::kWorldDirection: lightParam->getParameter( pname, floatVals ); direction = MFloatVector( floatVals[0], floatVals[1], floatVals[2] ); foundDirectional = true; break; case MHWRender::MLightParameterInformation::kIntensity: lightParam->getParameter( pname, floatVals ); lightIntensity = floatVals[0]; break; case MHWRender::MLightParameterInformation::kColor: lightParam->getParameter( pname, floatVals ); lightColor[0] = floatVals[0]; lightColor[1] = floatVals[1]; lightColor[2] = floatVals[2]; break; // Pick up shadowing parameters case MHWRender::MLightParameterInformation::kGlobalShadowOn: lightParam->getParameter( pname, intVals ); if (intVals.length()) globalShadowsOn = (intVals[0] != 0) ? true : false; break; case MHWRender::MLightParameterInformation::kShadowOn: lightParam->getParameter( pname, intVals ); if (intVals.length()) localShadowsOn = (intVals[0] != 0) ? true : false; break; case MHWRender::MLightParameterInformation::kShadowViewProj: lightParam->getParameter( pname, shadowViewProj); break; case MHWRender::MLightParameterInformation::kShadowMap: lightParam->getParameter( pname, shadowResource ); break; case MHWRender::MLightParameterInformation::kShadowDirty: if (intVals.length()) shadowDirty = (intVals[0] != 0) ? true : false; break; case MHWRender::MLightParameterInformation::kShadowSamp: lightParam->getParameter( pname, samplerDesc ); break; case MHWRender::MLightParameterInformation::kShadowColor: lightParam->getParameter( pname, floatVals ); shadowColor[0] = floatVals[0]; shadowColor[1] = floatVals[1]; shadowColor[2] = floatVals[2]; break; default: break; } } /* for params */ } if (foundDirectional && globalShadowsOn && localShadowsOn && shadowResource.texture) { void *resourceHandle = shadowResource.texture->resourceHandle(); if (resourceHandle) { static bool debugShadowBindings = false; status = shaderInstance->setParameter("mayaShadowPCF1_shadowMap", shadowResource ); if (status == MStatus::kSuccess && debugShadowBindings) fprintf(stderr, "Bound shadow map to shader param mayaShadowPCF1_shadowMap\n"); status = shaderInstance->setParameter("mayaShadowPCF1_shadowViewProj", shadowViewProj ); if (status == MStatus::kSuccess && debugShadowBindings) fprintf(stderr, "Bound shadow map transform to shader param mayaShadowPCF1_shadowViewProj\n"); status = shaderInstance->setParameter("mayaShadowPCF1_shadowColor", &shadowColor[0] ); if (status == MStatus::kSuccess && debugShadowBindings) fprintf(stderr, "Bound shadow map color to shader param mayaShadowPCF1_shadowColor\n"); } MHWRender::MRenderer* renderer = MHWRender::MRenderer::theRenderer(); if (renderer) { MHWRender::MTextureManager* textureManager = renderer->getTextureManager(); if (textureManager) { textureManager->releaseTexture(shadowResource.texture); } } shadowResource.texture = NULL; } } } // Set up parameters which should be set regardless of light existence. status = shaderInstance->setParameter("mayaDirectionalLight_direction", &( direction[0] )); status = shaderInstance->setParameter("mayaDirectionalLight_intensity", lightIntensity ); status = shaderInstance->setParameter("mayaDirectionalLight_color", &( lightColor[0] )); status = shaderInstance->setParameter("mayaShadowPCF1_mayaGlobalShadowOn", globalShadowsOn); status = shaderInstance->setParameter("mayaShadowPCF1_mayaShadowOn", localShadowsOn); }
//The writer simply goes gathers all objects from the scene. //We will check if the object has a transform, if so, we will check //if it's either a nurbsSphere, nurbsCone or nurbsCylinder. If so, //we will write it out. MStatus LepTranslator::writer ( const MFileObject& file, const MString& options, MPxFileTranslator::FileAccessMode mode) { MStatus status; bool showPositions = false; unsigned int i; const MString fname = file.fullName(); ofstream newf(fname.asChar(), ios::out); if (!newf) { // open failed cerr << fname << ": could not be opened for reading\n"; return MS::kFailure; } newf.setf(ios::unitbuf); if (options.length() > 0) { // Start parsing. MStringArray optionList; MStringArray theOption; options.split(';', optionList); // break out all the options. for( i = 0; i < optionList.length(); ++i ){ theOption.clear(); optionList[i].split( '=', theOption ); if( theOption[0] == MString("showPositions") && theOption.length() > 1 ) { if( theOption[1].asInt() > 0 ){ showPositions = true; }else{ showPositions = false; } } } } // output our magic number newf << "<LEP>\n"; MItDag dagIterator( MItDag::kBreadthFirst, MFn::kInvalid, &status); if ( !status) { status.perror ("Failure in DAG iterator setup"); return MS::kFailure; } MSelectionList selection; MGlobal::getActiveSelectionList (selection); MItSelectionList selIterator (selection, MFn::kDagNode); bool done = false; while (true) { MObject currentNode; switch (mode) { case MPxFileTranslator::kSaveAccessMode: case MPxFileTranslator::kExportAccessMode: if (dagIterator.isDone ()) done = true; else { currentNode = dagIterator.item (); dagIterator.next (); } break; case MPxFileTranslator::kExportActiveAccessMode: if (selIterator.isDone ()) done = true; else { selIterator.getDependNode (currentNode); selIterator.next (); } break; default: cerr << "Unrecognized write mode: " << mode << endl; break; } if (done) break; //We only care about nodes that are transforms MFnTransform dagNode(currentNode, &status); if ( status == MS::kSuccess ) { MString nodeNameNoNamespace=MNamespace::stripNamespaceFromName(dagNode.name()); for (i = 0; i < numPrimitives; ++i) { if(nodeNameNoNamespace.indexW(primitiveStrings[i]) >= 0){ // This is a node we support newf << primitiveCommands[i] << " -n " << nodeNameNoNamespace << endl; if (showPositions) { MVector pos; pos = dagNode.getTranslation(MSpace::kObject); newf << "move " << pos.x << " " << pos.y << " " << pos.z << endl; } } } }//if (status == MS::kSuccess) }//while loop newf.close(); return MS::kSuccess; }
void NifMeshExporterSkyrim::ExportMesh( MObject dagNode ) { //out << "NifTranslator::ExportMesh {"; ComplexShape cs; MStatus stat; MObject mesh; //Find Mesh child of given transform object MFnDagNode nodeFn(dagNode); cs.SetName(this->translatorUtils->MakeNifName(nodeFn.name())); for (int i = 0; i != nodeFn.childCount(); ++i) { // get a handle to the child if (nodeFn.child(i).hasFn(MFn::kMesh)) { MFnMesh tempFn(nodeFn.child(i)); //No history items if (!tempFn.isIntermediateObject()) { //out << "Found a mesh child." << endl; mesh = nodeFn.child(i); break; } } } MFnMesh visibleMeshFn(mesh, &stat); if (stat != MS::kSuccess) { //out << stat.errorString().asChar() << endl; throw runtime_error("Failed to create visibleMeshFn."); } //out << visibleMeshFn.name().asChar() << ") {" << endl; MFnMesh meshFn; MObject dataObj; MPlugArray inMeshPlugArray; MPlug childPlug; MPlug geomPlug; MPlug inputPlug; // this will hold the returned vertex positions MPointArray vts; //For now always use the visible mesh meshFn.setObject(mesh); //out << "Use the function set to get the points" << endl; // use the function set to get the points stat = meshFn.getPoints(vts); if (stat != MS::kSuccess) { //out << stat.errorString().asChar() << endl; throw runtime_error("Failed to get points."); } //Maya won't store any information about objects with no vertices. Just skip it. if (vts.length() == 0) { MGlobal::displayWarning("An object in this scene has no vertices. Nothing will be exported."); return; } vector<WeightedVertex> nif_vts(vts.length()); for (int i = 0; i != vts.length(); ++i) { nif_vts[i].position.x = float(vts[i].x); nif_vts[i].position.y = float(vts[i].y); nif_vts[i].position.z = float(vts[i].z); } //Set vertex info later since it includes skin weights //cs.SetVertices( nif_vts ); //out << "Use the function set to get the colors" << endl; MColorArray myColors; meshFn.getFaceVertexColors(myColors); //out << "Prepare NIF color vector" << endl; vector<Color4> niColors(myColors.length()); for (unsigned int i = 0; i < myColors.length(); ++i) { niColors[i] = Color4(myColors[i].r, myColors[i].g, myColors[i].b, myColors[i].a); } cs.SetColors(niColors); // this will hold the returned vertex positions MFloatVectorArray nmls; //out << "Use the function set to get the normals" << endl; // use the function set to get the normals stat = meshFn.getNormals(nmls, MSpace::kTransform); if (stat != MS::kSuccess) { //out << stat.errorString().asChar() << endl; throw runtime_error("Failed to get normals"); } //out << "Prepare NIF normal vector" << endl; vector<Vector3> nif_nmls(nmls.length()); for (int i = 0; i != nmls.length(); ++i) { nif_nmls[i].x = float(nmls[i].x); nif_nmls[i].y = float(nmls[i].y); nif_nmls[i].z = float(nmls[i].z); } cs.SetNormals(nif_nmls); //out << "Use the function set to get the UV set names" << endl; MStringArray uvSetNames; MString baseUVSet; MFloatArray myUCoords; MFloatArray myVCoords; bool has_uvs = false; // get the names of the uv sets on the mesh meshFn.getUVSetNames(uvSetNames); vector<TexCoordSet> nif_uvs; //Record assotiation between name and uv set index for later map<string, int> uvSetNums; int set_num = 0; for (unsigned int i = 0; i < uvSetNames.length(); ++i) { if (meshFn.numUVs(uvSetNames[i]) > 0) { TexType tt; string set_name = uvSetNames[i].asChar(); if (set_name == "base" || set_name == "map1") { tt = BASE_MAP; } else if (set_name == "dark") { tt = DARK_MAP; } else if (set_name == "detail") { tt = DETAIL_MAP; } else if (set_name == "gloss") { tt = GLOSS_MAP; } else if (set_name == "glow") { tt = GLOW_MAP; } else if (set_name == "bump") { tt = BUMP_MAP; } else if (set_name == "decal0") { tt = DECAL_0_MAP; } else if (set_name == "decal1") { tt = DECAL_1_MAP; } else { tt = BASE_MAP; } //Record the assotiation uvSetNums[set_name] = set_num; //Get the UVs meshFn.getUVs(myUCoords, myVCoords, &uvSetNames[i]); //Make sure this set actually has some UVs in it. Maya sometimes returns empty UV sets. if (myUCoords.length() == 0) { continue; } //Store the data TexCoordSet tcs; tcs.texType = tt; tcs.texCoords.resize(myUCoords.length()); for (unsigned int j = 0; j < myUCoords.length(); ++j) { tcs.texCoords[j].u = myUCoords[j]; //Flip the V coords tcs.texCoords[j].v = 1.0f - myVCoords[j]; } nif_uvs.push_back(tcs); baseUVSet = uvSetNames[i]; has_uvs = true; set_num++; } } cs.SetTexCoordSets(nif_uvs); // this will hold references to the shaders used on the meshes MObjectArray Shaders; // this is used to hold indices to the materials returned in the object array MIntArray FaceIndices; //out << "Get the connected shaders" << endl; // get the shaders used by the i'th mesh instance // Assume this is not instanced for now // TODO support instancing properly stat = visibleMeshFn.getConnectedShaders(0, Shaders, FaceIndices); if (stat != MS::kSuccess) { //out << stat.errorString().asChar() << endl; throw runtime_error("Failed to get connected shader list."); } vector<ComplexFace> nif_faces; //Add shaders to propGroup array vector< vector<NiPropertyRef> > propGroups; for (unsigned int shader_num = 0; shader_num < Shaders.length(); ++shader_num) { //Maya sometimes lists shaders that are not actually attached to any face. Disregard them. bool shader_is_used = false; for (size_t f = 0; f < FaceIndices.length(); ++f) { if (FaceIndices[f] == shader_num) { shader_is_used = true; break; } } if (shader_is_used == false) { //Shader isn't actually used, so continue to the next one. continue; } //out << "Found attached shader: "; //Attach all properties previously associated with this shader to //this NiTriShape MFnDependencyNode fnDep(Shaders[shader_num]); //Find the shader that this shading group connects to MPlug p = fnDep.findPlug("surfaceShader"); MPlugArray plugs; p.connectedTo(plugs, true, false); for (unsigned int i = 0; i < plugs.length(); ++i) { if (plugs[i].node().hasFn(MFn::kLambert)) { fnDep.setObject(plugs[i].node()); break; } } //out << fnDep.name().asChar() << endl; vector<NiPropertyRef> niProps = this->translatorData->shaders[fnDep.name().asChar()]; propGroups.push_back(niProps); } cs.SetPropGroups(propGroups); //out << "Export vertex and normal data" << endl; // attach an iterator to the mesh MItMeshPolygon itPoly(mesh, &stat); if (stat != MS::kSuccess) { throw runtime_error("Failed to create polygon iterator."); } // Create a list of faces with vertex IDs, and duplicate normals so they have the same ID for (; !itPoly.isDone(); itPoly.next()) { int poly_vert_count = itPoly.polygonVertexCount(&stat); if (stat != MS::kSuccess) { throw runtime_error("Failed to get vertex count."); } //Ignore polygons with less than 3 vertices if (poly_vert_count < 3) { continue; } ComplexFace cf; //Assume all faces use material 0 for now cf.propGroupIndex = 0; for (int i = 0; i < poly_vert_count; ++i) { ComplexPoint cp; cp.vertexIndex = itPoly.vertexIndex(i); cp.normalIndex = itPoly.normalIndex(i); if (niColors.size() > 0) { int color_index; stat = meshFn.getFaceVertexColorIndex(itPoly.index(), i, color_index); if (stat != MS::kSuccess) { //out << stat.errorString().asChar() << endl; throw runtime_error("Failed to get vertex color."); } cp.colorIndex = color_index; } //Get the UV set names used by this particular vertex MStringArray vertUvSetNames; itPoly.getUVSetNames(vertUvSetNames); for (unsigned int j = 0; j < vertUvSetNames.length(); ++j) { TexCoordIndex tci; tci.texCoordSetIndex = uvSetNums[vertUvSetNames[j].asChar()]; int uv_index; itPoly.getUVIndex(i, uv_index, &vertUvSetNames[j]); tci.texCoordIndex = uv_index; cp.texCoordIndices.push_back(tci); } cf.points.push_back(cp); } nif_faces.push_back(cf); } //Set shader/face association if (nif_faces.size() != FaceIndices.length()) { throw runtime_error("Num faces found do not match num faces reported."); } for (unsigned int face_index = 0; face_index < nif_faces.size(); ++face_index) { nif_faces[face_index].propGroupIndex = FaceIndices[face_index]; } cs.SetFaces(nif_faces); //--Skin Processing--// //Look up any skin clusters if (this->translatorData->meshClusters.find(visibleMeshFn.fullPathName().asChar()) != this->translatorData->meshClusters.end()) { const vector<MObject> & clusters = this->translatorData->meshClusters[visibleMeshFn.fullPathName().asChar()]; if (clusters.size() > 1) { throw runtime_error("Objects with multiple skin clusters affecting them are not currently supported. Try deleting the history and re-binding them."); } vector<MObject>::const_iterator cluster = clusters.begin(); if (cluster->isNull() != true) { MFnSkinCluster clusterFn(*cluster); //out << "Processing skin..." << endl; //Get path to visible mesh MDagPath meshPath; visibleMeshFn.getPath(meshPath); //out << "Getting a list of all verticies in this mesh" << endl; //Get a list of all vertices in this mesh MFnSingleIndexedComponent compFn; MObject vertices = compFn.create(MFn::kMeshVertComponent); MItGeometry gIt(meshPath); MIntArray vertex_indices(gIt.count()); for (int vert_index = 0; vert_index < gIt.count(); ++vert_index) { vertex_indices[vert_index] = vert_index; } compFn.addElements(vertex_indices); //out << "Getting Influences" << endl; //Get influences MDagPathArray myBones; clusterFn.influenceObjects(myBones, &stat); //out << "Creating a list of NiNodeRefs of influences." << endl; //Create list of NiNodeRefs of influences vector<NiNodeRef> niBones(myBones.length()); for (unsigned int bone_index = 0; bone_index < niBones.size(); ++bone_index) { const char* boneName = myBones[bone_index].fullPathName().asChar(); if (this->translatorData->nodes.find(myBones[bone_index].fullPathName().asChar()) == this->translatorData->nodes.end()) { //There is a problem; one of the joints was not exported. Abort. throw runtime_error("One of the joints necessary to export a bound skin was not exported."); } niBones[bone_index] = this->translatorData->nodes[myBones[bone_index].fullPathName().asChar()]; } //out << "Getting weights from Maya" << endl; //Get weights from Maya MDoubleArray myWeights; unsigned int bone_count = myBones.length(); stat = clusterFn.getWeights(meshPath, vertices, myWeights, bone_count); if (stat != MS::kSuccess) { //out << stat.errorString().asChar() << endl; throw runtime_error("Failed to get vertex weights."); } //out << "Setting skin influence list in ComplexShape" << endl; //Set skin information in ComplexShape cs.SetSkinInfluences(niBones); //out << "Adding weights to ComplexShape vertices" << endl; //out << "Number of weights: " << myWeights.length() << endl; //out << "Number of bones: " << myBones.length() << endl; //out << "Number of Maya vertices: " << gIt.count() << endl; //out << "Number of NIF vertices: " << int(nif_vts.size()) << endl; unsigned int weight_index = 0; SkinInfluence sk; for (unsigned int vert_index = 0; vert_index < nif_vts.size(); ++vert_index) { for (unsigned int bone_index = 0; bone_index < myBones.length(); ++bone_index) { //out << "vert_index: " << vert_index << " bone_index: " << bone_index << " weight_index: " << weight_index << endl; // Only bother with weights that are significant if (myWeights[weight_index] > 0.0f) { sk.influenceIndex = bone_index; sk.weight = float(myWeights[weight_index]); nif_vts[vert_index].weights.push_back(sk); } ++weight_index; } } } MPlugArray connected_dismember_plugs; MObjectArray dismember_nodes; meshFn.findPlug("message").connectedTo(connected_dismember_plugs, false, true); bool has_valid_dismemember_partitions = true; int faces_count = cs.GetFaces().size(); int current_face_index; vector<BodyPartList> body_parts_list; vector<uint> dismember_faces(faces_count, 0); for (int x = 0; x < connected_dismember_plugs.length(); x++) { MFnDependencyNode dependency_node(connected_dismember_plugs[x].node()); if (dependency_node.typeName() == "nifDismemberPartition") { dismember_nodes.append(dependency_node.object()); } } if (dismember_nodes.length() == 0) { has_valid_dismemember_partitions = false; } else { int blind_data_id; int blind_data_value; MStatus status; MPlug target_faces_plug; MItMeshPolygon it_polygons(meshFn.object()); MString mel_command; MStringArray current_body_parts_flags; MFnDependencyNode current_dismember_node; MFnDependencyNode current_blind_data_node; //Naive sort here, there is no reason and is extremely undesirable and not recommended to have more //than 10-20 dismember partitions out of many reasons, so it's okay here //as it makes the code easier to understand vector<int> dismember_nodes_id(dismember_nodes.length(), -1); for (int x = 0; x < dismember_nodes.length(); x++) { current_dismember_node.setObject(dismember_nodes[x]); connected_dismember_plugs.clear(); current_dismember_node.findPlug("targetFaces").connectedTo(connected_dismember_plugs, true, false); if (connected_dismember_plugs.length() == 0) { has_valid_dismemember_partitions = false; break; } current_blind_data_node.setObject(connected_dismember_plugs[0].node()); dismember_nodes_id[x] = current_blind_data_node.findPlug("typeId").asInt(); } for (int x = 0; x < dismember_nodes.length() - 1; x++) { for (int y = x + 1; y < dismember_nodes.length(); y++) { if (dismember_nodes_id[x] > dismember_nodes_id[y]) { MObject aux = dismember_nodes[x]; blind_data_id = dismember_nodes_id[x]; dismember_nodes[x] = dismember_nodes[y]; dismember_nodes_id[x] = dismember_nodes_id[y]; dismember_nodes[y] = aux; dismember_nodes_id[y] = blind_data_id; } } } for (int x = 0; x < dismember_nodes.length(); x++) { current_dismember_node.setObject(dismember_nodes[x]); target_faces_plug = current_dismember_node.findPlug("targetFaces"); connected_dismember_plugs.clear(); target_faces_plug.connectedTo(connected_dismember_plugs, true, false); if (connected_dismember_plugs.length() > 0) { current_blind_data_node.setObject(connected_dismember_plugs[0].node()); current_face_index = 0; blind_data_id = current_blind_data_node.findPlug("typeId").asInt(); for (it_polygons.reset(); !it_polygons.isDone(); it_polygons.next()) { if (it_polygons.polygonVertexCount() >= 3) { status = meshFn.getIntBlindData(it_polygons.index(), MFn::Type::kMeshPolygonComponent, blind_data_id, "dismemberValue", blind_data_value); if (status == MStatus::kSuccess && blind_data_value == 1 && meshFn.hasBlindDataComponentId(it_polygons.index(), MFn::Type::kMeshPolygonComponent, blind_data_id)) { dismember_faces[current_face_index] = x; } current_face_index++; } } } else { has_valid_dismemember_partitions = false; break; } mel_command = "getAttr "; mel_command += current_dismember_node.name(); mel_command += ".bodyPartsFlags"; status = MGlobal::executeCommand(mel_command, current_body_parts_flags); BSDismemberBodyPartType body_part_type = NifDismemberPartition::stringArrayToBodyPartType(current_body_parts_flags); current_body_parts_flags.clear(); mel_command = "getAttr "; mel_command += current_dismember_node.name(); mel_command += ".partsFlags"; status = MGlobal::executeCommand(mel_command, current_body_parts_flags); BSPartFlag part_type = NifDismemberPartition::stringArrayToPart(current_body_parts_flags); current_body_parts_flags.clear(); BodyPartList body_part; body_part.bodyPart = body_part_type; body_part.partFlag = part_type; body_parts_list.push_back(body_part); } } if (has_valid_dismemember_partitions == false) { MGlobal::displayWarning("No proper dismember partitions, generating default ones for " + meshFn.name()); for (int x = 0; x < dismember_faces.size(); x++) { dismember_faces[x] = 0; } BodyPartList body_part; body_part.bodyPart = (BSDismemberBodyPartType)0; body_part.partFlag = (BSPartFlag)(PF_EDITOR_VISIBLE | PF_START_NET_BONESET); body_parts_list.clear(); body_parts_list.push_back(body_part); } cs.SetDismemberPartitionsBodyParts(body_parts_list); cs.SetDismemberPartitionsFaces(dismember_faces); } //out << "Setting vertex info" << endl; //Set vertex info now that any skins have been processed cs.SetVertices(nif_vts); //ComplexShape is now complete, so split it //Get parent NiNodeRef parNode = this->translatorUtils->GetDAGParent(dagNode); Matrix44 transform = Matrix44::IDENTITY; vector<NiNodeRef> influences = cs.GetSkinInfluences(); if (influences.size() > 0) { //This is a skin, so we use the common ancestor of all influences //as the parent vector<NiAVObjectRef> objects; for (size_t i = 0; i < influences.size(); ++i) { objects.push_back(StaticCast<NiAVObject>(influences[i])); } //Get world transform of existing parent Matrix44 oldParWorld = parNode->GetWorldTransform(); //Set new parent node parNode = FindCommonAncestor(objects); transform = oldParWorld * parNode->GetWorldTransform().Inverse(); } //Get transform using temporary NiAVObject NiAVObjectRef tempAV = new NiAVObject; this->nodeExporter->ExportAV(tempAV, dagNode); NiAVObjectRef avObj; if (this->translatorOptions->exportTangentSpace == "falloutskyrimtangentspace") { //out << "Split ComplexShape from " << meshFn.name().asChar() << endl; avObj = cs.Split(parNode, tempAV->GetLocalTransform() * transform, this->translatorOptions->exportBonesPerSkinPartition, this->translatorOptions->exportAsTriStrips, true, this->translatorOptions->exportMinimumVertexWeight, 16); } else { avObj = cs.Split(parNode, tempAV->GetLocalTransform() * transform, this->translatorOptions->exportBonesPerSkinPartition, this->translatorOptions->exportAsTriStrips, false, this->translatorOptions->exportMinimumVertexWeight); } //out << "Get the NiAVObject portion of the root of the split" <<endl; //Get the NiAVObject portion of the root of the split avObj->SetName(tempAV->GetName()); avObj->SetVisibility(tempAV->GetVisibility()); avObj->SetFlags(tempAV->GetFlags()); //If polygon mesh is hidden, hide tri_shape MPlug vis = visibleMeshFn.findPlug(MString("visibility")); bool visibility; vis.getValue(visibility); NiNodeRef splitRoot = DynamicCast<NiNode>(avObj); if (splitRoot != NULL) { //Root is a NiNode with NiTriBasedGeom children. vector<NiAVObjectRef> children = splitRoot->GetChildren(); for (unsigned c = 0; c < children.size(); ++c) { //Set the default collision propogation flag to "use triangles" children[c]->SetFlags(2); // Make the mesh invisible if necessary if (visibility == false) { children[c]->SetVisibility(false); } } } else { //Root must be a NiTriBasedGeom. Make it invisible if necessary if (visibility == false) { avObj->SetVisibility(false); } } }
void ShaderValidConnection::setValidConnection() { MStringArray validConnection; //null (dummy shader) validConnection.clear(); validConnection.append(""); validConnectionMap.insert(std::make_pair("null", validConnection)); // MATERIAL ----------------------------------- /// surface /// //anisotropic //hairTubeShader //lambert validConnection.clear(); validConnection.append("color"); validConnection.append("transparency"); validConnection.append("ambientColor"); validConnection.append("incandescence"); validConnection.append("diffuse"); validConnection.append("outColor"); validConnection.append("outTransparency"); validConnectionMap.insert(std::make_pair("lambert", validConnection)); //layered shader //blinn validConnection.clear(); validConnection.append("color"); validConnection.append("transparency"); validConnection.append("ambientColor"); validConnection.append("incandescence"); validConnection.append("diffuse"); validConnection.append("eccentricity"); validConnection.append("specularRollOff"); validConnection.append("specularColor"); validConnection.append("reflectivity"); validConnection.append("reflectedColor"); validConnection.append("outColor"); validConnectionMap.insert(std::make_pair("blinn", validConnection)); //oceanShader //phong validConnection.clear(); validConnection.append("color"); validConnection.append("transparency"); validConnection.append("ambientColor"); validConnection.append("incandescence"); validConnection.append("normalCamera"); validConnection.append("diffuse"); validConnection.append("translucence"); validConnection.append("translucenceDepth"); validConnection.append("translucenceFocus"); validConnection.append("cosinePower"); validConnection.append("specularColor"); validConnection.append("reflectivity"); validConnection.append("reflectedColor"); validConnection.append("matteOpacityMode"); validConnection.append("matteOpacity"); validConnection.append("reflectionLimit"); validConnection.append("outColor"); validConnection.append("outTransparency"); validConnectionMap.insert(std::make_pair("phong", validConnection)); //phongE //rampShader //shadingMap //surfaceShader //useBackground /// Volumetric /// //envFog //fluidShape //lightFog //particleCloud //volumeFog //volumeShader /// DISPLACEMENT /// //displacement /// 2D Texture (normal)/// //bulge //checker validConnection.clear(); validConnection.append("alphaGain"); validConnection.append("alphaIsLuminance"); validConnection.append("alphaOffset"); validConnection.append("color1");//color1 validConnection.append("color1R"); validConnection.append("color1G"); validConnection.append("color1B"); validConnection.append("color2");//color2 validConnection.append("color2R"); validConnection.append("color2G"); validConnection.append("color2B"); validConnection.append("colorGain"); validConnection.append("colorOffset"); validConnection.append("contrast"); validConnection.append("defaultColor"); validConnection.append("filter"); validConnection.append("filterOffset"); validConnection.append("invert"); validConnection.append("uvCoord");//uvCoord validConnection.append("uCoord"); validConnection.append("vCoord"); validConnection.append("outAlpha"); validConnection.append("outColor");//outColor validConnection.append("outColorR"); validConnection.append("outColorG"); validConnection.append("outColorB"); validConnectionMap.insert(std::make_pair("checker", validConnection)); //cloth // file validConnection.clear(); validConnection.append("alphaGain"); validConnection.append("alphaIsLuminance"); validConnection.append("alphaOffset"); validConnection.append("colorGain"); validConnection.append("colorOffset"); validConnection.append("defaultColor"); validConnection.append("fileTextureName"); validConnection.append("filterType"); validConnection.append("filter"); validConnection.append("filterOffset"); validConnection.append("invert"); validConnection.append("uvCoord"); validConnection.append("fileHasAlpha"); validConnection.append("outAlpha"); validConnection.append("outColor"); validConnection.append("outTransparency"); validConnectionMap.insert(std::make_pair("file", validConnection)); //fluidTexture2D //fractal //grid //mountain //movie //noise //ocean //psdFileTex //ramp //water /// 3D Textures /// //brownian //cloud //crater //fluidTexture3D //granite //leather //marble //rock //snow //solidFractal //stucco //volumeNoise //wood /// Env Textures /// //envBall //envChrome //envCube //envSky //envSphere /// other textures /// //layeredTexture /// Lights /// //ambientLight //areaLight //directionalLight //pointLight //spotLight //volumeLight /// General utilities /// //arrayMapper //bump2d validConnection.clear(); validConnection.append("bumpValue"); validConnection.append("bumpDepth"); validConnection.append("bumpInterp"); validConnection.append("bumpFilter"); validConnection.append("bumpFilterOffset"); validConnection.append("normalCamera"); validConnection.append("bumpNormal"); validConnection.append("outNormal"); validConnectionMap.insert(std::make_pair("bump2d", validConnection)); //bump3d validConnection.clear(); validConnection.append("bumpValue"); validConnection.append("bumpDepth"); validConnection.append("bumpFilter"); validConnection.append("bumpFilterOffset"); validConnection.append("normalCamera"); validConnection.append("outNormal"); validConnectionMap.insert(std::make_pair("bump3d", validConnection)); //condition //distanceBetween //heightField //lightInfo //multiplyDivide //place2dTexture validConnection.clear(); validConnection.append("uvCoord"); validConnection.append("coverageU"); validConnection.append("coverageV"); validConnection.append("coverage"); validConnection.append("mirrorU"); validConnection.append("mirrorV"); validConnection.append("noiseU"); validConnection.append("noiseV"); validConnection.append("noiseUV"); validConnection.append("offsetU"); validConnection.append("offsetV"); validConnection.append("offset"); validConnection.append("repeatU"); validConnection.append("repeatV"); validConnection.append("repeatUV"); validConnection.append("rotateFrame"); validConnection.append("rotateUV"); validConnection.append("stagger"); validConnection.append("translateFrameU"); validConnection.append("translateFrameV"); validConnection.append("translateFrame"); validConnection.append("wrapU"); validConnection.append("wrapV"); validConnection.append("outUV"); validConnectionMap.insert(std::make_pair("place2dTexture", validConnection)); //place3dTexture //plusMinusAverage //projection //reverse //samplerInfo //setRange //stencil //studioClearCoat //uvChooser //vectorProduct /// color utilities /// //blendColors //clamp //contrast //gammaCorrect //hsvToRgb //luminance //remapColor //remapHsv //remapValue //rgbToHsv //smear //surfaceLuminance /// switch utilities /// //doubleShadingSwitch //quadShadingSwitch //singleShadingSwitch //tripleShadingSwitch /// particle utilities /// //particleSamplerInfo /// image planes /// //imagePlane /// glow /// //opticalFX setValidConnection_mi(); }
MStatus boingRbCmd::redoIt() { if (argParser->isFlagSet("help") || argParser->isFlagSet("h")) { MString helpMsg = "boingRB - command : Boing - bullet plugin by Risto Puukko\n"; helpMsg += "---------------------------------------------------------\n"; helpMsg += "boingRB [flag] [args] \n"; helpMsg += "\n"; helpMsg += "flags :\n"; helpMsg += " -getAttr [name.attr]\n"; helpMsg += " example : boingRb -getAttr (\"boingRb1.velocity\");\n" ; helpMsg += "\n"; helpMsg += " -getAttr [*.attr]\n"; helpMsg += " example : boingRb -getAttr (\"*.name\");\n" ; helpMsg += "\n"; helpMsg += " -setAttr [name.attr] -value [float float float ]\n"; helpMsg += " example : boingRb -setAttr (\"boingRb1.velocity\") -value 0 4 3 ;\n" ; helpMsg += "\n"; helpMsg += " -addAttr [name.attr] -type [int/double/string/vector]\n"; helpMsg += " example : boingRb -addAttr \"sampleRb.IntAttribute\" -type \"int\";\n" ; helpMsg += " example : boingRb -addAttr \"sampleRb.VectorAttribute\" -type \"vector\";\n" ; helpMsg += "\n"; helpMsg += " -create [ ( \"name=string;geo=string;velocity/vel=float,float,float;position/pos=float,float,float\" )]\n"; helpMsg += " example : boingRb -create (\"name=sampleRb;geo=pCubeShape1;pos=0,4,0\");\n"; helpMsg += "\n"; helpMsg += " -exists [name]\n"; helpMsg += " example : boingRb -exists \"sampleRb\";\n" ; helpMsg += "\n"; helpMsg += " -delete [name]\n"; helpMsg += " example : boingRb -delete \"sampleRb\";\n"; helpMsg += "\n"; helpMsg += "---------------------------------------------------------\n"; MGlobal::displayInfo(helpMsg); return MS::kSuccess; } isSetAttr = argParser->isFlagSet("-setAttr"); isGetAttr = argParser->isFlagSet("-getAttr"); isAddAttr = argParser->isFlagSet("-addAttr"); isType = argParser->isFlagSet("-type"); isExists = argParser->isFlagSet("-exists"); isAttributeExist = argParser->isFlagSet("-attributeExist"); isCreate = argParser->isFlagSet("-create"); isDelete = argParser->isFlagSet("-delete"); isValue = argParser->isFlagSet("-value"); //std::cout<<"argsList : "<<*argsList<<std::endl; //unsigned i; //MStatus stat; //MVector res; // Parse the arguments. /* for (i = 0; i <argsList->length (); i++) { //MString arg = argsList->asString(i, &stat); //if (MS::kSuccess == stat) std::cout<<"arg["<<i<<"] : "<<arg<<std::endl; if ( MString ("-setAttr") == argsList->asString(i, &stat) && MString ("-value") == argsList->asString(i+2, &stat) && MS::kSuccess == stat ) { for (unsigned j=3; j!=6; ++j) res[j-3 ] = argsList->asDouble (j, &stat); } } std::cout<<"res : "<<res<<std::endl; */ if (isSetAttr && isValue) { MString sAttr; argParser->getFlagArgument("setAttr", 0, sAttr); //std::cout<<sAttr<<std::endl; MStringArray jobArgsArray = parseArguments(sAttr, "."); MString rbName = jobArgsArray[0]; MString attr = checkAttribute(jobArgsArray[1]); //std::cout<<"attr : "<<attr<<std::endl; if ( attr == "custom" ) { MString customAttr = jobArgsArray[1]; //char * custAttr = (char*)customAttr.asChar(); //std::cout<<"customAttr : "<<customAttr<<std::endl; shared_ptr<bSolverNode> b_solv = bSolverNode::get_bsolver_node(); bSolverNode::m_custom_data *data = b_solv->getdata(rbName); //std::cout<<"data : "<<data<<std::endl; if (!data) return MS::kFailure; //std::cout<<"data->m_int_data : "<<data->m_int_data<<std::endl; MString type = b_solv->getAttrType(data, customAttr); //std::cout<<"attrype : "<<type<<std::endl; if (type == "string") { //std::cout<<"saving custom string : "<<customAttr<<std::endl; MString value; value = argsList->asString(3); data->m_string_data.append(value); b_solv->set_custom_data_string(data, customAttr, value); //data->m_attr_type.append(customAttr); //char * chars = (char *)value.asChar(); //void * char_ptr = (void *)chars; //b_solv->set_custom_data(customAttr, char_ptr); } else if (type == "double") { //std::cout<<"saving custom double : "<<customAttr<<std::endl; double value; value = argsList->asDouble(3); data->m_double_data.append(value); b_solv->set_custom_data_double(data, customAttr, value); //data->m_attr_type.append(customAttr); //void *val = &value; //b_solv->set_custom_data(customAttr, val); } else if (type == "int") { //std::cout<<"saving custom int : "<<customAttr<<std::endl; int value; value = argsList->asInt(3); //std::cout<<"argsList->get(3, value) -> value : "<<value<<std::endl; data->m_int_data.append(value); b_solv->set_custom_data_int(data, customAttr, value); //data->m_attr_type.append(customAttr); //std::cout<<"data->m_int_data : "<<data->m_int_data<<std::endl; //void *val = &value; //b_solv->set_custom_data(customAttr, val); //std::cout<<"b_solv->set_custom_data,static_cast<void*>(&value)) DONE!!!"<<std::endl; } else if (type == "vector") { //std::cout<<"saving custom vector : "<<customAttr<<std::endl; MVector value = MVector(); value.x = argsList->asDouble(3); value.y = argsList->asDouble(4); value.z = argsList->asDouble(5); data->m_vector_data.append(value); b_solv->set_custom_data_vector(data, customAttr, value); //data->m_attr_type.append(customAttr); //MVector *MVecPtr = &value; //void * vec_ptr = static_cast<void*const>(MVecPtr); //b_solv->set_custom_data(customAttr, vec_ptr); } } else { if (attr == "velocity" || attr == "position" || attr == "angularVelocity") { MVector value; value.x = argsList->asDouble(3); value.y = argsList->asDouble(4); value.z = argsList->asDouble(5); //std::cout<<"vector argument : "<<value<<std::endl; setBulletVectorAttribute(rbName, attr, value); } } //cout<<value<<endl; setResult(MS::kSuccess); } else if ( isAttributeExist ) { MString exAttr; bool result = false; argParser->getFlagArgument("attributeExist", 0, exAttr); //std::cout<<"exAttr : "<<exAttr<<std::endl; MStringArray jobArgsArray = parseArguments(exAttr, "."); MString rbname = jobArgsArray[0]; //std::cout<<"rbname : "<<rbname<<std::endl; MString attrToQuery = jobArgsArray[1]; //std::cout<<"attrToQuery : "<<attrToQuery<<std::endl; MString attr = checkAttribute(attrToQuery); //std::cout<<"attr : "<<attr<<std::endl; if ( attr == "custom" ){ // here we check if user attribute by the name attrToQuery exists shared_ptr<bSolverNode> b_solv = bSolverNode::get_bsolver_node(); //char * queryAttr = (char*)attrToQuery.asChar(); MString attrResult = b_solv->getAttrType(b_solv->getdata(rbname), attrToQuery); if (attrResult != "") //if (b_solv->attribute_exists(attrToQuery)) result = true; //std::cout<<result<<std::endl;; setResult(result); } } else if ( isAddAttr && isType ) { MString aAttr; argParser->getFlagArgument("addAttr", 0, aAttr); //std::cout<<"aAttr : "<<aAttr<<std::endl; MStringArray jobArgsArray = parseArguments(aAttr, "."); //std::cout<<"jobArgsArray : "<<jobArgsArray<<std::endl; MString rbname = jobArgsArray[0]; MString attrAdded = jobArgsArray[1]; //char *added = (char *)attrAdded.asChar(); MString attrType; argParser->getFlagArgument("-type", 0, attrType); //char *type = (char *)attrType.asChar(); //std::cout<<"attrType : "<<attrType<<std::endl; shared_ptr<bSolverNode> b_solv = bSolverNode::get_bsolver_node(); bSolverNode::m_custom_data *data = b_solv->getdata(rbname); data->m_attr_name.append(attrAdded); data->m_attr_type.append(attrType); b_solv->saveAttrType(data, attrAdded, attrType); //std::cout<<"attr "<<aAttr<<" added"<<std::endl; //std::cout<<"data->m_attr_type : "<<data->m_attr_type<<std::endl; //std::cout<<"data->m_attr_name : "<<data->m_attr_name<<std::endl; } else if ( isGetAttr) { MString gAttr; shared_ptr<bSolverNode> b_solv = bSolverNode::get_bsolver_node(); argParser->getFlagArgument("getAttr", 0, gAttr); //std::cout<<gAttr<<std::endl; MStringArray jobArgsArray = parseArguments(gAttr, "."); MString rbname = jobArgsArray[0]; //std::cout<<"name : "<<rbname<<std::endl; if ( rbname == "" ) { MString errorMsg = "ERROR ! boing -getAttr must provide a rigid body name!"; displayWarning(errorMsg, true); return MS::kFailure; } MString attr = checkAttribute(jobArgsArray[1]); //std::cout<<"attr = "<<attr<<std::endl; if ( attr=="velocity" || attr=="position" || attr=="angularVelocity" ) { //MVector result = MDoubleArray dResult = getBulletVectorAttribute(rbname, attr); setResult(dResult); } else if (attr == "contactPositions") { bSolverNode::m_custom_data *data = b_solv->getdata(rbname); MDoubleArray d_points = MDoubleArray(); if ( data->m_contact_count > 0 ) { MPointArray points = data->m_contact_positions; for (int i=0; i<points.length();i++) { d_points.append(points[i].x); d_points.append(points[i].y); d_points.append(points[i].z); } } setResult(d_points); } else if (attr == "contactGeos") { MStringArray contact_objects = MStringArray(); bSolverNode::m_custom_data *data = b_solv->getdata(rbname); if ( data->m_contact_count > 0 ) { MStringArray contact_objects = data->m_contact_objects; } setResult(contact_objects); } else if (attr == "contactCount") { bSolverNode::m_custom_data *data = b_solv->getdata(rbname); int contact_count = data->m_contact_count; setResult(contact_count); } else if (attr == "name") { MStringArray result; MStringArray names = b_solv->get_all_keys(); //std::cout<<"names : "<<names<<std::endl; //std::cout<<"b_solv->getdatalength() : "<<b_solv->getdatalength()<<std::endl; for(int i=0; i < names.length(); i++) { bSolverNode::m_custom_data *data = b_solv->getdata(names[i]); if ( NULL != data) { //std::cout<<"data->name : "<<data->name<<std::endl; //std::cout<<"data->m_initial_position: "<<data->m_initial_position<<std::endl; result.append(data->name); } } setResult(result); } else if ( attr == "" ) { MString errorMsg = "ERROR ! boing -getAttr must provide an attribute name to query!"; displayWarning(errorMsg, true); return MS::kFailure; } else if ( attr == "custom" ){ // here we handle user attributes MString customAttr = jobArgsArray[1]; //char * custAttr = (char*)customAttr.asChar(); //std::cout<<"customAttr : "<<customAttr<<std::endl; MString type = b_solv->getAttrType(b_solv->getdata(rbname), customAttr); //bSolverNode::m_custom_data *data = b_solv->getdata(rbname); std::cout<<" type : "<<type<<std::endl; if (type == "string") { //char * result = static_cast<char*>(b_solv->get_custom_data(customAttr)); MString result = b_solv->get_custom_data_string(b_solv->getdata(rbname), customAttr); if (result != NULL) { //std::cout<<"result : "<<result<<std::endl; MString value(result); setResult(value); } else { displayError(MString("Error getting b_solv->get_custom_data_string(\"" + customAttr + "\")")); } } else if (type == "double") { //double *value = static_cast<double*>(b_solv->get_custom_data(customAttr)); double value = b_solv->get_custom_data_double(b_solv->getdata(rbname), customAttr); setResult(value); } else if (type == "int") { //int *value = static_cast<int*>(b_solv->get_custom_data(customAttr)); int value = b_solv->get_custom_data_int(b_solv->getdata(rbname), customAttr); setResult(value); } else if (type == "vector") { //void * result = b_solv->get_custom_data(customAttr); //MVector *vec_res = (MVector*)result; MVector result = b_solv->get_custom_data_vector(b_solv->getdata(rbname), customAttr); MDoubleArray value; value.append(result.x); value.append(result.y); value.append(result.z); setResult(value); } } } else if ( isCreate ) { MString aArgument; argParser->getFlagArgument("-create", 0, aArgument); MStringArray createArgs = parseArguments(aArgument,";"); int size = createArgs.length(); MString inputShape; MString rbname = "dummyRb"; MVector av; MVector vel; MVector pos; MVector rot; for (int i=0; i!=size; ++i) { MStringArray singleArg = parseArguments(createArgs[i],"="); //std::cout<<"singleArg : "<<singleArg<<std::endl; if (singleArg[0] == "name") { rbname = singleArg[1]; } else if (singleArg[0] == "geo") { //geo inputShape = singleArg[1]; //std::cout<<"geo = "<<inputShape<<std::endl; } else if (singleArg[0] == "vel") { //initialvelocity MStringArray velArray = parseArguments(singleArg[1], ","); vel = MVector(velArray[0].asDouble(), velArray[1].asDouble(), velArray[2].asDouble() ); //std::cout<<"velocity = "<<vel<<std::endl; } else if (singleArg[0] == "pos") { //initialposition MStringArray posArray = parseArguments(singleArg[1], ","); pos = MVector(posArray[0].asDouble(), posArray[1].asDouble(), posArray[2].asDouble() ); //std::cout<<"position = "<<pos<<std::endl; } else if (singleArg[0] == "rot") { //initialrotation MStringArray rotArray = parseArguments(singleArg[1], ","); rot = MVector(rotArray[0].asDouble(), rotArray[1].asDouble(), rotArray[2].asDouble() ); //std::cout<<"rotation = "<<rot<<std::endl; } else if (singleArg[0] == "av") { //initialAngularVelocity MStringArray avArray = parseArguments(singleArg[1], ","); av = MVector(avArray[0].asDouble(), avArray[1].asDouble(), avArray[2].asDouble() ); //std::cout<<"initialAngularVelocity = "<<av<<std::endl; } else { std::cout<<"Unrecognized parameter : "<<singleArg[0]<<std::endl; } } // create boing node shared_ptr<bSolverNode> b_solv = bSolverNode::get_bsolver_node(); MObject node = nameToNode(inputShape); float mass = 1.0f; MString tname = "boing"; MStatus stat = b_solv->createNode(node, rbname, tname, pos, vel, rot, av, mass); if (MS::kSuccess == stat) { setResult(rbname); } else { MGlobal::displayError(MString("Something went wrong when trying to create rigidbody : " + rbname + " .")); } } else if ( isDelete ) { MString aArgument; argParser->getFlagArgument("-delete", 0, aArgument); //std::cout<<"delete aArgument "<<aArgument<<std::endl; if (aArgument != "") { shared_ptr<bSolverNode> b_solv = bSolverNode::get_bsolver_node(); b_solv->deletedata(aArgument); MStatus stat = b_solv->delete_key(aArgument, -1); if (stat != MS::kSuccess) { std::cerr<<"error occurred deleting "<<aArgument<<" ."<<std::endl; setResult(1); } } } else if ( isExists ) { MString exArg; argParser->getFlagArgument("-exists", 0, exArg); //std::cout<<"exArg : "<<exArg<<std::endl; if (exArg != "") { shared_ptr<bSolverNode> b_solv = bSolverNode::get_bsolver_node(); bSolverNode::m_custom_data *data = b_solv->getdata(exArg); int result = false; if ( NULL != data ) { //setResult ( data->name ); result = true; } setResult(result); } } return MS::kSuccess; }
void Helper4::addVariableBSDF( const std::string& param_name_as, const std::string& param_type_as, const std::string& param_name_maya ) { std::string param_value; const std::string plugName(param_name_maya); MString fullPlugName((m_nodename+"."+plugName).c_str()); int connected = liquidmaya::ShaderMgr::getSingletonPtr()->convertibleConnection(fullPlugName.asChar()); if( connected == 0 ) { if( isType("color", param_type_as) ) { MDoubleArray val; val.setLength(3); IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", val)); param_value = m_nodename+"_"+plugName; createColor3(m_assembly->colors(), param_value.c_str(), val[0], val[1], val[2]); } else if( isType("scalar", param_type_as) ) { MDoubleArray val; val.setLength(3); IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", val)); //val contains (r,b,g) value, but I only use val[0] for 'scalar' MString strVal0; strVal0.set(val[0]); param_value = strVal0.asChar(); } else { liquidMessage2(messageWarning,"only [color],[scalar] are handled for an unconnected plug in BSDF. " "the plug of %s is unhandled.", fullPlugName.asChar()); param_value = "unhandled"; } } else if(connected == 1)//the color plug is linked in. { if( isType("texture_instance", param_type_as) ) { MStringArray srcPlug; IfMErrorWarn(MGlobal::executeCommand("listConnections -source true -plugs true \""+fullPlugName+"\"", srcPlug)); assert(srcPlug.length()==1); MStringArray src; srcPlug[0].split('.',src); MString srcNode(src[0]); if( is2DTexture(srcNode) || is3DTexture(srcNode) ) { //visitFile(srcNode.asChar()); param_value = getTextureInstanceName(srcNode.asChar()); }else{ liquidMessage2(messageWarning,"type of [%s] is unhandled.(not 2Dtexture and 3Dtexture). [%s]", srcNode.asChar(), fullPlugName.asChar()); param_value = "unhandled"; } } else if( isType("bsdf", param_type_as) ) { //bsdf0 value MString srcBSDFModel; IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", srcBSDFModel)); MStringArray srcPlug; IfMErrorWarn(MGlobal::executeCommand("listConnections -source true -plugs true \""+fullPlugName+"\"", srcPlug)); assert(srcPlug.length()==1); MStringArray src; srcPlug[0].split('.',src); MString srcNode(src[0]); param_value = srcNode.asChar(); } else{ liquidMessage2(messageWarning,"only [texture_instance],[bsdf] are handled for a connected-in plug in BSDF." "the plug of %s is unhandled.", fullPlugName.asChar()); param_value = "unhandled"; } }else{// $(fullPlugName) is connected out // if $(fullPlugName) plug is connected out to "bsdf0"/"bsdf1" of a "bsdf_mix" node, // we also need to create this plug for appleseed // get destination node(s) MStringArray desNodePlug; IfMErrorWarn(MGlobal::executeCommand("listConnections -destination true -plugs true \""+fullPlugName+"\"", desNodePlug)); // check whether $(fullPlugName) is connected to a BSDF node bool isConnectedToA_BSDFMixNode = false; MString desPlug; for(std::size_t i = 0; i< desNodePlug.length(); ++i) { MStringArray des; desNodePlug[i].split('.',des); MString desNode(des[0]); //destination node BSDF type MString desNodeBSDFType; IfMErrorWarn(MGlobal::executeCommand( "getAttr \""+desNode+".rmanShaderType\"", desNodeBSDFType)); if(desNodeBSDFType == "bsdf_mix") { isConnectedToA_BSDFMixNode = true; desPlug = des[1]; } } // if $(fullPlugName) is connected out to "bsdf0"/"bsdf1" of a "bsdf_mix" node // we also need to create this plug for appleseed if( isConnectedToA_BSDFMixNode && (desPlug=="bsdf0" ||desPlug=="bsdf1") ) { if( isType("color", param_type_as) ) { MDoubleArray val; val.setLength(3); IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", val)); param_value = m_nodename+"_"+plugName; createColor3(m_assembly->colors(), param_value.c_str(), val[0], val[1], val[2]); } else if( isType("scalar", param_type_as) ) { MDoubleArray val; val.setLength(3); IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", val)); //val contains (r,b,g) value, but I only use val[0] for 'scalar' MString strVal0; strVal0.set(val[0]); param_value = strVal0.asChar(); } else if( isType("texture_instance", param_type_as) ) { MStringArray srcPlug; IfMErrorWarn(MGlobal::executeCommand("listConnections -source true -plugs true \""+fullPlugName+"\"", srcPlug)); assert(srcPlug.length()==1); MStringArray src; srcPlug[0].split('.',src); MString srcNode(src[0]); if( is2DTexture(srcNode) || is3DTexture(srcNode) ) { //visitFile(srcNode.asChar()); param_value = getTextureInstanceName(srcNode.asChar()); }else{ liquidMessage2(messageWarning,"type of [%s] is unhandled.(not 2Dtexture and 3Dtexture). [%s]", srcNode.asChar(), fullPlugName.asChar()); param_value = "unhandled"; } } else { liquidMessage2(messageWarning,"only [color],[scalar],[texture_instance] are handled for an connected-out plug in BSDF. " "the plug of %s is unhandled.", fullPlugName.asChar()); param_value = "unhandled"; } }//if( nodetype=="bsdf_mix" && (desPlug=="bsdf0" ||desPlug=="bsdf1") ) else { liquidMessage2(messageWarning,"[%s] is connected out. But not connected to brdf node, or not brdf0/brdf1 of a brdf node." " So I don't create the value for this plug.", fullPlugName.asChar()); } } // addVariableBSDF(param_name_as, param_value); }
// Parse the options String void ExportOptions::set ( const MString& optionsString ) { // Reset everything to the default value mBakeTransforms = false; mRelativePaths = true; /** True, if the texture files should be copied to the destination folder. */ mCopyTextures = false; mIsSampling = false; mCurveConstrainSampling = false; mRemoveStaticCurves = true; mExportCameraAsLookat = false; mExportTriangles = false; mExportPolygonMeshes = true; mExportLights = true; mExportCameras = true; mExportMaterialsOnly = false; mExportReferencedMaterials = true; mExportJointsAndSkin = true; mExportAnimations = true; mExportInvisibleNodes = false; mExportDefaultCameras = false; mExportNormals = true; mExportNormalsPerVertex = true; mExportTexCoords = true; mExportVertexColors = true; mExportVertexColorsPerVertex = true; mExportTangents = false; mExportTexTangents = false; mExportXRefs = true; mDereferenceXRefs = true; mCameraXFov = false; mCameraYFov = true; mDoublePrecision = false; mExportCgfxFileReferences = true; // Parse option String if ( optionsString.length() > 0 ) { MStringArray optionList; optionsString.split ( ';', optionList ); uint optionCount = optionList.length(); for ( uint i = 0; i < optionCount; ++i ) { MString& currentOption = optionList[i]; // Process option name and values. MStringArray decomposedOption; currentOption.split ( '=', decomposedOption ); MString& optionName = decomposedOption[0]; // For boolean values, the value is assumed to be true // if omitted. bool value = true; if ( decomposedOption.length() > 1 && decomposedOption[1] != "true" && decomposedOption[1] != "1" ) value = false; // Process options. if ( optionName == "bakeTransforms" ) mBakeTransforms = value; else if ( optionName == "relativePaths" ) mRelativePaths = value; else if ( optionName == "exportTriangles" ) mExportTriangles = value; else if ( optionName == "cgfxFileReferences" ) mExportCgfxFileReferences = value; else if ( optionName == "copyTextures" ) mCopyTextures = value; else if ( optionName == "exportPolygonMeshes" ) mExportPolygonMeshes = value; else if ( optionName == "exportLights" ) mExportLights = value; else if ( optionName == "exportCameras" ) mExportCameras = value; else if ( optionName == "exportJointsAndSkin" ) mExportJointsAndSkin = value; else if ( optionName == "exportMaterialsOnly" ) mExportMaterialsOnly = value; else if ( optionName == "exportReferencedMaterials" ) mExportReferencedMaterials = value; else if ( optionName == "exportAnimations" ) mExportAnimations = value; else if ( optionName == "exportInvisibleNodes" ) mExportInvisibleNodes = value; else if ( optionName == "exportDefaultCameras" ) mExportDefaultCameras = value; else if ( optionName == "exportNormals" ) mExportNormals = value; else if ( optionName == "exportNormalsPerVertex" ) mExportNormalsPerVertex = value; else if ( optionName == "exportTexCoords" ) mExportTexCoords = value; else if ( optionName == "exportVertexColors" ) mExportVertexColors = value; else if ( optionName == "exportVertexColorsPerVertex" ) mExportVertexColorsPerVertex = value; else if ( optionName == "exportTangents" ) mExportTangents = value; else if ( optionName == "exportTexTangents" ) mExportTexTangents = value; else if ( optionName == "exportCameraAsLookat" ) mExportCameraAsLookat = value; else if ( optionName == "cameraXFov" ) mCameraXFov = value; else if ( optionName == "cameraYFov" ) mCameraYFov = value; else if ( optionName == "doublePrecision" ) mDoublePrecision = value; else if ( optionName == "isSampling" ) mIsSampling = value; else if ( optionName == "curveConstrainSampling" ) mCurveConstrainSampling = value; else if ( optionName == "removeStaticCurves" ) mRemoveStaticCurves = value; else if ( optionName == "exportXRefs" ) mExportXRefs = value; else if ( optionName == "dereferenceXRefs" ) mDereferenceXRefs = value; } } if ( !mIsSampling ) { AnimationHelper::generateSamplingFunction(); } }
// Load material data MStatus Material::load(MFnDependencyNode* pShader,MStringArray& uvsets,ParamList& params) { MStatus stat; clear(); //read material name, adding the requested prefix MString tmpStr = params.matPrefix; if (tmpStr != "") tmpStr += "/"; tmpStr += pShader->name(); MStringArray tmpStrArray; tmpStr.split(':',tmpStrArray); m_name = ""; for (int i=0; i<tmpStrArray.length(); i++) { m_name += tmpStrArray[i]; if (i < tmpStrArray.length()-1) m_name += "_"; } //check if we want to export with lighting off option m_lightingOff = params.lightingOff; // GET MATERIAL DATA // Check material type if (pShader->object().hasFn(MFn::kPhong)) { stat = loadPhong(pShader); } else if (pShader->object().hasFn(MFn::kBlinn)) { stat = loadBlinn(pShader); } else if (pShader->object().hasFn(MFn::kLambert)) { stat = loadLambert(pShader); } else if (pShader->object().hasFn(MFn::kPluginHwShaderNode)) { stat = loadCgFxShader(pShader); } else { stat = loadSurfaceShader(pShader); } // Get textures data MPlugArray colorSrcPlugs; MPlugArray texSrcPlugs; MPlugArray placetexSrcPlugs; if (m_isTextured) { // Translate multiple textures if material is multitextured if (m_isMultiTextured) { // Get layered texture node MFnDependencyNode* pLayeredTexNode = NULL; if (m_type == MT_SURFACE_SHADER) pShader->findPlug("outColor").connectedTo(colorSrcPlugs,true,false); else pShader->findPlug("color").connectedTo(colorSrcPlugs,true,false); for (int i=0; i<colorSrcPlugs.length(); i++) { if (colorSrcPlugs[i].node().hasFn(MFn::kLayeredTexture)) { pLayeredTexNode = new MFnDependencyNode(colorSrcPlugs[i].node()); continue; } } // Get inputs to layered texture MPlug inputsPlug = pLayeredTexNode->findPlug("inputs"); // Scan inputs and export textures for (int i=inputsPlug.numElements()-1; i>=0; i--) { MFnDependencyNode* pTextureNode = NULL; // Search for a connected texture inputsPlug[i].child(0).connectedTo(colorSrcPlugs,true,false); for (int j=0; j<colorSrcPlugs.length(); j++) { if (colorSrcPlugs[j].node().hasFn(MFn::kFileTexture)) { pTextureNode = new MFnDependencyNode(colorSrcPlugs[j].node()); continue; } } // Translate the texture if it was found if (pTextureNode) { // Get blend mode TexOpType opType; short bm; inputsPlug[i].child(2).getValue(bm); switch(bm) { case 0: opType = TOT_REPLACE; break; case 1: opType = TOT_ALPHABLEND; break; case 4: opType = TOT_ADD; break; case 6: opType = TOT_MODULATE; break; default: opType = TOT_MODULATE; } stat = loadTexture(pTextureNode,opType,uvsets,params); delete pTextureNode; if (MS::kSuccess != stat) { std::cout << "Error loading layered texture\n"; std::cout.flush(); delete pLayeredTexNode; return MS::kFailure; } } } if (pLayeredTexNode) delete pLayeredTexNode; } // Else translate the single texture else { // Get texture node MFnDependencyNode* pTextureNode = NULL; if (m_type == MT_SURFACE_SHADER) pShader->findPlug("outColor").connectedTo(colorSrcPlugs,true,false); else pShader->findPlug("color").connectedTo(colorSrcPlugs,true,false); for (int i=0; i<colorSrcPlugs.length(); i++) { if (colorSrcPlugs[i].node().hasFn(MFn::kFileTexture)) { pTextureNode = new MFnDependencyNode(colorSrcPlugs[i].node()); continue; } } if (pTextureNode) { TexOpType opType = TOT_MODULATE; stat = loadTexture(pTextureNode,opType,uvsets,params); delete pTextureNode; if (MS::kSuccess != stat) { std::cout << "Error loading texture\n"; std::cout.flush(); return MS::kFailure; } } } } return MS::kSuccess; }
MStatus Submesh::load(std::vector<face>& faces, std::vector<vertexInfo>& vertInfo, MFloatPointArray& points, MFloatVectorArray& normals, MStringArray& texcoordsets,ParamList& params,bool opposite) { //save uvsets info for (int i=m_uvsets.size(); i<texcoordsets.length(); i++) { uvset uv; uv.size = 2; m_uvsets.push_back(uv); } //iterate over faces array, to retrieve vertices info for (int i=0; i<faces.size(); i++) { face newFace; // if we are using shared geometry, indexes refer to the vertex buffer of the whole mesh if (params.useSharedGeom) { if(opposite) { // reverse order of face vertices for correct culling newFace.v[0] = faces[i].v[2]; newFace.v[1] = faces[i].v[1]; newFace.v[2] = faces[i].v[0]; } else { newFace.v[0] = faces[i].v[0]; newFace.v[1] = faces[i].v[1]; newFace.v[2] = faces[i].v[2]; } } // otherwise we create a vertex buffer for this submesh else { // faces are triangles, so retrieve index of the three vertices for (int j=0; j<3; j++) { vertex v; vertexInfo vInfo = vertInfo[faces[i].v[j]]; // save vertex coordinates v.x = points[vInfo.pointIdx].x; v.y = points[vInfo.pointIdx].y; v.z = points[vInfo.pointIdx].z; // save vertex normal if (opposite) { v.n.x = -normals[vInfo.normalIdx].x; v.n.y = -normals[vInfo.normalIdx].y; v.n.z = -normals[vInfo.normalIdx].z; } else { v.n.x = normals[vInfo.normalIdx].x; v.n.y = normals[vInfo.normalIdx].y; v.n.z = normals[vInfo.normalIdx].z; } v.n.normalize(); // save vertex color v.r = vInfo.r; v.g = vInfo.g; v.b = vInfo.b; v.a = vInfo.a; // save vertex bone assignements for (int k=0; k<vInfo.vba.size(); k++) { vba newVba; newVba.jointIdx = vInfo.jointIds[k]; newVba.weight = vInfo.vba[k]; v.vbas.push_back(newVba); } // save texture coordinates for (int k=0; k<vInfo.u.size(); k++) { texcoords newTexCoords; newTexCoords.u = vInfo.u[k]; newTexCoords.v = vInfo.v[k]; newTexCoords.w = 0; v.texcoords.push_back(newTexCoords); } // add newly created vertex to vertex list m_vertices.push_back(v); if (opposite) // reverse order of face vertices to get correct culling newFace.v[2-j] = m_vertices.size() - 1; else newFace.v[j] = m_vertices.size() - 1; } } m_faces.push_back(newFace); } // set use32bitIndexes flag if (params.useSharedGeom || (m_vertices.size() > 65535) || (m_faces.size() > 65535)) m_use32bitIndexes = true; else m_use32bitIndexes = false; return MS::kSuccess; }
MStatus MayaToCorona::doIt( const MArgList& args) { MStatus stat = MStatus::kSuccess; std::unique_ptr<MayaTo::CmdArgs> cmdArgs(new MayaTo::CmdArgs); MArgDatabase argData(syntax(), args); if (argData.isFlagSet("-version", &stat)) { MStringArray res; for (auto v : getFullVersionString()) res.append(v.c_str()); setResult(res); return MS::kSuccess; } MayaTo::MayaToWorld::WorldRenderState rstate = MayaTo::getWorldPtr()->renderState; if (argData.isFlagSet("-state", &stat)) { if (rstate == MayaTo::MayaToWorld::RSTATETRANSLATING) setResult("rstatetranslating"); if (rstate == MayaTo::MayaToWorld::RSTATERENDERING) setResult("rstaterendering"); if (rstate == MayaTo::MayaToWorld::RSTATEDONE) setResult("rstatedone"); if (rstate == MayaTo::MayaToWorld::RSTATENONE) setResult("rstatenone"); if (rstate == MayaTo::MayaToWorld::RSTATESTOPPED) setResult("rstatestopped"); return MS::kSuccess; } MGlobal::displayInfo("Executing mayaToCorona..."); setLogLevel(); if (argData.isFlagSet("-canDoIPR", &stat)) { if(MayaTo::getWorldPtr()->canDoIPR()) setResult("yes"); else setResult("no"); return MS::kSuccess; } if ( argData.isFlagSet("-stopIpr", &stat)) { Logging::debug(MString("-stopIpr")); EventQueue::Event e; e.type = EventQueue::Event::IPRSTOP; theRenderEventQueue()->push(e); return MS::kSuccess; } if ( argData.isFlagSet("-pauseIpr", &stat)) { Logging::debug(MString("-pauseIpr")); Logging::debug(MString("-stopIpr")); EventQueue::Event e; e.type = EventQueue::Event::IPRPAUSE; theRenderEventQueue()->push(e); return MS::kSuccess; } if (argData.isFlagSet("-usrDataString", &stat)) { Logging::debug(MString("-usrDataString")); argData.getFlagArgument("-usrDataString", 0, cmdArgs->userDataString); } if (argData.isFlagSet("-usrDataInt", &stat)) { Logging::debug(MString("-usrDataInt")); argData.getFlagArgument("-usrDataInt", 0, cmdArgs->userDataInt); } if (argData.isFlagSet("-usrDataFloat", &stat)) { Logging::debug(MString("-usrDataFloat")); argData.getFlagArgument("-usrDataFloat", 0, cmdArgs->userDataFloat); } if (argData.isFlagSet("-usrEvent", &stat)) { Logging::debug(MString("-usrEvent")); argData.getFlagArgument("-usrEvent", 0, cmdArgs->userEvent); EventQueue::Event e; e.cmdArgsData = std::move(cmdArgs); e.type = EventQueue::Event::USER; theRenderEventQueue()->push(e); return MS::kSuccess; } // I have to request useRenderRegion here because as soon the command is finished, what happens immediatly after the command is // put into the queue, the value is set back to false. MObject drg = objectFromName("defaultRenderGlobals"); MFnDependencyNode drgfn(drg); cmdArgs->useRenderRegion = drgfn.findPlug("useRenderRegion").asBool(); cmdArgs->renderType = MayaTo::MayaToWorld::WorldRenderType::UIRENDER; if (MGlobal::mayaState() == MGlobal::kBatch) cmdArgs->renderType = MayaTo::MayaToWorld::WorldRenderType::BATCHRENDER; if ( argData.isFlagSet("-startIpr", &stat)) { Logging::debug(MString("-startIpr")); cmdArgs->renderType = MayaTo::MayaToWorld::WorldRenderType::IPRRENDER; } if (argData.isFlagSet("-width", &stat)) { argData.getFlagArgument("-width", 0, cmdArgs->width); Logging::debug(MString("width: ") + cmdArgs->width); } if (argData.isFlagSet("-height", &stat)) { argData.getFlagArgument("-height", 0, cmdArgs->height); Logging::debug(MString("height: ") + cmdArgs->height); } if ( argData.isFlagSet("-camera", &stat)) { MDagPath camera; MSelectionList selectionList; argData.getFlagArgument("-camera", 0, selectionList); stat = selectionList.getDagPath(0, camera); camera.extendToShape(); Logging::debug(MString("camera: ") + camera.fullPathName()); cmdArgs->cameraDagPath = camera; } EventQueue::Event e; e.cmdArgsData = std::move(cmdArgs); e.type = EventQueue::Event::INITRENDER; theRenderEventQueue()->push(e); // if (MGlobal::mayaState() == MGlobal::kBatch) { RenderQueueWorker::startRenderQueueWorker(); } return MStatus::kSuccess; }
MStatus lrutils::loadGeoReference(MString geoFilePath, MString geoName, MString & name, MObject & geoObj) { MStatus status = MS::kFailure; MString projPath = MGlobal::executeCommandStringResult(MString("workspace -q -rd;"),false,false); MString relativePath = geoFilePath.substring(2,geoFilePath.numChars() - 1); //assemble the full file path of the geometry file MString fullGeoPath = projPath + relativePath; //load the geometry file as a reference into the current scene //check to see if the referenced file has already been used MStringArray refNodeList; status = MFileIO::getReferences(refNodeList, true); MyCheckStatus(status, "getReferences failed"); int numReferences = 0; for(unsigned int i = 0; i < refNodeList.length(); i++) { MString tmp = refNodeList[i]; string tmp1 = tmp.asChar(); string tmp2 = fullGeoPath.asChar(); if(std::string::npos != tmp1.find(tmp2)) numReferences++; } string str (geoFilePath.asChar()); string key ("/"); size_t found = str.rfind(key); string fileName = str.substr(found+1,str.length()-found-4); string fileNamespace; if(numReferences > 0) { stringstream tmp; tmp << fileName << (numReferences+1); fileNamespace = tmp.str(); } else { fileNamespace = fileName; } { stringstream tmp; tmp << "file -r -type \"mayaAscii\" -gl -loadReferenceDepth \"all\" -namespace \"" << fileNamespace.c_str() << "\" -options \"v=0\" \"" << fullGeoPath.asChar() << "\";"; MString referenceCommand = MString(tmp.str().c_str()); MGlobal::executeCommand(referenceCommand); } //get the referenced geometry transform node and add the metaParent //attribute to it MSelectionList selection; if(numReferences > 0) { name += (boost::lexical_cast<string>(numReferences+1)).c_str(); } stringstream geoRefName; geoRefName << fileNamespace << ":" << geoName; MString mGeoRefName = MString(geoRefName.str().c_str()); status = selection.add( mGeoRefName, true ); MyCheckStatusReturn(status, "add geoRefName "+mGeoRefName+" to selection failed."); if(selection.length() ) selection.getDependNode(0, geoObj); MFnTransform transformFn; transformFn.setObject(geoObj); MFnMessageAttribute mAttr; MObject transformAttr = mAttr.create("metaParent", "metaParent"); transformFn.addAttribute(transformAttr); if( !geoObj.isNull() ) status = MS::kSuccess; return status; }
MStatus skinClusterWeights::redoIt() { MStatus status; unsigned int ptr = 0; MSelectionList selList; int geomLen = geometryArray.length(); fDagPathArray.setLength(geomLen); fComponentArray.setLength(geomLen); fInfluenceIndexArrayPtrArray = new MIntArray[geomLen]; fWeightsPtrArray = new MDoubleArray[geomLen]; for (int i = 0; i < geomLen; i++) { MDagPath dagPath; MObject component; selList.clear(); selList.add(geometryArray[i]); MStatus status = selList.getDagPath(0, dagPath, component); if (status != MS::kSuccess) { continue; } if (component.isNull()) dagPath.extendToShape(); MObject skinCluster = findSkinCluster(dagPath); if (!isSkinClusterIncluded(skinCluster)) { continue; } MFnSkinCluster skinClusterFn(skinCluster, &status); if (status != MS::kSuccess) { continue; } MIntArray influenceIndexArray; populateInfluenceIndexArray(skinClusterFn, influenceIndexArray); unsigned numInf = influenceIndexArray.length(); if (numInf == 0) continue; unsigned numCV = 0; if (dagPath.node().hasFn(MFn::kMesh)) { MItMeshVertex polyIter(dagPath, component, &status); if (status == MS::kSuccess) { numCV = polyIter.count(); } } else if (dagPath.node().hasFn(MFn::kNurbsSurface)) { MItSurfaceCV nurbsIter(dagPath, component, true, &status); if (status == MS::kSuccess) { while (!nurbsIter.isDone()) { numCV++; nurbsIter.next(); } } } else if (dagPath.node().hasFn(MFn::kNurbsCurve)) { MItCurveCV curveIter(dagPath, component, &status); if (status == MS::kSuccess) { while (!curveIter.isDone()) { numCV++; curveIter.next(); } } } unsigned numEntry = numCV * numInf; if (numEntry > 0) { MDoubleArray weights(numEntry); unsigned int numWeights = weightArray.length(); if (assignAllToSingle) { if (numInf <= numWeights) { for (unsigned j = 0; j < numEntry; j++) { weights[j] = weightArray[j % numInf]; } } else { MGlobal::displayError("Not enough weights specified\n"); return MS::kFailure; } } else { for (unsigned j = 0; j < numEntry; j++, ptr++) { if (ptr < numWeights) { weights[j] = weightArray[ptr]; } else { MGlobal::displayError("Not enough weights specified\n"); return MS::kFailure; } } } // support for undo fDagPathArray[i] = dagPath; fComponentArray[i] = component; fInfluenceIndexArrayPtrArray[i] = influenceIndexArray; MDoubleArray oldWeights; skinClusterFn.getWeights(dagPath, component, influenceIndexArray, oldWeights); fWeightsPtrArray[i] = oldWeights; skinClusterFn.setWeights(dagPath, component, influenceIndexArray, weights); } } 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].asUTF8(); } 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 == "-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; } } // 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; } }
// // Write out the "file" commands which specify the reference files used by // the scene. // void maTranslator::writeReferences(fstream& f) { MStringArray files; MFileIO::getReferences(files); unsigned numRefs = files.length(); unsigned i; for (i = 0; i < numRefs; i++) { MString refCmd = "file -r"; MString fileName = files[i]; MString nsName = ""; // // For simplicity, we assume that namespaces are always used when // referencing. // MString tempCmd = "file -q -ns \""; tempCmd += fileName + "\""; if (MGlobal::executeCommand(tempCmd, nsName)) { refCmd += " -ns \""; refCmd += nsName + "\""; } else MGlobal::displayWarning("Could not get namespace name."); // // Is this a deferred reference? // tempCmd = "file -q -dr \""; tempCmd += fileName + "\""; int isDeferred; if (MGlobal::executeCommand(tempCmd, isDeferred)) { if (isDeferred) refCmd += " -dr 1"; } else MGlobal::displayWarning("Could not get deferred reference info."); // // Get the file's reference node, if it has one. // tempCmd = "file -q -rfn \""; tempCmd += fileName + "\""; MString refNode; if (MGlobal::executeCommand(tempCmd, refNode)) { if (refNode.length() > 0) { refCmd += " -rfn \""; refCmd += refNode + "\""; } } else MGlobal::displayInfo("Could not query reference node name."); // // Write out the reference command. // f << refCmd.asChar() << " \"" << fileName.asChar() << "\";" << endl; } }
/** Create a RIB compatible subdivision surface representation using a Maya polygon mesh. */ liqRibSubdivisionData::liqRibSubdivisionData( MObject mesh ) : numFaces( 0 ), numPoints ( 0 ), nverts(), verts(), vertexParam( NULL ), interpolateBoundary( 0 ), uvDetail( rFaceVarying ), trueFacevarying( false ) { CM_TRACE_FUNC("liqRibSubdivisionData::liqRibSubdivisionData("<<MFnDagNode(mesh).fullPathName()<<")"); LIQDEBUGPRINTF( "-> creating subdivision surface\n" ); MFnMesh fnMesh( mesh ); name = fnMesh.name(); longName = fnMesh.fullPathName(); checkExtraTags( mesh ); numPoints = fnMesh.numVertices(); // UV sets ----------------- // const unsigned numSTs = fnMesh.numUVs(); const unsigned numUVSets = fnMesh.numUVSets(); MString currentUVSetName; MStringArray extraUVSetNames; fnMesh.getCurrentUVSetName( currentUVSetName ); MStringArray UVSetNames; fnMesh.getUVSetNames( UVSetNames ); for ( unsigned i( 0 ); i < numUVSets; i++ ) if( UVSetNames[i] != currentUVSetName ) extraUVSetNames.append( UVSetNames[i] ); numFaces = fnMesh.numPolygons(); const unsigned numFaceVertices( fnMesh.numFaceVertices() ); unsigned face( 0 ); unsigned faceVertex( 0 ); unsigned count; unsigned vertex; float S; float T; MPoint point; liqTokenPointer pointsPointerPair; liqTokenPointer pFaceVertexSPointer; liqTokenPointer pFaceVertexTPointer; // Allocate memory and tokens nverts = shared_array< RtInt >( new RtInt[ numFaces ] ); verts = shared_array< RtInt >( new RtInt[ numFaceVertices ] ); pointsPointerPair.set( "P", rPoint, numPoints ); pointsPointerPair.setDetailType( rVertex ); std::vector<liqTokenPointer> UVSetsArray; UVSetsArray.reserve( 1 + extraUVSetNames.length() ); if( numSTs > 0 ) { liqTokenPointer pFaceVertexPointerPair; pFaceVertexPointerPair.set( "st", rFloat, numFaceVertices, 2 ); pFaceVertexPointerPair.setDetailType( uvDetail ); UVSetsArray.push_back( pFaceVertexPointerPair ); for ( unsigned j( 0 ); j<extraUVSetNames.length(); j++) { liqTokenPointer pFaceVertexPointerPair; pFaceVertexPointerPair.set( extraUVSetNames[j].asChar(), rFloat, numFaceVertices, 2 ); pFaceVertexPointerPair.setDetailType( uvDetail ); UVSetsArray.push_back( pFaceVertexPointerPair ); } if( liqglo.liqglo_outputMeshUVs ) { // Match MTOR, which also outputs face-varying STs as well for some reason - Paul // not anymore - Philippe pFaceVertexSPointer.set( "u", rFloat, numFaceVertices ); pFaceVertexSPointer.setDetailType( uvDetail ); pFaceVertexTPointer.set( "v", rFloat, numFaceVertices ); pFaceVertexTPointer.setDetailType( uvDetail ); } } vertexParam = pointsPointerPair.getTokenFloatArray(); // Read the mesh from Maya for ( MItMeshPolygon polyIt ( mesh ); polyIt.isDone() == false; polyIt.next() ) { count = polyIt.polygonVertexCount(); nverts[face] = count; unsigned i = count; while( i ) { --i; vertex = polyIt.vertexIndex( i ); verts[faceVertex] = vertex; point = polyIt.point( i, MSpace::kObject ); pointsPointerPair.setTokenFloat( vertex, point.x, point.y, point.z ); if( UVSetsArray.size() ) { fnMesh.getPolygonUV( face, i, S, T ); UVSetsArray[0].setTokenFloat( faceVertex, 0, S ); UVSetsArray[0].setTokenFloat( faceVertex, 1, 1 - T ); for ( unsigned j( 1 ); j<=extraUVSetNames.length(); j++ ) { fnMesh.getPolygonUV( face, i, S, T, &extraUVSetNames[j] ); UVSetsArray[j].setTokenFloat( faceVertex, 0, S ); UVSetsArray[j].setTokenFloat( faceVertex, 1, 1 - T ); } if( liqglo.liqglo_outputMeshUVs ) { // Match MTOR, which always outputs face-varying STs as well for some reason - Paul pFaceVertexSPointer.setTokenFloat( faceVertex, S ); pFaceVertexTPointer.setTokenFloat( faceVertex, 1 - T ); } } ++faceVertex; } ++face; } // Add tokens to array and clean up after tokenPointerArray.push_back( pointsPointerPair ); if( UVSetsArray.size() ) tokenPointerArray.insert( tokenPointerArray.end(), UVSetsArray.begin(), UVSetsArray.end() ); if( liqglo.liqglo_outputMeshUVs ) { assert( !pFaceVertexSPointer ); tokenPointerArray.push_back( pFaceVertexSPointer ); assert( !pFaceVertexTPointer ); tokenPointerArray.push_back( pFaceVertexTPointer ); } addAdditionalSurfaceParameters( mesh ); }
MStatus animExport::writer( const MFileObject& file, const MString& options, FileAccessMode mode) { MStatus status = MS::kFailure; #ifdef MAYA_EVAL_VERSION status = MS::kFailure; return status; #endif MString fileName = file.fullName(); #if defined (OSMac_) char fname[MAXPATHLEN]; strcpy (fname, fileName.asChar()); ofstream animFile(fname); #else ofstream animFile(fileName.asChar()); #endif // Defaults. // MString copyFlags("copyKey -cb api -fea 1 "); int precision = kDefaultPrecision; bool nodeNames = true; bool verboseUnits = false; // Parse the options. The options syntax is in the form of // "flag=val;flag1=val;flag2=val" // MString exportFlags; if (options.length() > 0) { const MString flagPrecision("precision"); const MString flagNodeNames("nodeNames"); const MString flagVerboseUnits("verboseUnits"); const MString flagCopyKeyCmd("copyKeyCmd"); // Start parsing. // MStringArray optionList; MStringArray theOption; options.split(';', optionList); unsigned nOptions = optionList.length(); for (unsigned i = 0; i < nOptions; i++) { theOption.clear(); optionList[i].split('=', theOption); if (theOption.length() < 1) { continue; } if (theOption[0] == flagPrecision && theOption.length() > 1) { if (theOption[1].isInt()) { precision = theOption[1].asInt(); } } else if ( theOption[0] == flagNodeNames && theOption.length() > 1) { if (theOption[1].isInt()) { nodeNames = (theOption[1].asInt()) ? true : false; } } else if (theOption[0] == flagVerboseUnits && theOption.length() > 1) { if (theOption[1].isInt()) { verboseUnits = (theOption[1].asInt()) ? true : false; } } else if ( theOption[0] == flagCopyKeyCmd && theOption.length() > 1) { // Replace any '>' characters with '"'. This is needed // since the file translator option boxes do not handle // escaped quotation marks. // const char *optStr = theOption[1].asChar(); size_t nChars = strlen(optStr); char *copyStr = new char[nChars+1]; copyStr = strcpy(copyStr, optStr); for (size_t j = 0; j < nChars; j++) { if (copyStr[j] == '>') { copyStr[j] = '"'; } } copyFlags += copyStr; delete copyStr; } } } // Set the precision of the ofstream. // animFile.precision(precision); status = exportSelected(animFile, copyFlags, nodeNames, verboseUnits); animFile.flush(); animFile.close(); return status; }
static MStatus convertToMayaMeshData(OpenSubdiv::Far::TopologyRefiner const & refiner, std::vector<Vertex> const & vertexBuffer, MFnMesh const & inMeshFn, MObject newMeshDataObj) { MStatus status; typedef OpenSubdiv::Far::ConstIndexArray IndexArray; int maxlevel = refiner.GetMaxLevel(); OpenSubdiv::Far::TopologyLevel const & refLastLevel = refiner.GetLevel(maxlevel); int nfaces = refLastLevel.GetNumFaces(); // Init Maya Data // -- Face Counts MIntArray faceCounts(nfaces); for (int face=0; face < nfaces; ++face) { faceCounts[face] = 4; } // -- Face Connects MIntArray faceConnects(nfaces*4); for (int face=0, idx=0; face < nfaces; ++face) { IndexArray fverts = refLastLevel.GetFaceVertices(face); for (int vert=0; vert < fverts.size(); ++vert) { faceConnects[idx++] = fverts[vert]; } } // -- Points MFloatPointArray points(refLastLevel.GetNumVertices()); Vertex const * v = &vertexBuffer.at(0); for (int level=1; level<=maxlevel; ++level) { int nverts = refiner.GetLevel(level).GetNumVertices(); if (level==maxlevel) { for (int vert=0; vert < nverts; ++vert, ++v) { points.set(vert, v->position[0], v->position[1], v->position[2]); } } else { v += nverts; } } // Create New Mesh from MFnMesh MFnMesh newMeshFn; MObject newMeshObj = newMeshFn.create(points.length(), faceCounts.length(), points, faceCounts, faceConnects, newMeshDataObj, &status); MCHECKERR(status, "Cannot create new mesh"); int fvarTotalWidth = 0; if (fvarTotalWidth > 0) { // Get face-varying set names and other info from the inMesh MStringArray uvSetNames; MStringArray colorSetNames; std::vector<int> colorSetChannels; std::vector<MFnMesh::MColorRepresentation> colorSetReps; int totalColorSetChannels = 0; status = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames, colorSetChannels, colorSetReps, totalColorSetChannels); #if defined(DEBUG) or defined(_DEBUG) int numUVSets = uvSetNames.length(); int expectedFvarTotalWidth = numUVSets*2 + totalColorSetChannels; assert(fvarTotalWidth == expectedFvarTotalWidth); #endif // XXXX fvar stuff here } return MS::kSuccess; }