// Start is called before the first frame update public static void StartQuery() { string evergreenAssetPath = "Assets/Plugins/HoudiniEngineUnity/HDAs/EverGreen.otl"; string evergreenFullPath = HEU_AssetDatabase.GetAssetFullPath(evergreenAssetPath); if (string.IsNullOrEmpty(evergreenFullPath)) { Debug.LogErrorFormat("Unable to load Evergreen asset at path: {0}", evergreenAssetPath); return; } // Always need a Houdini Engine session in order to use the APIs. // This call will create a new session if one does not exist, or continue using // an existing session. HEU_SessionBase session = HEU_SessionManager.GetOrCreateDefaultSession(); // Load the Evergreen HDA into the Houdini Engine session, as well as the Unity scene. // This gives back the root gameobject of the generated HDA hiearchy in Unity. GameObject rootGO = HEU_HAPIUtility.InstantiateHDA(evergreenFullPath, Vector3.zero, session, true); if (rootGO != null) { HEU_EditorUtility.SelectObject(rootGO); } // Get reference to the Houdini script component on the asset. // This is the main container of the HDA's loaded data, and will be used in all // APIs to query and manipulate the asset. HEU_HoudiniAsset houdiniAsset = QueryHoudiniAsset(rootGO); if (houdiniAsset == null) { return; } // Make sure the HDA is cooked before querying or changing its properties. CookAsset(houdiniAsset); // Example of querying and changing parms. ChangeParmsAndCook(houdiniAsset); // This will query objects, geometry, parts, and attributes in the asset. QueryObjects(houdiniAsset); // This will query the gravity attribute. QueryAttribute(houdiniAsset, "EvergreenGenerator", "EvergreenGenerator1", 0, "Cd"); }
/// <summary> /// Applies a Houdini's UVLayout node to each given gameobject's mesh data, and generates the output. /// The output could be a copy gameobject, or replace the mesh and materials on the original. /// </summary> /// <param name="gameObjects">Array of gameobjects containing meshes</param> /// <param name="outputMode">How the outputs should be generated</param> /// <param name="output_name_suffix">Name to append at end of each generated gameobject if outputMode == COPY</param> public static void ApplyUVLayoutTo(GameObject[] gameObjects, OutputMode outputMode, string output_name_suffix) { // A Houdini Engine session is always required. This should catch any licensing and installation issues. HEU_SessionBase session = HEU_SessionManager.GetOrCreateDefaultSession(); if (session == null || !session.IsSessionValid()) { Debug.LogError("Failed to get Houdini Engine session. Unable to apply UV layout."); return; } if (gameObjects == null || gameObjects.Length == 0) { Debug.LogError("No input objects found to apply UV layout."); return; } // For each gameobject with mesh: // -create an input node in the Houdini session // -import the mesh data into the input node // -connect input node to a new UVLayout node // -cook the UVLayout node // -generate the output mesh foreach (GameObject currentGO in gameObjects) { // Process the current gameobject to get the potential list of input mesh data. // HEU_InputUtility contains helper functions for uploading mesh data into Houdini. // Also handles LOD meshes. bool bHasLODGroup = false; HEU_InputInterfaceMesh inputMeshInterface = HEU_InputUtility.GetInputInterfaceByType(typeof(HEU_InputInterfaceMesh)) as HEU_InputInterfaceMesh; HEU_InputInterfaceMesh.HEU_InputDataMeshes inputMeshes = inputMeshInterface.GenerateMeshDatasFromGameObject(currentGO); if (inputMeshes == null || inputMeshes._inputMeshes.Count == 0) { Debug.LogWarningFormat("Failed to generate input mesh data for: {0}", currentGO.name); continue; } // Create the input node in Houdini. // Houdini Engine automatically creates a new object to contain the input node. string inputName = null; HAPI_NodeId inputNodeID = HEU_Defines.HEU_INVALID_NODE_ID; session.CreateInputNode(out inputNodeID, inputName); if (inputNodeID == HEU_Defines.HEU_INVALID_NODE_ID || !HEU_HAPIUtility.IsNodeValidInHoudini(session, inputNodeID)) { Debug.LogErrorFormat("Failed to create new input node in Houdini session!"); break; } // Need the HAPI_NodeInfo of the new input node to get its details, such as parent object ID. HAPI_NodeInfo nodeInfo = new HAPI_NodeInfo(); if (!session.GetNodeInfo(inputNodeID, ref nodeInfo)) { break; } // Cook the node to make sure everything is alright. if (!session.CookNode(inputNodeID, false)) { session.DeleteNode(nodeInfo.parentId); Debug.LogErrorFormat("New input node failed to cook!"); break; } // Now upload the mesh data into the input node. if (!inputMeshInterface.UploadData(session, inputNodeID, inputMeshes)) { session.DeleteNode(nodeInfo.parentId); Debug.LogErrorFormat("Failed to upload input mesh data"); break; } // Create UVLayout node in Houdini. Passing in the input node's parent node's ID will // create it within the same object as the input node.. HAPI_NodeId uvlayoutID = -1; if (!session.CreateNode(nodeInfo.parentId, "uvlayout", "UVLayout", true, out uvlayoutID)) { session.DeleteNode(nodeInfo.parentId); break; } // Example showing how to set the parameter on the new UVLayout node. session.SetParamIntValue(uvlayoutID, "correctareas", 0, 1); // Connect the input node to the UVLayout node. // Important bit here is the node IDs being passed in. if (!session.ConnectNodeInput(uvlayoutID, 0, inputNodeID, 0)) { session.DeleteNode(nodeInfo.parentId); break; } // Force cook the UVLayout node in Houdini. if (!HEU_HAPIUtility.CookNodeInHoudini(session, uvlayoutID, true, "uvlayout")) { session.DeleteNode(nodeInfo.parentId); break; } // Now its time to generate the actual output in Unity. A couple of utlity classes will help here. // materialCache will contain the list of materials generated.. List <HEU_MaterialData> materialCache = new List <HEU_MaterialData>(); // Suggested name of the folder within this project where output files might be written out to (eg. materials). string assetCachePathName = "uvlayoutcache"; // First create a HEU_GenerateGeoCache which will contain the geometry data from Houdiini. // This will get all the geometry data buffers from Houdini from the UVLayout node, along with the materials (new or existing). HEU_GenerateGeoCache geoCache = HEU_GenerateGeoCache.GetPopulatedGeoCache(session, inputNodeID, uvlayoutID, 0, bHasLODGroup, materialCache, assetCachePathName); if (geoCache == null) { session.DeleteNode(nodeInfo.parentId); break; } // Store reorganized data buffers into mesh groups. Groups are created if its a LOD mesh. List <HEU_GeoGroup> LODGroupMeshes = null; // The default material identifier (used when no material is supplied initially in Unity). int defaultMaterialKey = 0; // Flag whether to generate UVs, tangents, normals in Unity (in case they weren't created in Houdini). bool bGenerateUVs = false; bool bGenerateTangents = false; bool bGenerateNormals = false; bool bPartInstanced = false; // Now reorganize the data buffers into Unity mesh friendly format. // This handles point splitting into vertices, collider groups, submeshes based on multiple materials, LOD groups. // Can instead use HEU_GenerateGeoCache.GenerateGeoGroupUsingGeoCachePoints to keep as points instead. bool bResult = HEU_GenerateGeoCache.GenerateGeoGroupUsingGeoCacheVertices(session, geoCache, bGenerateUVs, bGenerateTangents, bGenerateNormals, bHasLODGroup, bPartInstanced, out LODGroupMeshes, out defaultMaterialKey); if (!bResult) { session.DeleteNode(nodeInfo.parentId); break; } // This will hold the output gameobject, along with any children and materials. HEU_GeneratedOutput generatedOutput = new HEU_GeneratedOutput(); if (outputMode == OutputMode.COPY) { // For copy mode, create and set new gameobject as output generatedOutput._outputData._gameObject = new GameObject(currentGO.name + "_HEU_modified"); } else if (outputMode == OutputMode.REPLACE) { // For replace, just use current input gameobject generatedOutput._outputData._gameObject = currentGO; } // Now generate the Unity meshes with material assignment. Handle LOD groups. int numLODs = LODGroupMeshes != null ? LODGroupMeshes.Count : 0; if (numLODs > 1) { bResult = HEU_GenerateGeoCache.GenerateLODMeshesFromGeoGroups(session, LODGroupMeshes, geoCache, generatedOutput, defaultMaterialKey, bGenerateUVs, bGenerateTangents, bGenerateNormals, bPartInstanced); } else if (numLODs == 1) { bResult = HEU_GenerateGeoCache.GenerateMeshFromSingleGroup(session, LODGroupMeshes[0], geoCache, generatedOutput, defaultMaterialKey, bGenerateUVs, bGenerateTangents, bGenerateNormals, bPartInstanced); } // Clean up by deleting the object node containing the input and uvlayout node. session.DeleteNode(nodeInfo.parentId); } }