Esempio n. 1
0
	/// <summary>
	/// Connect the input to the merge object node
	/// </summary>
	/// <param name="session"></param>
	private void ConnectToMergeObject(HEU_SessionBase session)
	{
	    if (_inputNodeType == InputNodeType.PARAMETER)
	    {
		if (string.IsNullOrEmpty(_paramName))
		{
		    Debug.LogErrorFormat("Invalid parameter name for input node of parameter type!");
		    return;
		}

		if (!session.SetParamNodeValue(_nodeID, _paramName, _connectedNodeID))
		{
		    Debug.LogErrorFormat("Unable to connect to input node!");
		    return;
		}

		//Debug.LogFormat("Setting input connection for parameter {0} with {1} connecting to {2}", _paramName, _nodeID, _connectedNodeID);
	    }
	    else
	    {
		if (!session.ConnectNodeInput(_nodeID, _inputIndex, _connectedNodeID))
		{
		    Debug.LogErrorFormat("Unable to connect to input node!");
		    return;
		}
	    }
	}
Esempio n. 2
0
		private void ConnectInputNode(HEU_SessionBase session)
		{
			// Connect node input
			
			if (_inputNodeType == InputNodeType.PARAMETER)
			{
				if (string.IsNullOrEmpty(_paramName))
				{
					Debug.LogErrorFormat("Invalid parameter name for input node of parameter type!");
					return;
				}

				if (!session.SetParamNodeValue(_nodeID, _paramName, _connectedNodeID))
				{
					Debug.LogErrorFormat("Unable to connect to input node!");
					return;
				}

				//Debug.LogFormat("Setting input connection for parameter {0} with {1} connecting to {2}", _paramName, _nodeID, _connectedNodeID);
			}
			else
			{
				if(!session.ConnectNodeInput(_nodeID, _inputIndex, _connectedNodeID))
				{
					Debug.LogErrorFormat("Unable to connect to input node!");
					return;
				}
			}

			// This ensures that the input node's own object merge Keep World Transform
			// plays nicely with the connected object merge's Keep World Transform
			SetInputNodeObjectMergeKeepTransform(session, false);
		}
Esempio n. 3
0
		private void ConnectInputNode(HEU_SessionBase session)
		{
			// Connect node input
			
			if (_inputNodeType == InputNodeType.PARAMETER)
			{
				if (string.IsNullOrEmpty(_paramName))
				{
					Debug.LogErrorFormat("Invalid parameter name for input node of parameter type!");
					return;
				}

				if (!session.SetParamNodeValue(_nodeID, _paramName, _connectedNodeID))
				{
					Debug.LogErrorFormat("Unable to connect to input node!");
					return;
				}
			}
			else
			{
				if(!session.ConnectNodeInput(_nodeID, _inputIndex, _connectedNodeID))
				{
					Debug.LogErrorFormat("Unable to connect to input node!");
					return;
				}
			}
		}
Esempio n. 4
0
		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;
		}
Esempio n. 5
0
	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;
	}
Esempio n. 6
0
	/// <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;
	}
Esempio n. 7
0
		/// <summary>
		/// Upload the alphamaps (terrain layers) into heightfield network.
		/// Note that this skips the base layer.
		/// </summary>
		/// <param name="session"></param>
		/// <param name="idt"></param>
		/// <returns></returns>
		public bool UploadAlphaMaps(HEU_SessionBase session, HEU_InputDataTerrain idt)
		{
			bool bResult = true;

			int alphaLayers = idt._terrainData.alphamapLayers;

			// Skip the base layer
			if (alphaLayers < 1)
			{
				return true;
			}

			int sizeX = idt._terrainData.alphamapWidth;
			int sizeY = idt._terrainData.alphamapHeight;
			int totalSize = sizeX * sizeY;

			float[,,] alphaMaps = idt._terrainData.GetAlphamaps(0, 0, sizeX, sizeY);

			float[][] alphaMapsConverted = new float[alphaLayers - 1][];

			// Convert the alphamap layers to double arrays.
			// Note that we're skipping the base alpha map.
			for (int m = 0; m < alphaLayers - 1; ++m)
			{
				alphaMapsConverted[m] = new float[totalSize];
				for (int j = 0; j < sizeY; j++)
				{
					for (int i = 0; i < sizeX; i++)
					{
						// Flip for coordinate system change
						float h = alphaMaps[i, (sizeY - j - 1), m + 1];

						alphaMapsConverted[m][i + j * sizeX] = h;
					}
				}
			}


			// Create volume layers for all non-base alpha maps and upload values.
			for (int m = 0; m < alphaLayers - 1; ++m)
			{
				string layerName = "unity_alphamap_" + m + 1;

				HAPI_NodeId alphaLayerID = HEU_Defines.HEU_INVALID_NODE_ID;
				if (!session.CreateHeightfieldInputVolumeNode(idt._heightfieldNodeID, out alphaLayerID, layerName,
					Mathf.RoundToInt(sizeX * idt._voxelSize), Mathf.RoundToInt(sizeY * idt._voxelSize), idt._voxelSize))
				{
					bResult = false;
					Debug.LogError("Failed to create input volume node for layer " + layerName);
					break;
				}

				if (!SetHeightFieldData(session, alphaLayerID, 0, alphaMapsConverted[m], layerName))
				{
					bResult = false;
					break;
				}

				if (!session.CommitGeo(alphaLayerID))
				{
					bResult = false;
					Debug.LogError("Failed to commit volume layer " + layerName);
					break;
				}

				// Connect to the merge node but starting from index 1 since index 0 is height layer
				if (!session.ConnectNodeInput(idt._mergeNodeID, m + 2, alphaLayerID, 0))
				{
					bResult = false;
					Debug.LogError("Unable to connect new volume node for layer " + layerName);
					break;
				}
			}

			return bResult;
		}
	/// <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 UploadColliderData(HEU_SessionBase session, HAPI_NodeId mergeNodeID, HEU_InputDataMeshes inputData, HAPI_NodeId parentNodeId)
	{
	    // The input to put on
	    int inputIndex = 1;

	    foreach (HEU_InputDataMesh inputMesh in inputData._inputMeshes)
	    {
		if (inputMesh == null || inputMesh._colliders == null)
		{
		    continue;
		}

		foreach (HEU_InputDataCollider colliderData in inputMesh._colliders)
		{
		    if (colliderData == null || colliderData._collider == null || colliderData._colliderType == HEU_InputColliderType.NONE)
		    {
			continue;
		    }
		    HAPI_NodeId newInputNodeID = HEU_Defines.HEU_INVALID_NODE_ID;

		    switch (colliderData._colliderType)
		    {
			case HEU_InputColliderType.BOX:
			    BoxCollider boxCollider = colliderData._collider as BoxCollider;
			    if (!boxCollider || !UploadBoxColliderData(session, boxCollider, inputIndex, parentNodeId, out newInputNodeID))
			    {
				HEU_Logger.LogWarning("Invalid collider input!");
				continue;
			    }

			    break;
			case HEU_InputColliderType.SPHERE:
			    SphereCollider sphereCollider = colliderData._collider as SphereCollider;
			    if (!sphereCollider || !UploadSphereColliderData(session, sphereCollider, inputIndex, parentNodeId, out newInputNodeID))
			    {
				HEU_Logger.LogWarning("Invalid collider input!");
				continue;
			    }

			    break;
			case HEU_InputColliderType.CAPSULE:
			    CapsuleCollider capsuleCollider = colliderData._collider as CapsuleCollider;
			    if (!capsuleCollider || !UploadCapsuleColliderData(session, capsuleCollider, inputIndex, parentNodeId, out newInputNodeID))
			    {
				HEU_Logger.LogWarning("Invalid collider input!");
				return false;
			    }

			    break;
			case HEU_InputColliderType.MESH:
			    MeshCollider meshCollider = colliderData._collider as MeshCollider;
			    if (!meshCollider || !UploadMeshColliderData(session, meshCollider, inputIndex, parentNodeId, out newInputNodeID))
			    {
				HEU_Logger.LogWarning("Invalid collider input!");
				return false;
			    }

			    break;
			default:
			    HEU_Logger.LogWarning("Invalid collider type!");
			    return false;
		    }

		    if (newInputNodeID == HEU_Defines.HEU_INVALID_NODE_ID) continue;

		    if (!session.ConnectNodeInput(mergeNodeID, inputIndex, newInputNodeID))
		    {
			HEU_Logger.LogErrorFormat("Unable to connect to input node!");
			return false;
		    }

		    inputIndex++;
		}
	    }

	    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;
	}
Esempio n. 14
0
        /// <summary>
        /// Upload the alphamaps (TerrainLayers) into heightfield network.
        /// </summary>
        /// <param name="session"></param>
        /// <param name="idt"></param>
        /// <param name="baseVolumeInfo">The valid base height HAPI_VolumeInfo</param>
        /// <param name="bMaskSet">This is set to true if a mask layer was uploaded</param>
        /// <returns>True if successfully uploaded all layers</returns>
        public bool UploadAlphaMaps(HEU_SessionBase session, HEU_InputDataTerrain idt, ref HAPI_VolumeInfo baseVolumeInfo, out bool bMaskSet)
        {
            bool bResult = true;

            bMaskSet = false;

            int alphaLayers = idt._terrainData.alphamapLayers;

            if (alphaLayers < 1)
            {
                return(bResult);
            }

            int sizeX     = idt._terrainData.alphamapWidth;
            int sizeY     = idt._terrainData.alphamapHeight;
            int totalSize = sizeX * sizeY;

            float[,,] alphaMaps = idt._terrainData.GetAlphamaps(0, 0, sizeX, sizeY);

            float[][] alphaMapsConverted = new float[alphaLayers][];

            // Convert the alphamap layers to double arrays.
            for (int m = 0; m < alphaLayers; ++m)
            {
                alphaMapsConverted[m] = new float[totalSize];
                for (int j = 0; j < sizeY; j++)
                {
                    for (int i = 0; i < sizeX; i++)
                    {
                        // Flip for coordinate system change
                        float h = alphaMaps[i, (sizeY - j - 1), m];

                        alphaMapsConverted[m][i + j * sizeX] = h;
                    }
                }
            }

            // Create volume layers for all alpha maps and upload values.
            bool bMaskLayer      = false;
            int  inputLayerIndex = 1;

            for (int m = 0; m < alphaLayers; ++m)
            {
#if UNITY_2018_3_OR_NEWER
                string layerName = idt._terrainData.terrainLayers[m].name;
#else
                string layerName = "unity_alphamap_" + m + 1;
#endif

                // The Unity layer name could contain '.terrainlayer' and spaces. Remove them because Houdini doesn't allow
                // spaces, and the extension isn't necessary.
                layerName = layerName.Replace(" ", "_");
                int extIndex = layerName.LastIndexOf(HEU_Defines.HEU_EXT_TERRAINLAYER);
                if (extIndex > 0)
                {
                    layerName = layerName.Remove(extIndex);
                }
                //Debug.Log("Processing terrain layer: " + layerName);

                HAPI_NodeId alphaLayerID = HEU_Defines.HEU_INVALID_NODE_ID;

                if (layerName.Equals(HEU_Defines.HAPI_HEIGHTFIELD_LAYERNAME_HEIGHT))
                {
                    // Skip height (base) layer (since it has been uploaded already)
                    continue;
                }
                else if (layerName.Equals(HEU_Defines.HAPI_HEIGHTFIELD_LAYERNAME_MASK))
                {
                    //Debug.Log("Mask layer found! Skipping creating the HF.");
                    bMaskSet     = true;
                    bMaskLayer   = true;
                    alphaLayerID = idt._maskNodeID;
                }
                else
                {
                    bMaskLayer = false;

                    if (!session.CreateHeightfieldInputVolumeNode(idt._heightfieldNodeID, out alphaLayerID, layerName,
                                                                  Mathf.RoundToInt(sizeX * idt._voxelSize), Mathf.RoundToInt(sizeY * idt._voxelSize), idt._voxelSize))
                    {
                        bResult = false;
                        Debug.LogError("Failed to create input volume node for layer " + layerName);
                        break;
                    }
                }

                //Debug.Log("Uploading terrain layer: " + layerName);

                if (!SetHeightFieldData(session, alphaLayerID, 0, alphaMapsConverted[m], layerName, ref baseVolumeInfo))
                {
                    bResult = false;
                    break;
                }

#if UNITY_2018_3_OR_NEWER
                SetTerrainLayerAttributesToHeightField(session, alphaLayerID, 0, idt._terrainData.terrainLayers[m]);
#endif

                if (!session.CommitGeo(alphaLayerID))
                {
                    bResult = false;
                    Debug.LogError("Failed to commit volume layer " + layerName);
                    break;
                }

                if (!bMaskLayer)
                {
                    // Connect to the merge node but starting from index 1 since index 0 is height layer
                    if (!session.ConnectNodeInput(idt._mergeNodeID, inputLayerIndex + 1, alphaLayerID, 0))
                    {
                        bResult = false;
                        Debug.LogError("Unable to connect new volume node for layer " + layerName);
                        break;
                    }

                    inputLayerIndex++;
                }
            }

            return(bResult);
        }