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 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 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 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;
	}