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