static void cook(FnKat::GeolibCookInterface &interface) { boost::shared_lock<boost::upgrade_mutex> readerLock(UsdKatanaGetStageLock()); UsdPrim prim; PxrUsdKatanaUsdInArgsRefPtr usdInArgs; PxrUsdKatanaUsdInPrivateData* privateData = static_cast<PxrUsdKatanaUsdInPrivateData*>(interface.getPrivateData()); FnKat::GroupAttribute opArgs = interface.getOpArg(); if (privateData) { usdInArgs = privateData->GetUsdInArgs(); } else { FnKat::GroupAttribute additionalOpArgs; usdInArgs = InitUsdInArgs(interface, additionalOpArgs); opArgs = FnKat::GroupBuilder() .update(opArgs) .deepUpdate(additionalOpArgs) .build(); } if (not usdInArgs) { ERROR("Could not initialize PxrUsdIn usdInArgs."); return; } if (interface.atRoot()) { interface.stopChildTraversal(); prim = usdInArgs->GetRootPrim(); // XXX This info currently gets used to determine whether // to correctively rotate cameras. The camera's zUp needs to be // recorded until we have no more USD z-Up assets and the katana // assets have no more prerotate camera nodes. interface.setAttr("info.usd.stageIsZup", FnKat::IntAttribute(UsdUtilsGetCamerasAreZup(usdInArgs->GetStage()))); // Construct the global camera list at the USD scene root. // FnKat::StringBuilder cameraListBuilder; SdfPathVector cameraPaths = PxrUsdKatanaUtils::FindCameraPaths(prim.GetStage()); TF_FOR_ALL(cameraPathIt, cameraPaths) { const std::string path = (*cameraPathIt).GetString(); // only add cameras to the camera list that are beneath the isolate prim path if (path.find(usdInArgs->GetIsolatePath()) != std::string::npos) { cameraListBuilder.push_back( TfNormPath(usdInArgs->GetRootLocationPath()+"/"+ path.substr(usdInArgs->GetIsolatePath().size()))); } } FnKat::StringAttribute cameraListAttr = cameraListBuilder.build(); if (cameraListAttr.getNumberOfValues() > 0) { interface.setAttr("cameraList", cameraListAttr); } interface.setAttr("info.usdOpArgs", opArgs); FnKat::GroupAttribute masterMapping = opArgs.getChildByName("masterMapping"); if (masterMapping.isValid() && masterMapping.getNumberOfChildren()) { FnGeolibServices::StaticSceneCreateOpArgsBuilder sscb(false); for (size_t i = 0, e = masterMapping.getNumberOfChildren(); i != e; ++i) { std::string masterName = FnKat::DelimiterDecode( masterMapping.getChildName(i)); std::string katanaPath = FnKat::StringAttribute( masterMapping.getChildByIndex(i) ).getValue("", false); if (katanaPath.empty()) { continue; } sscb.createEmptyLocation(katanaPath, "instance source"); sscb.setAttrAtLocation(katanaPath, "tabs.scenegraph.stopExpand", FnKat::IntAttribute(1)); sscb.setAttrAtLocation(katanaPath, "childPrimPath", FnKat::StringAttribute(masterName)); } interface.createChild( "Masters", "PxrUsdIn.MasterIntermediate", FnKat::GroupBuilder() .update(opArgs) .set("staticScene", sscb.build()) .build(), FnKat::GeolibCookInterface::ResetRootFalse, new PxrUsdKatanaUsdInPrivateData( usdInArgs->GetRootPrim(), usdInArgs, privateData), PxrUsdKatanaUsdInPrivateData::Delete); } }
void InstancerOp::cook(Foundry::Katana::GeolibCookInterface& interface) { if (interface.atRoot()) { interface.stopChildTraversal(); } // find c argument FnAttribute::GroupAttribute cGroupAttr = interface.getOpArg("c"); if (cGroupAttr.isValid()) { if (cGroupAttr.getNumberOfChildren() != 1) { Foundry::Katana::ReportError(interface, "Invalid attributes."); interface.stopChildTraversal(); return; } std::string childName = FnAttribute::DelimiterDecode(cGroupAttr.getChildName(0)); FnAttribute::GroupAttribute childArgs = cGroupAttr.getChildByIndex(0); interface.createChild(childName, "", childArgs); return; } FnAttribute::GroupAttribute aGroupAttr = interface.getOpArg("a"); if (aGroupAttr.isValid()) { // TODO: cache this with Foundry::Katana::GeolibPrivateData... std::string sourceLocation; FnAttribute::StringAttribute sourceLocationAttr = aGroupAttr.getChildByName("sourceLocation"); if (sourceLocationAttr.isValid()) { sourceLocation = sourceLocationAttr.getValue("", false); } FnAttribute::IntAttribute instanceTypeAttr = aGroupAttr.getChildByName("instanceType"); bool threeD = false; FnAttribute::IntAttribute threeDAttr = aGroupAttr.getChildByName("threeD"); if (threeDAttr.isValid()) { threeD = threeDAttr.getValue(0, false) == 1; } bool floatFormat = false; FnAttribute::IntAttribute floatFormatMatrixAttr = aGroupAttr.getChildByName("floatFormatMatrix"); if (floatFormatMatrixAttr.isValid()) { floatFormat = floatFormatMatrixAttr.getValue(0, false) == 1; } FnAttribute::IntAttribute numInstancesAttr = aGroupAttr.getChildByName("numInstances"); FnAttribute::IntAttribute groupInstancesAttr = aGroupAttr.getChildByName("groupInstances"); unsigned int numInstances = (unsigned int)numInstancesAttr.getValue(0, false); if (numInstances == 0) { return; } bool instanceArray = true; FnAttribute::IntAttribute instanceArrayAttr = aGroupAttr.getChildByName("instanceArray"); if (instanceArrayAttr.isValid()) { instanceArray = instanceArrayAttr.getValue(1, false); } bool createInstanceIndexAttribute = false; FnAttribute::IntAttribute createInstanceIndexAttributeAttr = aGroupAttr.getChildByName("createInstanceIndexAttribute"); if (createInstanceIndexAttributeAttr.isValid()) { createInstanceIndexAttribute = createInstanceIndexAttributeAttr.getValue(1, false); } Vec3 areaSpread(20.0f, 20.0f, 20.0f); FnAttribute::FloatAttribute areaSpreadAttr = aGroupAttr.getChildByName("areaSpread"); if (areaSpreadAttr.isValid()) { FnKat::FloatConstVector data = areaSpreadAttr.getNearestSample(0); areaSpread.x = data[0]; areaSpread.y = data[1]; areaSpread.z = data[2]; } // we're dangerously assuming that this will be run first... if (!threeD) { create2DGrid(numInstances, areaSpread, aTranslates); } else { create3DGrid(numInstances, areaSpread, aTranslates); } if (!instanceArray) { bool groupInstances = groupInstancesAttr.getValue(0, false); if (groupInstances) { FnAttribute::IntAttribute groupSizeAttr = aGroupAttr.getChildByName("groupSize"); int groupSize = groupSizeAttr.getValue(0, false); int groupsNeeded = numInstances / groupSize; groupsNeeded += (int)(numInstances % groupSize > 0); int remainingInstances = numInstances; int indexStartCount = 0; for (int i = 0; i < groupsNeeded; i++) { std::ostringstream ss; ss << "group_" << i; int thisGroupSize = (remainingInstances >= groupSize) ? groupSize : remainingInstances; FnAttribute::GroupBuilder childArgsBuilder; childArgsBuilder.set("group.index", FnAttribute::IntAttribute(i)); childArgsBuilder.set("group.indexStart", FnAttribute::IntAttribute(indexStartCount)); childArgsBuilder.set("group.size", FnAttribute::IntAttribute(thisGroupSize)); childArgsBuilder.set("group.sourceLoc", FnAttribute::StringAttribute(sourceLocation)); interface.createChild(ss.str(), "", childArgsBuilder.build()); remainingInstances -= thisGroupSize; indexStartCount += thisGroupSize; } } else { for (int i = 0; i < numInstances; i++) { std::ostringstream ss; ss << "instance_" << i; FnAttribute::GroupBuilder childArgsBuilder; childArgsBuilder.set("leaf.index", FnAttribute::IntAttribute(i)); childArgsBuilder.set("leaf.sourceLoc", FnAttribute::StringAttribute(sourceLocation)); interface.createChild(ss.str(), "", childArgsBuilder.build()); } } } else { // just create a single instance array location FnAttribute::GroupBuilder geoGb; geoGb.set("instanceSource", FnAttribute::StringAttribute(sourceLocation)); if (floatFormat) { // we can use FloatAttr for instance array types std::vector<float> aMatrixValues(numInstances * 16, 0.0f); for (int i = 0; i < numInstances; i++) { const Vec3& trans = aTranslates[i]; // set matrix values unsigned int matrixStartOffset = i * 16; aMatrixValues[matrixStartOffset] = 1.0f; aMatrixValues[matrixStartOffset + 5] = 1.0f; aMatrixValues[matrixStartOffset + 10] = 1.0f; aMatrixValues[matrixStartOffset + 12] = trans.x; aMatrixValues[matrixStartOffset + 13] = trans.y; aMatrixValues[matrixStartOffset + 14] = trans.z; aMatrixValues[matrixStartOffset + 15] = 1.0f; } geoGb.set("instanceMatrix", FnAttribute::FloatAttribute(aMatrixValues.data(), numInstances * 16, 16)); } else { // double format std::vector<double> aMatrixValues(numInstances * 16, 0.0); for (int i = 0; i < numInstances; i++) { const Vec3& trans = aTranslates[i]; // set matrix values unsigned int matrixStartOffset = i * 16; aMatrixValues[matrixStartOffset] = 1.0; aMatrixValues[matrixStartOffset + 5] = 1.0; aMatrixValues[matrixStartOffset + 10] = 1.0; aMatrixValues[matrixStartOffset + 12] = trans.x; aMatrixValues[matrixStartOffset + 13] = trans.y; aMatrixValues[matrixStartOffset + 14] = trans.z; aMatrixValues[matrixStartOffset + 15] = 1.0; } geoGb.set("instanceMatrix", FnAttribute::DoubleAttribute(aMatrixValues.data(), numInstances * 16, 16)); } std::vector<int> aInstanceIndices; if (createInstanceIndexAttribute) { // if we want the optional (for renderers we care about anyway) instanceIndex attribute, add that as well... // create array of 0, for each index aInstanceIndices.resize(numInstances, 0); geoGb.set("instanceIndex", FnAttribute::IntAttribute(aInstanceIndices.data(), numInstances, 1)); } interface.setAttr("geometry", geoGb.build()); interface.setAttr("type", FnAttribute::StringAttribute("instance array")); interface.stopChildTraversal(); } return; } FnAttribute::GroupAttribute group = interface.getOpArg("group"); if (group.isValid()) { FnAttribute::IntAttribute indexStartAttr = group.getChildByName("indexStart"); int indexStart = indexStartAttr.getValue(0, false); FnAttribute::IntAttribute sizeAttr = group.getChildByName("size"); int size = sizeAttr.getValue(0 , false); FnAttribute::StringAttribute sourceLocationAttr = group.getChildByName("sourceLoc"); interface.setAttr("type", FnAttribute::StringAttribute("group")); for (int i = indexStart; i < indexStart + size; i++) { std::ostringstream ss; ss << "instance_" << i; FnAttribute::GroupBuilder childArgsBuilder; childArgsBuilder.set("leaf.index", FnAttribute::IntAttribute(i)); childArgsBuilder.set("leaf.sourceLoc", sourceLocationAttr); interface.createChild(ss.str(), "", childArgsBuilder.build()); } interface.stopChildTraversal(); } FnAttribute::GroupAttribute leaf = interface.getOpArg("leaf"); if (leaf.isValid()) { FnAttribute::IntAttribute indexAttr = leaf.getChildByName("index"); int index = indexAttr.getValue(0 , false); FnAttribute::GroupBuilder geoGb; FnAttribute::StringAttribute sourceLocationAttr = leaf.getChildByName("sourceLoc"); if (sourceLocationAttr.isValid()) { geoGb.set("instanceSource", sourceLocationAttr); } interface.setAttr("type", FnAttribute::StringAttribute("instance")); interface.setAttr("geometry", geoGb.build()); FnAttribute::GroupBuilder xformGb; const Vec3& trans = aTranslates[index]; double transValues[3] = { trans.x, trans.y, trans.z }; xformGb.set("translate", FnAttribute::DoubleAttribute(transValues, 3, 3)); interface.setAttr("xform", xformGb.build()); interface.stopChildTraversal(); } }