private void GenerateInstancer(HEU_LoadBufferInstancer instancerBuffer, Dictionary<HAPI_NodeId, HEU_LoadBufferBase> idBuffersMap) { if (instancerBuffer._generatedOutput != null) { // Already generated return; } Transform parent = this.gameObject.transform; GameObject instanceRootGO = new GameObject("instance_" + instancerBuffer._name); Transform instanceRootTransform = instanceRootGO.transform; instanceRootTransform.parent = parent; instanceRootTransform.localPosition = Vector3.zero; instanceRootTransform.localRotation = Quaternion.identity; instanceRootTransform.localScale = Vector3.one; instancerBuffer._generatedOutput = new HEU_GeneratedOutput(); instancerBuffer._generatedOutput._outputData._gameObject = instanceRootGO; _generatedOutputs.Add(instancerBuffer._generatedOutput); if (instancerBuffer._instanceNodeIDs != null && instancerBuffer._instanceNodeIDs.Length > 0) { GenerateInstancesFromNodeIDs(instancerBuffer, idBuffersMap, instanceRootTransform); } else if (instancerBuffer._assetPaths != null && instancerBuffer._assetPaths.Length > 0) { GenerateInstancesFromAssetPaths(instancerBuffer, instanceRootTransform); } SetOutputVisiblity(instancerBuffer); }
public bool GenerateInstancerBuffers(HEU_SessionBase session, HAPI_NodeId nodeID, List<HAPI_PartInfo> instancerParts, out List<HEU_LoadBufferInstancer> instancerBuffers) { instancerBuffers = null; if (instancerParts.Count == 0) { return true; } instancerBuffers = new List<HEU_LoadBufferInstancer>(); foreach (HAPI_PartInfo partInfo in instancerParts) { HAPI_NodeId geoID = nodeID; HAPI_PartId partID = partInfo.id; string partName = HEU_SessionManager.GetString(partInfo.nameSH, session); HEU_LoadBufferInstancer newBuffer = null; if (partInfo.instancedPartCount > 0) { // Part instancer newBuffer = GeneratePartsInstancerBuffer(session, geoID, partID, partName, partInfo); } else if (partInfo.vertexCount == 0 && partInfo.pointCount > 0) { // Point attribute instancer newBuffer = GeneratePointAttributeInstancerBuffer(session, geoID, partID, partName, partInfo); } else { SetLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Invalid instanced part count: {0} for part {1}", partInfo.instancedPartCount, partName)); continue; } if (newBuffer != null) { instancerBuffers.Add(newBuffer); } } return true; }
private void GenerateInstancer(HAPI_NodeId cookNodeId, HEU_LoadBufferInstancer instancerBuffer, Dictionary <HAPI_NodeId, HEU_LoadBufferBase> idBuffersMap) { if (instancerBuffer._generatedOutput != null) { // Already generated return; } HEU_SessionBase session = GetHoudiniSession(true); Transform parent = this.gameObject.transform; GameObject instanceRootGO = new GameObject("instance_" + instancerBuffer._name); HAPI_PartId partId = instancerBuffer._id; ApplyAttributeModifiersOnGameObjectOutput(session, cookNodeId, partId, ref instanceRootGO); Transform instanceRootTransform = instanceRootGO.transform; instanceRootTransform.parent = parent; instanceRootTransform.localPosition = Vector3.zero; instanceRootTransform.localRotation = Quaternion.identity; instanceRootTransform.localScale = Vector3.one; instancerBuffer._generatedOutput = new HEU_GeneratedOutput(); instancerBuffer._generatedOutput._outputData._gameObject = instanceRootGO; _generatedOutputs.Add(instancerBuffer._generatedOutput); if (instancerBuffer._instanceNodeIDs != null && instancerBuffer._instanceNodeIDs.Length > 0) { GenerateInstancesFromNodeIDs(cookNodeId, instancerBuffer, idBuffersMap, instanceRootTransform); } else if (instancerBuffer._assetPaths != null && instancerBuffer._assetPaths.Length > 0) { GenerateInstancesFromAssetPaths(instancerBuffer, instanceRootTransform); } SetOutputVisiblity(instancerBuffer); }
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; }
private void GenerateInstancesFromNodeIDs(HEU_LoadBufferInstancer instancerBuffer, Dictionary<HAPI_NodeId, HEU_LoadBufferBase> idBuffersMap, Transform instanceRootTransform) { int numInstances = instancerBuffer._instanceNodeIDs.Length; for (int i = 0; i < numInstances; ++i) { HEU_LoadBufferBase sourceBuffer = null; if (!idBuffersMap.TryGetValue(instancerBuffer._instanceNodeIDs[i], out sourceBuffer) || sourceBuffer == null) { Debug.LogErrorFormat("Part with id {0} is missing. Unable to setup instancer!", instancerBuffer._instanceNodeIDs[i]); return; } // If the part we're instancing is itself an instancer, make sure it has generated its instances if (sourceBuffer._bInstanced && sourceBuffer._generatedOutput == null) { HEU_LoadBufferInstancer sourceBufferInstancer = instancerBuffer as HEU_LoadBufferInstancer; if (sourceBufferInstancer != null) { GenerateInstancer(sourceBufferInstancer, idBuffersMap); } } GameObject sourceGameObject = sourceBuffer._generatedOutput._outputData._gameObject; if (sourceGameObject == null) { Debug.LogErrorFormat("Output gameobject is null for source {0}. Unable to instance for {1}.", sourceBuffer._name, instancerBuffer._name); continue; } int numTransforms = instancerBuffer._instanceTransforms.Length; for (int j = 0; j < numTransforms; ++j) { CreateNewInstanceFromObject(sourceGameObject, (j + 1), instanceRootTransform, ref instancerBuffer._instanceTransforms[i], instancerBuffer._instancePrefixes, instancerBuffer._name); } } }
private void GenerateInstancesFromAssetPaths(HEU_LoadBufferInstancer instancerBuffer, Transform instanceRootTransform) { // For single asset, this is set when its impoted GameObject singleAssetGO = null; // For multi assets, keep track of loaded objects so we only need to load once for each object Dictionary<string, GameObject> loadedUnityObjectMap = new Dictionary<string, GameObject>(); // Temporary empty gameobject in case the specified Unity asset is not found GameObject tempGO = null; if (instancerBuffer._assetPaths.Length == 1) { // Single asset path if (!string.IsNullOrEmpty(instancerBuffer._assetPaths[0])) { HEU_AssetDatabase.ImportAsset(instancerBuffer._assetPaths[0], HEU_AssetDatabase.HEU_ImportAssetOptions.Default); singleAssetGO = HEU_AssetDatabase.LoadAssetAtPath(instancerBuffer._assetPaths[0], typeof(GameObject)) as GameObject; } if (singleAssetGO == null) { Debug.LogErrorFormat("Asset at path {0} not found. Unable to create instances for {1}.", instancerBuffer._assetPaths[0], instancerBuffer._name); return; } } int numInstancesCreated = 0; int numInstances = instancerBuffer._instanceTransforms.Length; for (int i = 0; i < numInstances; ++i) { // Reset to the single asset for each instance allows which is null if using multi asset // therefore forcing the instance asset to be found GameObject unitySrcGO = singleAssetGO; if (unitySrcGO == null) { // If not using single asset, then there must be an asset path for each instance if (string.IsNullOrEmpty(instancerBuffer._assetPaths[i])) { continue; } if (!loadedUnityObjectMap.TryGetValue(instancerBuffer._assetPaths[i], out unitySrcGO)) { // Try loading it //HEU_AssetDatabase.ImportAsset(instancerBuffer._assetPaths[i], HEU_AssetDatabase.HEU_ImportAssetOptions.Default); unitySrcGO = HEU_AssetDatabase.LoadAssetAtPath(instancerBuffer._assetPaths[i], typeof(GameObject)) as GameObject; if (unitySrcGO == null) { Debug.LogErrorFormat("Unable to load asset at {0} for instancing!", instancerBuffer._assetPaths[i]); // Even though the source Unity object is not found, we should create an object instance info to track it if (tempGO == null) { tempGO = new GameObject(); } unitySrcGO = tempGO; } // Adding to map even if not found so we don't flood the log with the same error message loadedUnityObjectMap.Add(instancerBuffer._assetPaths[i], unitySrcGO); } } CreateNewInstanceFromObject(unitySrcGO, (numInstancesCreated + 1), instanceRootTransform, ref instancerBuffer._instanceTransforms[i], instancerBuffer._instancePrefixes, instancerBuffer._name); numInstancesCreated++; } if (tempGO != null) { HEU_GeneralUtility.DestroyImmediate(tempGO, bRegisterUndo: false); } }
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; }
private void GenerateInstancesFromNodeIDs(HAPI_NodeId cookNodeId, HEU_LoadBufferInstancer instancerBuffer, Dictionary <HAPI_NodeId, HEU_LoadBufferBase> idBuffersMap, Transform instanceRootTransform) { // For single collision geo override GameObject singleCollisionGO = null; // For multi collision geo overrides, keep track of loaded objects Dictionary <string, GameObject> loadedCollisionObjectMap = new Dictionary <string, GameObject>(); if (instancerBuffer._collisionAssetPaths != null && instancerBuffer._collisionAssetPaths.Length == 1) { // Single collision override if (!string.IsNullOrEmpty(instancerBuffer._collisionAssetPaths[0])) { HEU_AssetDatabase.ImportAsset(instancerBuffer._collisionAssetPaths[0], HEU_AssetDatabase.HEU_ImportAssetOptions.Default); singleCollisionGO = HEU_AssetDatabase.LoadAssetAtPath(instancerBuffer._collisionAssetPaths[0], typeof(GameObject)) as GameObject; } if (singleCollisionGO == null) { // Continue on but log error Debug.LogErrorFormat("Collision asset at path {0} not found for instance {1}.", instancerBuffer._collisionAssetPaths[0], instancerBuffer._name); } } int numInstances = instancerBuffer._instanceNodeIDs.Length; for (int i = 0; i < numInstances; ++i) { HEU_LoadBufferBase sourceBuffer = null; if (!idBuffersMap.TryGetValue(instancerBuffer._instanceNodeIDs[i], out sourceBuffer) || sourceBuffer == null) { Debug.LogErrorFormat("Part with id {0} is missing. Unable to setup instancer!", instancerBuffer._instanceNodeIDs[i]); return; } // If the part we're instancing is itself an instancer, make sure it has generated its instances if (sourceBuffer._bInstanced && sourceBuffer._generatedOutput == null) { HEU_LoadBufferInstancer sourceBufferInstancer = instancerBuffer as HEU_LoadBufferInstancer; if (sourceBufferInstancer != null) { GenerateInstancer(cookNodeId, sourceBufferInstancer, idBuffersMap); } } GameObject sourceGameObject = sourceBuffer._generatedOutput._outputData._gameObject; if (sourceGameObject == null) { Debug.LogErrorFormat("Output gameobject is null for source {0}. Unable to instance for {1}.", sourceBuffer._name, instancerBuffer._name); continue; } GameObject collisionSrcGO = null; if (singleCollisionGO != null) { // Single collision geo collisionSrcGO = singleCollisionGO; } else if (instancerBuffer._collisionAssetPaths != null && (i < instancerBuffer._collisionAssetPaths.Length) && !string.IsNullOrEmpty(instancerBuffer._collisionAssetPaths[i])) { // Mutliple collision geo (one per instance). if (!loadedCollisionObjectMap.TryGetValue(instancerBuffer._collisionAssetPaths[i], out collisionSrcGO)) { collisionSrcGO = HEU_AssetDatabase.LoadAssetAtPath(instancerBuffer._collisionAssetPaths[i], typeof(GameObject)) as GameObject; if (collisionSrcGO == null) { Debug.LogErrorFormat("Unable to load collision asset at {0} for instancing!", instancerBuffer._collisionAssetPaths[i]); } else { loadedCollisionObjectMap.Add(instancerBuffer._collisionAssetPaths[i], collisionSrcGO); } } } int numTransforms = instancerBuffer._instanceTransforms.Length; for (int j = 0; j < numTransforms; ++j) { CreateNewInstanceFromObject(sourceGameObject, (j + 1), instanceRootTransform, ref instancerBuffer._instanceTransforms[j], instancerBuffer._instancePrefixes, instancerBuffer._name, collisionSrcGO); } } }