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]; } }
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; }
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; }
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); } } } } }
/// <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); } } } } }