public static bool CreateAndCookCurveAsset(HEU_SessionBase session, string assetName, bool bCookTemplatedGeos, out HAPI_NodeId newAssetID) { newAssetID = HEU_Defines.HEU_INVALID_NODE_ID; if (!session.CreateNode(HEU_Defines.HEU_INVALID_NODE_ID, "SOP/curve", "Curve", true, out newAssetID)) { return(false); } // Make sure cooking is successfull before proceeding. Any licensing or file data issues will be caught here. if (!HEU_HAPIUtility.ProcessHoudiniCookStatus(session, assetName)) { return(false); } // In case the cooking wasn't done previously, force it now. bool bResult = HEU_HAPIUtility.CookNodeInHoudini(session, newAssetID, bCookTemplatedGeos, assetName); if (!bResult) { // When cook failed, delete the node created earlier session.DeleteNode(newAssetID); newAssetID = HEU_Defines.HEU_INVALID_NODE_ID; return(false); } return(true); }
public static bool CreateInputNodeWithMultiObjects(HEU_SessionBase session, HAPI_NodeId assetID, ref HAPI_NodeId connectedAssetID, ref List<HEU_InputObjectInfo> inputObjects, ref List<HAPI_NodeId> inputObjectsConnectedAssetIDs, bool bKeepWorldTransform) { // Create the merge SOP node. if (!session.CreateNode(-1, "SOP/merge", null, true, out connectedAssetID)) { Debug.LogErrorFormat("Unable to create merge SOP node for connecting input assets."); return false; } int numObjects = inputObjects.Count; for (int i = 0; i < numObjects; ++i) { HAPI_NodeId meshNodeID = HEU_Defines.HEU_INVALID_NODE_ID; inputObjectsConnectedAssetIDs.Add(meshNodeID); // Skipping null gameobjects. Though if this causes issues, can always let it continue // to create input node, but not upload mesh data if (inputObjects[i]._gameObject == null) { continue; } bool bResult = CreateInputNodeWithGeoData(session, assetID, inputObjects[i]._gameObject, out meshNodeID); if (!bResult || meshNodeID == HEU_Defines.HEU_INVALID_NODE_ID) { string errorMsg = string.Format("Input at index {0} is not valid", i); if (inputObjects[i]._gameObject.GetComponent<HEU_HoudiniAssetRoot>() != null) { errorMsg += " because it is an HDA. Change the Input Type to HDA."; } else if (inputObjects[i]._gameObject.GetComponent<MeshFilter>() == null || inputObjects[i]._gameObject.GetComponent<MeshFilter>().sharedMesh == null) { errorMsg += " because it does not have a valid Mesh. Make sure the GameObject has a MeshFilter component with a valid mesh."; } else { errorMsg += ". Unable to create input node."; } Debug.LogErrorFormat(errorMsg); // Skipping this and continuing input processing since this isn't a deal breaker continue; } inputObjectsConnectedAssetIDs[i] = meshNodeID; if (!session.ConnectNodeInput(connectedAssetID, i, meshNodeID)) { Debug.LogErrorFormat("Unable to connect input nodes!"); return false; } UploadInputObjectTransform(session, inputObjects[i], meshNodeID, bKeepWorldTransform); } return true; }
internal bool CreateInputNodeForCollider(HEU_SessionBase session, out HAPI_NodeId outNodeID, HAPI_NodeId parentNodeId, int colliderIndex, string colliderName, float[] colliderVertices, int[] colliderIndices) { outNodeID = HEU_Defines.HEU_INVALID_NODE_ID; HAPI_NodeId colliderNodeId = HEU_Defines.HEU_INVALID_NODE_ID; if (!session.CreateNode(parentNodeId, "null", colliderName, false, out colliderNodeId)) return false; HAPI_PartInfo partInfo = new HAPI_PartInfo(); partInfo.init(); partInfo.id = 0; partInfo.nameSH = 0; partInfo.attributeCounts[(int)HAPI_AttributeOwner.HAPI_ATTROWNER_POINT] = 0; partInfo.attributeCounts[(int)HAPI_AttributeOwner.HAPI_ATTROWNER_PRIM] = 0; partInfo.attributeCounts[(int)HAPI_AttributeOwner.HAPI_ATTROWNER_VERTEX] = 0; partInfo.attributeCounts[(int)HAPI_AttributeOwner.HAPI_ATTROWNER_DETAIL] = 0; partInfo.vertexCount = colliderIndices.Length; partInfo.faceCount = colliderIndices.Length / 3; partInfo.pointCount = colliderVertices.Length / 3; partInfo.type = HAPI_PartType.HAPI_PARTTYPE_MESH; if (!session.SetPartInfo(colliderNodeId, 0, ref partInfo)) return false; HAPI_AttributeInfo attributeInfoPoint = new HAPI_AttributeInfo(); attributeInfoPoint.count = colliderVertices.Length / 3; attributeInfoPoint.tupleSize = 3; attributeInfoPoint.exists = true; attributeInfoPoint.owner = HAPI_AttributeOwner.HAPI_ATTROWNER_POINT; attributeInfoPoint.storage = HAPI_StorageType.HAPI_STORAGETYPE_FLOAT; attributeInfoPoint.originalOwner = HAPI_AttributeOwner.HAPI_ATTROWNER_INVALID; if (!session.AddAttribute(colliderNodeId, 0, HEU_HAPIConstants.HAPI_ATTRIB_POSITION, ref attributeInfoPoint)) return false; if (!session.SetAttributeFloatData(colliderNodeId, 0, HEU_HAPIConstants.HAPI_ATTRIB_POSITION, ref attributeInfoPoint, colliderVertices, 0, attributeInfoPoint.count)) return false; if (!session.SetVertexList(colliderNodeId, 0, colliderIndices, 0, colliderIndices.Length)) return false; int[] faceCounts = new int[partInfo.faceCount]; for (int i = 0; i < faceCounts.Length; i++) { faceCounts[i] = 3; } if (!session.SetFaceCount(colliderNodeId, 0, faceCounts, 0, faceCounts.Length)) return false; if (!session.CommitGeo(colliderNodeId)) return false; outNodeID = colliderNodeId; return true; }
internal static bool CreateInputNodeWithMultiAssets(HEU_SessionBase session, HEU_HoudiniAsset parentAsset, ref HAPI_NodeId connectMergeID, ref List<HEU_InputHDAInfo> inputAssetInfos, bool bKeepWorldTransform, HAPI_NodeId mergeParentID = -1) { // Create the merge SOP node that the input nodes are going to connect to. if (!session.CreateNode(mergeParentID, "SOP/merge", null, true, out connectMergeID)) { HEU_Logger.LogErrorFormat("Unable to create merge SOP node for connecting input assets."); return false; } int numInputs = inputAssetInfos.Count; for (int i = 0; i < numInputs; ++i) { inputAssetInfos[i]._connectedInputNodeID = HEU_Defines.HEU_INVALID_NODE_ID; if (inputAssetInfos[i]._pendingGO == null) { continue; } // ID of the asset that will be connected HAPI_NodeId inputAssetID = HEU_Defines.HEU_INVALID_NODE_ID; HEU_HoudiniAssetRoot inputAssetRoot = inputAssetInfos[i]._pendingGO.GetComponent<HEU_HoudiniAssetRoot>(); if (inputAssetRoot != null && inputAssetRoot._houdiniAsset != null) { if (!inputAssetRoot._houdiniAsset.IsAssetValidInHoudini(session)) { // Force a recook if its not valid (in case it hasn't been loaded into the session) inputAssetRoot._houdiniAsset.RequestCook(true, false, true, true); } inputAssetID = inputAssetRoot._houdiniAsset.AssetID; } if (inputAssetID == HEU_Defines.HEU_INVALID_NODE_ID) { continue; } if (!session.ConnectNodeInput(connectMergeID, i, inputAssetID)) { HEU_Logger.LogErrorFormat("Unable to connect input nodes!"); return false; } inputAssetInfos[i]._connectedInputNodeID = inputAssetID; inputAssetInfos[i]._connectedGO = inputAssetInfos[i]._pendingGO; inputAssetInfos[i]._connectedMergeNodeID = connectMergeID; parentAsset.ConnectToUpstream(inputAssetRoot._houdiniAsset); } return true; }
public static void CreateNodeSync(HEU_SessionBase session, string opName, string nodeNabel) { if (session == null) { session = HEU_SessionManager.GetDefaultSession(); } if (session == null || !session.IsSessionValid()) { return; } HAPI_NodeId newNodeID = -1; HAPI_NodeId parentNodeId = -1; if (!session.CreateNode(parentNodeId, opName, nodeNabel, true, out newNodeID)) { Debug.LogErrorFormat("Unable to create merge SOP node for connecting input assets."); return; } if (parentNodeId == -1) { // When creating a node without a parent, for SOP nodes, a container // geometry object will have been created by HAPI. // In all cases we want to use the node ID of that object container // so the below code sets the parent's node ID. // But for SOP/subnet we actually do want the subnet SOP node ID // hence the useSOPNodeID argument here is to override it. bool useSOPNodeID = opName.Equals("SOP/subnet"); HAPI_NodeInfo nodeInfo = new HAPI_NodeInfo(); if (!session.GetNodeInfo(newNodeID, ref nodeInfo)) { return; } if (nodeInfo.type == HAPI_NodeType.HAPI_NODETYPE_SOP) { if (!useSOPNodeID) { newNodeID = nodeInfo.parentId; } } else if (nodeInfo.type != HAPI_NodeType.HAPI_NODETYPE_OBJ) { Debug.LogErrorFormat("Unsupported node type {0}", nodeInfo.type); return; } } GameObject newGO = new GameObject(nodeNabel); HEU_NodeSync nodeSync = newGO.AddComponent<HEU_NodeSync>(); nodeSync.InitializeFromHoudini(session, newNodeID, nodeNabel, ""); }
/// <summary> /// Create an input node network and upload the given set of input objects. /// This creates a SOP/merge node, and input nodes for each object in inputObjects /// which are then connected to the merge node. /// It finds the input interface that supports each object in inputObjects for creating /// the input node and uploading the data based on the type of data. /// </summary> /// <param name="session">Session to create the input node in</param> /// <param name="assetID">Main asset ID</param> /// <param name="connectMergeID">Created SOP/merge node ID</param> /// <param name="inputObjects">List of input objects to upload</param> /// <param name="inputObjectsConnectedAssetIDs">List of input node IDs for the input nodes created</param> /// <param name="bKeepWorldTransform">Whether to use world transform for the input nodes</param> /// <returns>True if successfully uploading input nodes</returns> public static bool CreateInputNodeWithMultiObjects(HEU_SessionBase session, HAPI_NodeId assetID, ref HAPI_NodeId connectMergeID, ref List<HEU_InputObjectInfo> inputObjects, ref List<HAPI_NodeId> inputObjectsConnectedAssetIDs, bool bKeepWorldTransform) { // Create the merge SOP node that the input nodes are going to connect to. if (!session.CreateNode(-1, "SOP/merge", null, true, out connectMergeID)) { Debug.LogErrorFormat("Unable to create merge SOP node for connecting input assets."); return false; } int numObjects = inputObjects.Count; for (int i = 0; i < numObjects; ++i) { HAPI_NodeId newConnectInputID = HEU_Defines.HEU_INVALID_NODE_ID; inputObjectsConnectedAssetIDs.Add(newConnectInputID); // Skipping null gameobjects. Though if this causes issues, can always let it continue // to create input node, but not upload mesh data if (inputObjects[i]._gameObject == null) { continue; } HEU_InputInterface inputInterface = GetInputInterface(inputObjects[i]); if (inputInterface == null) { Debug.LogWarningFormat("No input interface found for gameobject: {0}. Skipping upload!", inputObjects[i]._gameObject.name); continue; } bool bResult = inputInterface.CreateInputNodeWithDataUpload(session, connectMergeID, inputObjects[i]._gameObject, out newConnectInputID); if (!bResult || newConnectInputID == HEU_Defines.HEU_INVALID_NODE_ID) { Debug.LogError("Failed to upload input."); continue; } inputObjectsConnectedAssetIDs[i] = newConnectInputID; if (!session.ConnectNodeInput(connectMergeID, i, newConnectInputID)) { Debug.LogErrorFormat("Unable to connect input nodes!"); return false; } UploadInputObjectTransform(session, inputObjects[i], newConnectInputID, bKeepWorldTransform); } return true; }
public static bool CreateAndCookAssetNode(HEU_SessionBase session, string assetName, bool bCookTemplatedGeos, out HAPI_NodeId newAssetID) { newAssetID = HEU_Defines.HEU_INVALID_NODE_ID; // Create top level node. Note that CreateNode will cook the node if HAPI was initialized with threaded cook setting on. bool bResult = session.CreateNode(-1, assetName, "", false, out newAssetID); if (!bResult) { return(false); } // Make sure cooking is successfull before proceeding. Any licensing or file data issues will be caught here. if (!ProcessHoudiniCookStatus(session, assetName)) { return(false); } // In case the cooking wasn't done previously, force it now. bResult = CookNodeInHoudini(session, newAssetID, bCookTemplatedGeos, assetName); if (!bResult) { // When cook failed, deleted the node created earlier session.DeleteNode(newAssetID); newAssetID = HEU_Defines.HEU_INVALID_NODE_ID; return(false); } // Get the asset ID HAPI_AssetInfo assetInfo = new HAPI_AssetInfo(); bResult = session.GetAssetInfo(newAssetID, ref assetInfo); if (bResult) { // Check for any errors HAPI_ErrorCodeBits errors = session.CheckForSpecificErrors(newAssetID, (HAPI_ErrorCodeBits)HAPI_ErrorCode.HAPI_ERRORCODE_ASSET_DEF_NOT_FOUND); if (errors > 0) { // TODO: revisit for UI improvement HEU_EditorUtility.DisplayDialog("Asset Missing Sub-asset Definitions", "There are undefined nodes. This is due to not being able to find specific " + "asset definitions.", "Ok"); return(false); } } return(true); }
/// <summary> /// Creates a mesh input node and uploads the mesh data from inputObject. /// </summary> /// <param name="session">Session that connectNodeID exists in</param> /// <param name="connectNodeID">The node to connect the network to. Most likely a SOP/merge node</param> /// <param name="inputObject">The gameobject containing the mesh components</param> /// <param name="inputNodeID">The created input node ID</param> /// <returns>True if created network and uploaded mesh data.</returns> public override bool CreateInputNodeWithDataUpload(HEU_SessionBase session, HAPI_NodeId connectNodeID, GameObject inputObject, out HAPI_NodeId inputNodeID) { inputNodeID = HEU_Defines.HEU_INVALID_NODE_ID; // Create input node, cook it, then upload the geometry data if (!HEU_HAPIUtility.IsNodeValidInHoudini(session, connectNodeID)) { HEU_Logger.LogError("Connection node is invalid."); return false; } bool bExportColliders = settings != null && settings.ExportColliders == true; // Get upload meshes from input object HEU_InputDataMeshes inputMeshes = GenerateMeshDatasFromGameObject(inputObject, bExportColliders); if (inputMeshes == null || inputMeshes._inputMeshes == null || inputMeshes._inputMeshes.Count == 0) { HEU_Logger.LogError("No valid meshes found on input objects."); return false; } string inputName = null; HAPI_NodeId newNodeID = HEU_Defines.HEU_INVALID_NODE_ID; session.CreateInputNode(out newNodeID, inputName); if (newNodeID == HEU_Defines.HEU_INVALID_NODE_ID || !HEU_HAPIUtility.IsNodeValidInHoudini(session, newNodeID)) { HEU_Logger.LogError("Failed to create new input node in Houdini session!"); return false; } inputNodeID = newNodeID; if (!UploadData(session, inputNodeID, inputMeshes)) { if (!session.CookNode(inputNodeID, false)) { HEU_Logger.LogError("New input node failed to cook!"); return false; } return false; } bool createMergeNode = false; HAPI_NodeId mergeNodeId = HEU_Defines.HEU_INVALID_NODE_ID; if (bExportColliders) { createMergeNode = true; } if (!createMergeNode) { return true; } HAPI_NodeId parentId = HEU_HAPIUtility.GetParentNodeID(session, newNodeID); if (!session.CreateNode(parentId, "merge", null, false, out mergeNodeId)) { HEU_Logger.LogErrorFormat("Unable to create merge SOP node for connecting input assets."); return false; } if (!session.ConnectNodeInput(mergeNodeId, 0, newNodeID)) { HEU_Logger.LogErrorFormat("Unable to connect to input node!"); return false; } if (!session.SetNodeDisplay(mergeNodeId, 1)) { HEU_Logger.LogWarningFormat("Unable to set display flag!"); } inputNodeID = mergeNodeId; if (bExportColliders) { if (!UploadColliderData(session, mergeNodeId, inputMeshes, parentId)) { return false; } } if (!session.CookNode(inputNodeID, false)) { HEU_Logger.LogError("New input node failed to cook!"); return false; } return true; }
internal bool UploadCapsuleColliderData(HEU_SessionBase session, CapsuleCollider collider, int inputIndex, HAPI_NodeId parentNodeID, out HAPI_NodeId inputNodeID) { inputNodeID = HEU_Defines.HEU_INVALID_NODE_ID; if (!collider) return false; // Copied from Unreal FKSphylElem::GetElemSolid because exact Unity capsule source code is not available Vector3 sphereCenter = collider.center; float sphereRadius = collider.radius; float sphereLength = collider.height; // Height in Unreal is only the line segment. Height in Unity is the total length, so to get the line length, subtract 2 * rad sphereLength = Mathf.Max(sphereLength - 2 * sphereRadius, 0); int direction = collider.direction; // 0 = X, 1 = Y, 2 = Z. Default is Y // Unreal Y -> Unity X, Unreal Z -> Unity Y int numSides = 6; int numRings = (numSides / 2) + 1; int numVerts = (numSides + 1) * (numRings + 1); // Calculate the vertices for one arc Vector3[] arcVertices = new Vector3[numRings + 1]; for (int ringIdx = 0; ringIdx < numRings + 1; ringIdx++) { float angle; float zOffset; if (ringIdx <= numSides / 4) { angle = ((float) ringIdx / (numRings - 1)) * Mathf.PI; zOffset = 0.5f * sphereLength; } else { angle = ((float)(ringIdx - 1) / (numRings - 1) ) * Mathf.PI; zOffset = -0.5f * sphereLength; } // Note- unit sphere, so position always has mag of one. We can just use it for normal! Vector3 spherePos = new Vector3(); spherePos.x = sphereRadius * Mathf.Sin(angle); spherePos.y = sphereRadius * Mathf.Cos(angle); spherePos.z = 0; arcVertices[ringIdx] = spherePos + new Vector3(0, zOffset, 0); } Vector3 directionRotationEuler = Vector3.zero; if (direction == 1) { // Y axis - This is the default after Unity unit conversion directionRotationEuler = Vector3.zero; } else if (direction == 0) { // X axis - Rotate around Z directionRotationEuler = new Vector3(0, 0, 90); } else if (direction == 2) { // Z axis - Rotate around X directionRotationEuler = new Vector3(90, 0, 0); } Quaternion directionRotation = Quaternion.Euler(directionRotationEuler); // Get the transform matrix for the rotation // Get the capsule vertices by rotating the arc NumSides+1 times float[] vertices = new float[numVerts * 3]; for (int sideIdx = 0; sideIdx < numSides + 1; sideIdx++) { Vector3 arcEuler = new Vector3(0, 360.0f *((float)sideIdx / (float)numSides), 0); Quaternion arcRot = Quaternion.Euler(arcEuler); for (int vertIdx = 0; vertIdx < numRings + 1; vertIdx++) { int vIx = (numRings + 1) * sideIdx + vertIdx; Vector3 arcVertex = arcRot * arcVertices[vertIdx]; arcVertex = directionRotation * arcVertex; Vector3 curPosition = sphereCenter + arcVertex; HEU_HAPIUtility.ConvertPositionUnityToHoudini(curPosition, out vertices[vIx * 3 + 0], out vertices[vIx * 3 + 1], out vertices[vIx * 3 + 2]); } } int numIndices = numSides * numRings * 6; int[] indices = new int[numIndices]; int curIndex = 0; for (int sideIdx = 0; sideIdx < numSides; sideIdx++) { int a0start = (sideIdx + 0) * (numRings + 1); int a1start = (sideIdx + 1) * (numRings + 1); for (int ringIdx = 0; ringIdx < numRings; ringIdx++) { // First tri (reverse winding) indices[curIndex+0] = a0start + ringIdx + 0; indices[curIndex+2] = a1start + ringIdx + 0; indices[curIndex+1] = a0start + ringIdx + 1; curIndex += 3; // Second Tri (reverse winding) indices[curIndex+0] = a1start + ringIdx + 0; indices[curIndex+2] = a1start + ringIdx + 1; indices[curIndex+1] = a0start + ringIdx + 1; curIndex += 3; } } HAPI_NodeId sphereNodeID = -1; string sphereName = string.Format("Sphyl{0}", inputIndex); if (!CreateInputNodeForCollider(session, out sphereNodeID, parentNodeID, inputIndex, sphereName, vertices, indices)) return false; if (!session.CookNode(sphereNodeID, false)) return false; HAPI_NodeId groupNodeID = HEU_Defines.HEU_INVALID_NODE_ID; string groupName = string.Format("group{0}", inputIndex); if (!session.CreateNode(parentNodeID, "groupcreate", groupName, false, out groupNodeID)) { HEU_Logger.LogErrorFormat("Unable to create group SOP node for connecting input assets."); return false; } HAPI_NodeId groupParmID = HEU_Defines.HEU_INVALID_NODE_ID; if (!session.GetParmIDFromName(groupNodeID, "groupname", out groupParmID) || groupParmID == HEU_Defines.HEU_INVALID_NODE_ID) return false; string baseGroupName = GetColliderGroupBaseName(collider, bIsConvex: false, bIsSimple: true); string groupNameStr = string.Format("{0}_capsule{1}", baseGroupName, inputIndex); if (!session.SetParamStringValue(groupNodeID, groupNameStr, groupParmID, 0)) return false; if (!session.ConnectNodeInput(groupNodeID, 0, sphereNodeID)) return false; inputNodeID = groupNodeID; return true; }
internal bool UploadSphereColliderData(HEU_SessionBase session, SphereCollider collider, int inputIndex, HAPI_NodeId parentNodeID, out HAPI_NodeId inputNodeID) { inputNodeID = HEU_Defines.HEU_INVALID_NODE_ID; if (!collider) return false; Vector3 center = HEU_HAPIUtility.ConvertPositionUnityToHoudini(collider.center); float radius = collider.radius; HAPI_NodeId sphereNodeID = HEU_Defines.HEU_INVALID_NODE_ID; string name = string.Format("Sphere{0}", inputIndex); if (!session.CreateNode(parentNodeID, "sphere", null, false, out sphereNodeID)) { HEU_Logger.LogErrorFormat("Unable to create merge box node for connecting input assets."); return false; } string radParamName = "rad"; if (!session.SetParamFloatValue(sphereNodeID, radParamName, 0, radius)) return false; if (!session.SetParamFloatValue(sphereNodeID, radParamName, 1, radius)) return false; if (!session.SetParamFloatValue(sphereNodeID, radParamName, 2, radius)) return false; string transformParamName = "t"; if (!session.SetParamFloatValue(sphereNodeID, transformParamName, 0, center.x)) return false; if (!session.SetParamFloatValue(sphereNodeID, transformParamName, 1, center.y)) return false; if (!session.SetParamFloatValue(sphereNodeID, transformParamName, 2, center.z)) return false; string typeParamName = "type"; if (!session.SetParamIntValue(sphereNodeID, typeParamName, 0, 1)) return false; if (!session.CookNode(sphereNodeID, false)) return false; HAPI_NodeId groupNodeID = HEU_Defines.HEU_INVALID_NODE_ID; string groupName = string.Format("group{0}", inputIndex); if (!session.CreateNode(parentNodeID, "groupcreate", groupName, false, out groupNodeID)) { HEU_Logger.LogErrorFormat("Unable to create group SOP node for connecting input assets."); return false; } HAPI_NodeId groupParmID = HEU_Defines.HEU_INVALID_NODE_ID; if (!session.GetParmIDFromName(groupNodeID, "groupname", out groupParmID) || groupParmID == HEU_Defines.HEU_INVALID_NODE_ID) return false; string baseGroupName = GetColliderGroupBaseName(collider, bIsConvex: false, bIsSimple: true); string groupNameStr = string.Format("{0}_sphere{1}", baseGroupName, inputIndex); if (!session.SetParamStringValue(groupNodeID, groupNameStr, groupParmID, 0)) return false; if (!session.ConnectNodeInput(groupNodeID, 0, sphereNodeID)) return false; inputNodeID = groupNodeID; return true; }
internal bool UploadBoxColliderData(HEU_SessionBase session, BoxCollider collider, int inputIndex, HAPI_NodeId parentNodeID, out HAPI_NodeId inputNodeID) { inputNodeID = HEU_Defines.HEU_INVALID_NODE_ID; if (!collider) return false; HAPI_NodeId boxNodeID = HEU_Defines.HEU_INVALID_NODE_ID; string name = string.Format("Box{0}", inputIndex); Vector3 center = HEU_HAPIUtility.ConvertPositionUnityToHoudini(collider.center); Vector3 size = HEU_HAPIUtility.ConvertScaleUnityToHoudini(collider.size); if (!session.CreateNode(parentNodeID, "box", null, false, out boxNodeID)) { HEU_Logger.LogErrorFormat("Unable to create merge box node for connecting input assets."); return false; } string sizeParamName = "size"; if (!session.SetParamFloatValue(boxNodeID, sizeParamName, 0, size.x)) return false; if (!session.SetParamFloatValue(boxNodeID, sizeParamName, 1, size.y)) return false; if (!session.SetParamFloatValue(boxNodeID, sizeParamName, 2, size.z)) return false; string transformParamName = "t"; if (!session.SetParamFloatValue(boxNodeID, transformParamName, 0, center.x)) return false; if (!session.SetParamFloatValue(boxNodeID, transformParamName, 1, center.y)) return false; if (!session.SetParamFloatValue(boxNodeID, transformParamName, 2, center.z)) return false; if (!session.CookNode(boxNodeID, false)) return false; HAPI_NodeId groupNodeID = HEU_Defines.HEU_INVALID_NODE_ID; string groupName = string.Format("group{0}", inputIndex); if (!session.CreateNode(parentNodeID, "groupcreate", groupName, false, out groupNodeID)) { HEU_Logger.LogErrorFormat("Unable to create group SOP node for connecting input assets."); return false; } HAPI_NodeId groupParmID = HEU_Defines.HEU_INVALID_NODE_ID; if (!session.GetParmIDFromName(groupNodeID, "groupname", out groupParmID) || groupParmID == HEU_Defines.HEU_INVALID_NODE_ID) return false; string baseGroupName = GetColliderGroupBaseName(collider, bIsConvex: false, bIsSimple: true); string groupNameStr = string.Format("{0}_box{1}", baseGroupName, inputIndex); if (!session.SetParamStringValue(groupNodeID, groupNameStr, groupParmID, 0)) return false; if (!session.ConnectNodeInput(groupNodeID, 0, boxNodeID)) return false; inputNodeID = groupNodeID; return true; }
internal bool UploadMeshColliderData(HEU_SessionBase session, MeshCollider collider, int inputIndex, HAPI_NodeId parentNodeID, out HAPI_NodeId inputNodeID) { inputNodeID = HEU_Defines.HEU_INVALID_NODE_ID; if (!collider) return false; Mesh mesh = collider.sharedMesh; Vector3[] vertices = mesh.vertices; int numSubmeshes = mesh.subMeshCount; List<int> indices = new List<int>(); for (int i = 0; i < numSubmeshes; i++) { int[] indicesForSubmesh = mesh.GetIndices(i); indices.AddRange(indicesForSubmesh); } int[] indicesArr = indices.ToArray(); float[] verticesArr = new float[vertices.Length * 3]; for (int i = 0; i < vertices.Length; i++) { HEU_HAPIUtility.ConvertPositionUnityToHoudini(vertices[i], out verticesArr[i * 3 + 0], out verticesArr[i * 3 + 1], out verticesArr[i * 3 + 2]); } HAPI_NodeId meshNodeID = -1; string meshName = string.Format("MeshCollider{0}", inputIndex); if (!CreateInputNodeForCollider(session, out meshNodeID, parentNodeID, inputIndex, meshName, verticesArr, indicesArr)) return false; if (!session.CookNode(meshNodeID, false)) return false; HAPI_NodeId groupNodeID = HEU_Defines.HEU_INVALID_NODE_ID; string groupName = string.Format("group{0}", inputIndex); if (!session.CreateNode(parentNodeID, "groupcreate", groupName, false, out groupNodeID)) { HEU_Logger.LogErrorFormat("Unable to create group SOP node for connecting input assets."); return false; } HAPI_NodeId groupParmID = HEU_Defines.HEU_INVALID_NODE_ID; if (!session.GetParmIDFromName(groupNodeID, "groupname", out groupParmID) || groupParmID == HEU_Defines.HEU_INVALID_NODE_ID) return false; bool isConvex = collider.convex; string baseGroupName = GetColliderGroupBaseName(collider, bIsConvex: isConvex, bIsSimple: false); string groupNameStr = string.Format("{0}_mesh{1}", baseGroupName, inputIndex); if (!session.SetParamStringValue(groupNodeID, groupNameStr, groupParmID, 0)) return false; if (!session.ConnectNodeInput(groupNodeID, 0, meshNodeID)) return false; inputNodeID = groupNodeID; return true; }