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);
}
Beispiel #2
0
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();
	}
}