Beispiel #1
0
		private void LoadStringFromAttribute(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_NodeId partID, string attrName, ref string strValue)
		{
			HAPI_AttributeInfo attrInfo = new HAPI_AttributeInfo();
			string[] strAttr = HEU_GeneralUtility.GetAttributeStringData(session, geoID, partID, attrName, ref attrInfo);
			if (strAttr != null && strAttr.Length > 0 && !string.IsNullOrEmpty(strAttr[0]))
			{
				strValue = strAttr[0];
			}
		}
Beispiel #2
0
		private Texture2D LoadLayerTextureFromAttribute(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_NodeId partID, string attrName)
		{
			// The texture path is stored as string primitive attribute. Only 1 string path per layer.
			HAPI_AttributeInfo attrInfo = new HAPI_AttributeInfo();
			string[] texturePath = HEU_GeneralUtility.GetAttributeStringData(session, geoID, partID, attrName, ref attrInfo);
			if (texturePath != null && texturePath.Length > 0 && !string.IsNullOrEmpty(texturePath[0]))
			{
				return LoadAssetTexture(texturePath[0]);
			}
			return null;
		}
		public static string GetTerrainDataExportPathFromHeightfieldAttribute(HEU_SessionBase session, HAPI_NodeId geoID, 
			HAPI_PartId partID)
		{
			HAPI_AttributeInfo attrInfo = new HAPI_AttributeInfo();
			string[] attrValue = HEU_GeneralUtility.GetAttributeStringData(session, geoID, partID, 
				HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TERRAINDATA_EXPORT_PATH,
				ref attrInfo);
			if (attrInfo.exists && attrValue.Length > 0 && string.IsNullOrEmpty(attrValue[0]))
			{
				return attrValue[0];
			}
			return "";
		}
		/// <summary>
		/// Returns list of HEU_TreePrototypeInfo formed by querying data from given part.
		/// </summary>
		/// <param name="session">Houdini Engine session</param>
		/// <param name="geoID">Geometry object</param>
		/// <param name="partID">Part ID</param>
		/// <returns>Returns list of HEU_TreePrototypeInfo or null if none found.</returns>
		public static List<HEU_TreePrototypeInfo> GetTreePrototypeInfosFromPart(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID)
		{
			List<HEU_TreePrototypeInfo> treePrototypes = new List<HEU_TreePrototypeInfo>();

			// Each TreePrototype data is stored as a string attribute, under the 'HEU_Defines.HEIGHTFIELD_TREEPROTOTYPE + index'
			// name. So check and parse until no more valid attributes found.
			int index = 0;
			while (true)
			{
				// Does this attribute exist?
				string attrName = HEU_Defines.HEIGHTFIELD_TREEPROTOTYPE + index.ToString();
				if (!HEU_GeneralUtility.HasAttribute(session, geoID, partID, attrName, HAPI_AttributeOwner.HAPI_ATTROWNER_PRIM))
				{
					break;
				}

				index++;

				// Get the string value
				HAPI_AttributeInfo treeAttrInfo = new HAPI_AttributeInfo();
				string[] protoAttrString = HEU_GeneralUtility.GetAttributeStringData(session, geoID, partID,
					attrName, ref treeAttrInfo);
				if (protoAttrString == null || protoAttrString.Length == 0 || string.IsNullOrEmpty(protoAttrString[0]))
				{
					break;
				}

				// Parse the attribute string value:
				// Only expecting a single element here, comma-separated for the asset path and bend factor:
				// => asset_path,bend_factor
				string[] properties = protoAttrString[0].Split(',');
				if (properties.Length > 0 && !string.IsNullOrEmpty(properties[0]))
				{
					HEU_TreePrototypeInfo prototype = new HEU_TreePrototypeInfo();
					prototype._prefabPath = properties[0];
					if (properties.Length >= 2)
					{
						float.TryParse(properties[1], out prototype._bendfactor);
					}

					treePrototypes.Add(prototype);
				}
			}

			return treePrototypes.Count > 0 ? treePrototypes : null;
		}
Beispiel #5
0
		private HEU_LoadBufferInstancer GeneratePartsInstancerBuffer(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID, string partName, HAPI_PartInfo partInfo)
		{
			// Get the instance node IDs to get the geometry to be instanced.
			// Get the instanced count to all the instances. These will end up being mesh references to the mesh from instance node IDs.

			// Get each instance's transform
			HAPI_Transform[] instanceTransforms = new HAPI_Transform[partInfo.instanceCount];
			if (!HEU_GeneralUtility.GetArray3Arg(geoID, partID, HAPI_RSTOrder.HAPI_SRT, session.GetInstancerPartTransforms, instanceTransforms, 0, partInfo.instanceCount))
			{
				SetLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Unable to get instance transforms for part {0}", partName));
				return null;
			}

			// Get part IDs for the parts being instanced
			HAPI_NodeId[] instanceNodeIDs = new HAPI_NodeId[partInfo.instancedPartCount];
			if (!HEU_GeneralUtility.GetArray2Arg(geoID, partID, session.GetInstancedPartIds, instanceNodeIDs, 0, partInfo.instancedPartCount))
			{
				SetLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Unable to get instance node IDs for part {0}", partName));
				return null;
			}

			// Get instance names if set
			string[] instancePrefixes = null;
			HAPI_AttributeInfo instancePrefixAttrInfo = new HAPI_AttributeInfo();
			HEU_GeneralUtility.GetAttributeInfo(session, geoID, partID, HEU_Defines.DEFAULT_INSTANCE_PREFIX_ATTR, ref instancePrefixAttrInfo);
			if (instancePrefixAttrInfo.exists)
			{
				instancePrefixes = HEU_GeneralUtility.GetAttributeStringData(session, geoID, partID, HEU_Defines.DEFAULT_INSTANCE_PREFIX_ATTR, ref instancePrefixAttrInfo);
			}

			HEU_LoadBufferInstancer instancerBuffer = new HEU_LoadBufferInstancer();
			instancerBuffer.InitializeBuffer(partID, partName, partInfo.isInstanced, true);

			instancerBuffer._instanceTransforms = instanceTransforms;
			instancerBuffer._instanceNodeIDs = instanceNodeIDs;
			instancerBuffer._instancePrefixes = instancePrefixes;

			return instancerBuffer;
		}
		/// <summary>
		/// Returns the heightfield layer type (HFLayerType) for the specified part.
		/// </summary>
		/// <param name="session">Current Houdini Engine session</param>
		/// <param name="geoID">Heightfield object</param>
		/// <param name="partID">Heightfield layer</param>
		/// <param name="volumeName">Heightfield name</param>
		/// <returns>The HFLayerType of the specified part, or HFLayerType.DEFAULT if not valid</returns>
		public static HFLayerType GetHeightfieldLayerType(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID, string volumeName)
		{
			HFLayerType layerType = HFLayerType.DEFAULT;

			if (volumeName.Equals(HEU_Defines.HAPI_HEIGHTFIELD_LAYERNAME_HEIGHT))
			{
				layerType = HFLayerType.HEIGHT;
			}
			else if (volumeName.Equals(HEU_Defines.HAPI_HEIGHTFIELD_LAYERNAME_MASK))
			{
				layerType = HFLayerType.MASK;
			}
			else
			{
				HAPI_AttributeInfo layerTypeAttr = new HAPI_AttributeInfo();
				string[] layerTypeStr = HEU_GeneralUtility.GetAttributeStringData(session, geoID, partID, HEU_Defines.HEIGHTFIELD_LAYER_ATTR_TYPE,
					ref layerTypeAttr);
				if (layerTypeStr != null && layerTypeStr.Length >= 0 && layerTypeStr[0].Equals(HEU_Defines.HEIGHTFIELD_LAYER_TYPE_DETAIL))
				{
					layerType = HFLayerType.DETAIL;
				}
			}
			return layerType;
		}
Beispiel #7
0
		private HEU_LoadBufferInstancer GeneratePointAttributeInstancerBuffer(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID, 
			string partName, HAPI_PartInfo partInfo)
		{
			int numInstances = partInfo.pointCount;
			if (numInstances <= 0)
			{
				return null;
			}

			// Find type of instancer
			string instanceAttrName = HEU_PluginSettings.InstanceAttr;
			string unityInstanceAttrName = HEU_PluginSettings.UnityInstanceAttr;
			string instancePrefixAttrName = HEU_Defines.DEFAULT_INSTANCE_PREFIX_ATTR;

			HAPI_AttributeInfo instanceAttrInfo = new HAPI_AttributeInfo();
			HAPI_AttributeInfo unityInstanceAttrInfo = new HAPI_AttributeInfo();
			HAPI_AttributeInfo instancePrefixAttrInfo = new HAPI_AttributeInfo();

			HEU_GeneralUtility.GetAttributeInfo(session, geoID, partID, instanceAttrName, ref instanceAttrInfo);
			HEU_GeneralUtility.GetAttributeInfo(session, geoID, partID, unityInstanceAttrName, ref unityInstanceAttrInfo);

			if (unityInstanceAttrInfo.exists)
			{
				// Object instancing via existing Unity object (path from point attribute)

				HAPI_Transform[] instanceTransforms = new HAPI_Transform[numInstances];
				if (!HEU_GeneralUtility.GetArray3Arg(geoID, partID, HAPI_RSTOrder.HAPI_SRT, session.GetInstanceTransformsOnPart, instanceTransforms, 0, numInstances))
				{
					return null;
				}

				string[] instancePrefixes = null;
				HEU_GeneralUtility.GetAttributeInfo(session, geoID, partID, instancePrefixAttrName, ref instancePrefixAttrInfo);
				if (instancePrefixAttrInfo.exists)
				{
					instancePrefixes = HEU_GeneralUtility.GetAttributeStringData(session, geoID, partID, instancePrefixAttrName, ref instancePrefixAttrInfo);
				}

				string[] assetPaths = null;

				// Attribute owner type determines whether to use single (detail) or multiple (point) asset(s) as source
				if (unityInstanceAttrInfo.owner == HAPI_AttributeOwner.HAPI_ATTROWNER_POINT || unityInstanceAttrInfo.owner == HAPI_AttributeOwner.HAPI_ATTROWNER_DETAIL)
				{

					assetPaths = HEU_GeneralUtility.GetAttributeStringData(session, geoID, partID, unityInstanceAttrName, ref unityInstanceAttrInfo);
				}
				else
				{
					// Other attribute owned types are unsupported
					SetLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Unsupported attribute owner {0} for attribute {1}", 
						unityInstanceAttrInfo.owner, unityInstanceAttrName));
					return null;
				}

				if (assetPaths == null)
				{
					SetLog(HEU_LoadData.LoadStatus.ERROR, "Unable to get instanced asset path from attribute!");
					return null;
				}

				HEU_LoadBufferInstancer instancerBuffer = new HEU_LoadBufferInstancer();
				instancerBuffer.InitializeBuffer(partID, partName, partInfo.isInstanced, true);

				instancerBuffer._instanceTransforms = instanceTransforms;
				instancerBuffer._instancePrefixes = instancePrefixes;
				instancerBuffer._assetPaths = assetPaths;

				return instancerBuffer;
			}
			else if (instanceAttrInfo.exists)
			{
				// Object instancing via internal object path is not supported
				SetLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Object instancing is not supported (part {0})!", partName));
			}
			else
			{
				// Standard object instancing via single Houdini object is not supported
				SetLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Object instancing is not supported (part {0})!", partName));
			}

			return null;
		}
		/// <summary>
		/// Fill up the given detailPrototype with values from the specified heightfield part.
		/// </summary>
		/// <param name="session">Houdini Engine session to query</param>
		/// <param name="geoID">The geometry ID in Houdini</param>
		/// <param name="partID">The part ID in Houdini</param>
		/// <param name="detailPrototype">The detail prototype object to populate</param>
		public static void PopulateDetailPrototype(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID,
			ref HEU_DetailPrototype detailPrototype)
		{
			// Get the detail prototype properties from attributes on this layer

			if (detailPrototype == null)
			{
				detailPrototype = new HEU_DetailPrototype();
			}

			HAPI_AttributeInfo prefabAttrInfo = new HAPI_AttributeInfo();
			string[] prefabPaths = HEU_GeneralUtility.GetAttributeStringData(session, geoID, partID, 
				HEU_Defines.HEIGHTFIELD_DETAIL_PROTOTYPE_PREFAB, ref prefabAttrInfo);

			if (prefabAttrInfo.exists && prefabPaths.Length >= 1)
			{
				detailPrototype._prototypePrefab = prefabPaths[0];
			}

			HAPI_AttributeInfo textureAttrInfo = new HAPI_AttributeInfo();
			string[] texturePaths = HEU_GeneralUtility.GetAttributeStringData(session, geoID, partID, 
				HEU_Defines.HEIGHTFIELD_DETAIL_PROTOTYPE_TEXTURE, ref textureAttrInfo);

			if (textureAttrInfo.exists && texturePaths.Length >= 1)
			{
				detailPrototype._prototypeTexture = texturePaths[0];
			}

			float fvalue = 0;
			if (HEU_GeneralUtility.GetAttributeFloatSingle(session, geoID, partID,
				HEU_Defines.HEIGHTFIELD_DETAIL_PROTOTYPE_BENDFACTOR, out fvalue))
			{
				detailPrototype._bendFactor = fvalue;
			}

			Color color = Color.white;
			if (HEU_GeneralUtility.GetAttributeColorSingle(session, geoID, partID,
				HEU_Defines.HEIGHTFIELD_DETAIL_PROTOTYPE_DRYCOLOR, ref color))
			{
				detailPrototype._dryColor = color;
			}

			if (HEU_GeneralUtility.GetAttributeColorSingle(session, geoID, partID,
				HEU_Defines.HEIGHTFIELD_DETAIL_PROTOTYPE_HEALTHYCOLOR, ref color))
			{
				detailPrototype._healthyColor = color;
			}

			if (HEU_GeneralUtility.GetAttributeFloatSingle(session, geoID, partID,
				HEU_Defines.HEIGHTFIELD_DETAIL_PROTOTYPE_MAXHEIGHT, out fvalue))
			{
				detailPrototype._maxHeight = fvalue;
			}

			if (HEU_GeneralUtility.GetAttributeFloatSingle(session, geoID, partID,
				HEU_Defines.HEIGHTFIELD_DETAIL_PROTOTYPE_MAXWIDTH, out fvalue))
			{
				detailPrototype._maxWidth = fvalue;
			}

			if (HEU_GeneralUtility.GetAttributeFloatSingle(session, geoID, partID,
				HEU_Defines.HEIGHTFIELD_DETAIL_PROTOTYPE_MINHEIGHT, out fvalue))
			{
				detailPrototype._minHeight = fvalue;
			}

			if (HEU_GeneralUtility.GetAttributeFloatSingle(session, geoID, partID,
				HEU_Defines.HEIGHTFIELD_DETAIL_PROTOTYPE_MINWIDTH, out fvalue))
			{
				detailPrototype._minWidth = fvalue;
			}

			if (HEU_GeneralUtility.GetAttributeFloatSingle(session, geoID, partID,
				HEU_Defines.HEIGHTFIELD_DETAIL_PROTOTYPE_NOISESPREAD, out fvalue))
			{
				detailPrototype._noiseSpread = fvalue;
			}

			int iValue = 0;
			if (HEU_GeneralUtility.GetAttributeIntSingle(session, geoID, partID,
				HEU_Defines.HEIGHTFIELD_DETAIL_PROTOTYPE_RENDERMODE, out iValue))
			{
				detailPrototype._renderMode = iValue;
			}
		}
	/// <summary>
	/// Generates object instances.
	/// Skips parts that already have their instances generated.
	/// </summary>
	/// <param name="session">Active session to use</param>
	public void GenerateObjectInstances(HEU_SessionBase session)
	{
	    if (!IsInstancer())
	    {
		Debug.LogErrorFormat("Generate object instances called on a non-instancer object {0} for asset {1}!", ObjectName, ParentAsset.AssetName);
		return;
	    }

	    //Debug.LogFormat("Generate Object Instances:: id={5}, name={0}, isInstancer={1}, isInstanced={2}, instancePath={3}, instanceId={4}", HEU_SessionManager.GetString(_objectInfo.nameSH, session), 
	    //	_objectInfo.isInstancer, _objectInfo.isInstanced, HEU_SessionManager.GetString(_objectInfo.objectInstancePathSH, session), _objectInfo.objectToInstanceId, _objectInfo.nodeId);

	    // Is this a Houdini attribute instancer?
	    string instanceAttrName = HEU_PluginSettings.InstanceAttr;
	    string unityInstanceAttrName = HEU_PluginSettings.UnityInstanceAttr;
	    string instancePrefixAttrName = HEU_Defines.DEFAULT_INSTANCE_PREFIX_ATTR;

	    HAPI_AttributeInfo instanceAttrInfo = new HAPI_AttributeInfo();
	    HAPI_AttributeInfo unityInstanceAttrInfo = new HAPI_AttributeInfo();
	    HAPI_AttributeInfo instancePrefixAttrInfo = new HAPI_AttributeInfo();

	    int numGeos = _geoNodes.Count;
	    for (int i = 0; i < numGeos; ++i)
	    {
		if (_geoNodes[i].Displayable)
		{
		    List<HEU_PartData> parts = _geoNodes[i].GetParts();
		    int numParts = parts.Count;
		    for (int j = 0; j < numParts; ++j)
		    {
			if (parts[j].ObjectInstancesBeenGenerated || parts[j].IsPartVolume())
			{
			    // This prevents instances being created unnecessarily (e.g. part hasn't changed since last cook).
			    // Or for volumes that might have instance attributes.
			    continue;
			}

			HEU_GeneralUtility.GetAttributeInfo(session, _geoNodes[i].GeoID, parts[j].PartID, instanceAttrName, ref instanceAttrInfo);
			HEU_GeneralUtility.GetAttributeInfo(session, _geoNodes[i].GeoID, parts[j].PartID, unityInstanceAttrName, ref unityInstanceAttrInfo);

			string[] instancePrefixes = null;
			HEU_GeneralUtility.GetAttributeInfo(session, _geoNodes[i].GeoID, parts[j].PartID, instancePrefixAttrName, ref instancePrefixAttrInfo);
			if (instancePrefixAttrInfo.exists)
			{
			    instancePrefixes = HEU_GeneralUtility.GetAttributeStringData(session, _geoNodes[i].GeoID, parts[j].PartID, instancePrefixAttrName, ref instancePrefixAttrInfo);
			}

			// Must clear out instances, as otherwise we get duplicates
			parts[j].ClearInstances();

			// Clear out invalid object instance infos that no longer have any valid parts
			parts[j].ClearInvalidObjectInstanceInfos();

			if (instanceAttrInfo.exists)
			{
			    // Object instancing via Houdini instance attribute

			    parts[j].GenerateInstancesFromObjectIds(session, instancePrefixes);
			}
			else if (unityInstanceAttrInfo.exists)
			{
			    // Object instancing via existing Unity object (path from point attribute)

			    // Attribute owner type determines whether to use single instanced object (detail) or multiple (point)
			    if (unityInstanceAttrInfo.owner == HAPI_AttributeOwner.HAPI_ATTROWNER_POINT)
			    {
				parts[j].GenerateInstancesFromUnityAssetPathAttribute(session, unityInstanceAttrName);
			    }
			    else if (unityInstanceAttrInfo.owner == HAPI_AttributeOwner.HAPI_ATTROWNER_DETAIL)
			    {
				bool bInstanced = false;
				int[] scriptAttr = new int[unityInstanceAttrInfo.count];
				HEU_GeneralUtility.GetAttribute(session, _geoNodes[i].GeoID, parts[j].PartID, unityInstanceAttrName, ref unityInstanceAttrInfo, ref scriptAttr, session.GetAttributeStringData);
				if (unityInstanceAttrInfo.exists)
				{
				    string assetPath = HEU_SessionManager.GetString(scriptAttr[0]);
				    if (!string.IsNullOrEmpty(assetPath))
				    {
					parts[j].GenerateInstancesFromUnityAssetPath(session, assetPath, instancePrefixes);
					bInstanced = true;
				    }
				}

				if (!bInstanced)
				{
				    Debug.LogWarningFormat("Unable to get instanced object path from detail instance attribute!");
				}
			    }
			    else
			    {
				// Other attribute owned types are unsupported.
				// Originally had a warning here, but unnecessary as in some cases (e.g. heightfield attrbiutes) the
				// attribute owner could be changed in HAPI.
			    }
			}
			else
			{
			    // Standard object instancing via single Houdini object

			    if (_objectInfo.objectToInstanceId == HEU_Defines.HEU_INVALID_NODE_ID)
			    {
				Debug.LogAssertionFormat("Invalid object ID {0} used for object instancing. "
					+ "Make sure to turn on Full point instancing and set the correct Instance Object.", _objectInfo.objectToInstanceId);
				continue;
			    }

			    parts[j].GenerateInstancesFromObjectID(session, _objectInfo.objectToInstanceId, instancePrefixes);
			}
		    }
		}
	    }
	}
Beispiel #10
0
	/// <summary>
	/// Generates object instances.
	/// Skips parts that already have their instances generated.
	/// </summary>
	/// <param name="session">Active session to use</param>
	internal void GenerateObjectInstances(HEU_SessionBase session)
	{
	    if (ParentAsset == null)
	    {
		return;
	    }
	    
	    if (!IsInstancer())
	    {
		HEU_Logger.LogErrorFormat("Generate object instances called on a non-instancer object {0} for asset {1}!", ObjectName, ParentAsset.AssetName);
		return;
	    }

	    //HEU_Logger.LogFormat("Generate Object Instances:: id={5}, name={0}, isInstancer={1}, isInstanced={2}, instancePath={3}, instanceId={4}", HEU_SessionManager.GetString(_objectInfo.nameSH, session), 
	    //	_objectInfo.isInstancer, _objectInfo.isInstanced, HEU_SessionManager.GetString(_objectInfo.objectInstancePathSH, session), _objectInfo.objectToInstanceId, _objectInfo.nodeId);

	    // Is this a Houdini attribute instancer?
	    string instanceAttrName = HEU_PluginSettings.InstanceAttr;
	    string unityInstanceAttrName = HEU_PluginSettings.UnityInstanceAttr;
	    string instancePrefixAttrName = HEU_Defines.DEFAULT_INSTANCE_PREFIX_ATTR;

	    HAPI_AttributeInfo instanceAttrInfo = new HAPI_AttributeInfo();
	    HAPI_AttributeInfo unityInstanceAttrInfo = new HAPI_AttributeInfo();
	    HAPI_AttributeInfo instancePrefixAttrInfo = new HAPI_AttributeInfo();
	    HAPI_AttributeInfo materialAttrInfo = new HAPI_AttributeInfo();

	    int numGeos = _geoNodes.Count;
	    for (int i = 0; i < numGeos; ++i)
	    {
		if (_geoNodes[i].Displayable)
		{
		    List<HEU_PartData> parts = _geoNodes[i].GetParts();
		    int numParts = parts.Count;
		    for (int j = 0; j < numParts; ++j)
		    {
			if (parts[j]._objectInstancesGenerated || parts[j].IsPartVolume())
			{
			    // This prevents instances being created unnecessarily (e.g. part hasn't changed since last cook).
			    // Or for volumes that might have instance attributes.
			    continue;
			}

			HEU_GeneralUtility.GetAttributeInfo(session, _geoNodes[i].GeoID, parts[j].PartID, instanceAttrName, ref instanceAttrInfo);
			HEU_GeneralUtility.GetAttributeInfo(session, _geoNodes[i].GeoID, parts[j].PartID, unityInstanceAttrName, ref unityInstanceAttrInfo);

			string[] instancePrefixes = null;
			HEU_GeneralUtility.GetAttributeInfo(session, _geoNodes[i].GeoID, parts[j].PartID, instancePrefixAttrName, ref instancePrefixAttrInfo);
			if (instancePrefixAttrInfo.exists)
			{
			    instancePrefixes = HEU_GeneralUtility.GetAttributeStringData(session, _geoNodes[i].GeoID, parts[j].PartID, instancePrefixAttrName, ref instancePrefixAttrInfo);
			}

			string[] instanceMaterialPaths = null;
			HEU_GeneralUtility.GetAttributeInfo(session, _geoNodes[i].GeoID, parts[j].PartID, HEU_PluginSettings.UnityMaterialAttribName, ref materialAttrInfo);
			if (materialAttrInfo.exists)
			{
			    instanceMaterialPaths = HEU_GeneralUtility.GetAttributeStringData(session, _geoNodes[i].GeoID, parts[j].PartID, HEU_PluginSettings.UnityMaterialAttribName, ref materialAttrInfo);
			}

			if (instanceAttrInfo.exists)
			{
			    // Object instancing via Houdini instance attribute

			    parts[j].GenerateInstancesFromObjectIds(session, instancePrefixes, instanceMaterialPaths);
			}
			else if (unityInstanceAttrInfo.exists)
			{
			    // Object instancing via existing Unity object (path from point attribute)

			    // Attribute owner type determines whether to use single instanced object (detail) or multiple (point)
			    if (unityInstanceAttrInfo.owner == HAPI_AttributeOwner.HAPI_ATTROWNER_POINT ||
			        unityInstanceAttrInfo.owner == HAPI_AttributeOwner.HAPI_ATTROWNER_DETAIL)
			    {
				parts[j].GenerateInstancesFromUnityAssetPathAttribute(session, unityInstanceAttrName);
			    }
			    else
			    {
				// Other attribute owned types are unsupported.
				// Originally had a warning here, but unnecessary as in some cases (e.g. heightfield attrbiutes) the
				// attribute owner could be changed in HAPI.
			    }
			}
			else
			{
			    // Standard object instancing via single Houdini object

			    if (_objectInfo.objectToInstanceId == HEU_Defines.HEU_INVALID_NODE_ID)
			    {
				// HEU_Logger.LogAssertionFormat("Invalid object ID {0} used for object instancing. "
				// 	+ "Make sure to turn on Full point instancing and set the correct Instance Object.", _objectInfo.objectToInstanceId);
				// Could be a part instancer
				continue;
			    }

			    parts[j].GenerateInstancesFromObjectID(session, _objectInfo.objectToInstanceId, instancePrefixes, instanceMaterialPaths);
			}
		    }
		}
	    }
	}