void AttributeMath::handleOperation( FnAttribute::GroupAttribute &spec, FnKat::GeolibCookInterface &interface) { FnAttribute::StringAttribute srcNameAttr = spec.getChildByName("attributeName"); if(!srcNameAttr.isValid()) { return; } const std::string srcName = srcNameAttr.getValue(); if(srcName.empty()) { return; } FnAttribute::DataAttribute srcAttr = interface.getAttr(srcName); if(!srcAttr.isValid()) { // see if we should apply to globals FnAttribute::IntAttribute applyGlobals = interface.getOpArg("applyToGlobalValues"); if(applyGlobals.getValue(0, false) != 0) { srcAttr = FnKat::GetGlobalAttr(interface, srcName); } } if(!srcAttr.isValid()) { // see if we should apply to defaults FnAttribute::IntAttribute applyDefaults= interface.getOpArg("applyToDefaultValues"); if(applyDefaults.getValue(0, false) != 0) { FnAttribute::GroupAttribute defaults = FnGeolibServices::FnGeolibCookInterfaceUtils::cookDaps(interface, ""); srcAttr = defaults.getChildByName(srcName); } } if(!srcAttr.isValid()) { return; } FnAttribute::DataAttribute finalAttr; // We need to support ints, floats and doubles, FnAttribute::FloatAttribute asFloatAttr = srcAttr; if(asFloatAttr.isValid()) { finalAttr = handleAttr(asFloatAttr, spec, interface); } else { FnAttribute::DoubleAttribute asDoubleAttr = srcAttr; if(asDoubleAttr.isValid()) { finalAttr = handleAttr(asDoubleAttr, spec, interface); } else { FnAttribute::IntAttribute asIntAttr = srcAttr; if(asIntAttr.isValid()) { finalAttr = handleAttr(asIntAttr, spec, interface); } } } if(!finalAttr.isValid()){ return; } // this is way more fun FnAttribute::StringAttribute destNameAttr = spec.getChildByName("destinationAttr"); std::string destAttrName = destNameAttr.getValue(srcName, false); if(destAttrName == "") { destAttrName = srcName; } interface.setAttr(destAttrName, finalAttr); }
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(); } }