public override bool CreateInputNodeWithDataUpload(HEU_SessionBase session, int connectNodeID, GameObject inputObject, out int inputNodeID)
        {
            inputNodeID = HEU_Defines.HEU_INVALID_NODE_ID;
            if (!HEU_HAPIUtility.IsNodeValidInHoudini(session, connectNodeID))
            {
                Debug.LogError("Connection node is invalid.");
                return false;
            }

            HEU_InputDataTilemap inputTilemap = GenerateTilemapDataFromGameObject(inputObject);

            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))
            {
                Debug.LogError("Failed to create new input node in Houdini session!");
                return false;
            }

            inputNodeID = newNodeID;
            if (!session.CookNode(inputNodeID, false))
            {
                Debug.LogError("New input node failed to cook!");
                return false;
            }

            return UploadData(session, inputNodeID, inputTilemap);
        }
Ejemplo n.º 2
0
		/// <summary>
		/// Create the main heightfield network for input.
		/// </summary>
		/// <param name="session"></param>
		/// <param name="idt"></param>
		/// <returns>True if successfully created the network</returns>
		public bool CreateHeightFieldInputNode(HEU_SessionBase session, HEU_InputDataTerrain idt)
		{
			idt._heightfieldNodeID = HEU_Defines.HEU_INVALID_NODE_ID;
			idt._heightNodeID = HEU_Defines.HEU_INVALID_NODE_ID;
			idt._maskNodeID = HEU_Defines.HEU_INVALID_NODE_ID;
			idt._mergeNodeID = HEU_Defines.HEU_INVALID_NODE_ID;

			// Create the HeightField node network
			bool bResult = session.CreateHeightfieldInputNode(idt._parentNodeID, idt._heightFieldName, idt._numPointsX, idt._numPointsY, idt._voxelSize,
				out idt._heightfieldNodeID, out idt._heightNodeID, out idt._maskNodeID, out idt._mergeNodeID);
			if (!bResult 
				|| idt._heightfieldNodeID == HEU_Defines.HEU_INVALID_NODE_ID 
				|| idt._heightNodeID == HEU_Defines.HEU_INVALID_NODE_ID
				|| idt._maskNodeID == HEU_Defines.HEU_INVALID_NODE_ID 
				|| idt._mergeNodeID == HEU_Defines.HEU_INVALID_NODE_ID)
			{
				Debug.LogError("Failed to create new heightfield node in Houdini session!");
				return false;
			}

			if (!session.CookNode(idt._heightNodeID, false))
			{
				Debug.LogError("New input node failed to cook!");
				return false;
			}

			return true;
		}
	protected virtual bool CookNode(HEU_SessionBase session, HAPI_NodeId cookNodeID)
	{
	    // Cooking it will load the bgeo
	    if (!session.CookNode(cookNodeID, false))
	    {
		AppendLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Unable to cook node."));
		return false;
	    }

	    // Wait until cooking has finished
	    bool bResult = true;
	    HAPI_State statusCode = HAPI_State.HAPI_STATE_STARTING_LOAD;
	    while (bResult && statusCode > HAPI_State.HAPI_STATE_MAX_READY_STATE)
	    {
		bResult = session.GetCookState(out statusCode);

		Sleep();
	    }

	    // Check cook results for any errors
	    if (statusCode == HAPI_State.HAPI_STATE_READY_WITH_COOK_ERRORS || statusCode == HAPI_State.HAPI_STATE_READY_WITH_FATAL_ERRORS)
	    {
		string statusString = session.GetStatusString(HAPI_StatusType.HAPI_STATUS_COOK_RESULT, HAPI_StatusVerbosity.HAPI_STATUSVERBOSITY_ERRORS);
		AppendLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Cook failed: {0}.", statusString));
		return false;
	    }

	    return true;
	}
        /// <summary>
        /// Create the main heightfield network for input.
        /// </summary>
        /// <param name="session"></param>
        /// <param name="idt"></param>
        /// <returns>True if successfully created the network</returns>
        public bool CreateHeightFieldInputNode(HEU_SessionBase session, HEU_InputDataTerrain idt)
        {
            idt._heightfieldNodeID = HEU_Defines.HEU_INVALID_NODE_ID;
            idt._heightNodeID      = HEU_Defines.HEU_INVALID_NODE_ID;
            idt._maskNodeID        = HEU_Defines.HEU_INVALID_NODE_ID;
            idt._mergeNodeID       = HEU_Defines.HEU_INVALID_NODE_ID;
            idt._parentNodeID      = HEU_Defines.HEU_INVALID_NODE_ID; // Heightfields should have its own objects.

            // Create the HeightField node network
            bool bResult = session.CreateHeightFieldInput(idt._parentNodeID, idt._heightFieldName, idt._numPointsX, idt._numPointsY, idt._voxelSize,
                                                          HAPI_HeightFieldSampling.HAPI_HEIGHTFIELD_SAMPLING_CORNER,
                                                          out idt._heightfieldNodeID, out idt._heightNodeID, out idt._maskNodeID, out idt._mergeNodeID);

            if (!bResult ||
                idt._heightfieldNodeID == HEU_Defines.HEU_INVALID_NODE_ID ||
                idt._heightNodeID == HEU_Defines.HEU_INVALID_NODE_ID ||
                idt._maskNodeID == HEU_Defines.HEU_INVALID_NODE_ID ||
                idt._mergeNodeID == HEU_Defines.HEU_INVALID_NODE_ID)
            {
                HEU_Logger.LogError("Failed to create new heightfield node in Houdini session!");
                return(false);
            }

            if (!session.CookNode(idt._heightNodeID, false))
            {
                HEU_Logger.LogError("New input node failed to cook!");
                return(false);
            }

            return(true);
        }
Ejemplo n.º 5
0
		public void Initialize(HEU_SessionBase session, HAPI_ObjectInfo objectInfo, HAPI_Transform objectTranform, HEU_HoudiniAsset parentAsset)
		{
			_objectInfo = objectInfo;
			_objectTransform = objectTranform;
			_parentAsset = parentAsset;

			SyncWithObjectInfo(session);

			// Translate transform to Unity (TODO)

			List<HAPI_GeoInfo> geoInfos = new List<HAPI_GeoInfo>();

			// Get display geo info
			HAPI_GeoInfo displayGeoInfo = new HAPI_GeoInfo();
			if(!session.GetDisplayGeoInfo(_objectInfo.nodeId, ref displayGeoInfo))
			{
				return;
			}
			//Debug.LogFormat("Found geoinfo with name {0} and id {1}", HEU_SessionManager.GetString(displayGeoInfo.nameSH, session), displayGeoInfo.nodeId);
			geoInfos.Add(displayGeoInfo);
			
			// TODO: The following editable node query also retrieves geo nodes for terrain with visualization nodes. Need to review to check if we're using the
			// correct query flags, and handling returned nodes correctly.
			// Get editable nodes, cook em, then create geo nodes for them
			HAPI_NodeId[] editableNodes = null;
			HEU_SessionManager.GetComposedChildNodeList(session, _objectInfo.nodeId, (int)HAPI_NodeType.HAPI_NODETYPE_SOP, (int)HAPI_NodeFlags.HAPI_NODEFLAGS_EDITABLE, true, out editableNodes); 
			if(editableNodes != null)
			{
				foreach(HAPI_NodeId editNodeID in editableNodes)
				{
					if (editNodeID != displayGeoInfo.nodeId)
					{
						session.CookNode(editNodeID, HEU_PluginSettings.CookTemplatedGeos);

						HAPI_GeoInfo editGeoInfo = new HAPI_GeoInfo();
						if (session.GetGeoInfo(editNodeID, ref editGeoInfo))
						{
							geoInfos.Add(editGeoInfo);
						}
					}
				}
			}
			
			//Debug.LogFormat("Object id={5}, name={0}, isInstancer={1}, isInstanced={2}, instancePath={3}, instanceId={4}", 
			//	HEU_SessionManager.GetString(objectInfo.nameSH, session), objectInfo.isInstancer, objectInfo.isInstanced, 
			//	HEU_SessionManager.GetString(objectInfo.objectInstancePathSH, session), objectInfo.objectToInstanceId, objectInfo.nodeId);

			// Go through geo infos to create geometry
			int numGeoInfos = geoInfos.Count;
			for(int i = 0; i < numGeoInfos; ++i)
			{
				// Create GeoNode for each
				_geoNodes.Add(CreateGeoNode(session, geoInfos[i]));
			}

			// This has been moved to GenerateGeometry but kept here just in case.
			//ApplyObjectTransformToGeoNodes();
		}
Ejemplo n.º 6
0
        /// <summary>
        /// Cooks node and returns true if successfull.
        /// </summary>
        /// <param name="nodeID">The node to cook</param>
        /// <param name="bCookTemplatedGeos">Whether to cook templated geos</param>
        /// <returns>True if successfully cooked node</returns>
        public static bool CookNodeInHoudini(HEU_SessionBase session, HAPI_NodeId nodeID, bool bCookTemplatedGeos, string assetName)
        {
            bool bResult = session.CookNode(nodeID, bCookTemplatedGeos);

            if (bResult)
            {
                return(HEU_HAPIUtility.ProcessHoudiniCookStatus(session, assetName));
            }

            return(bResult);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Helper to set heightfield data for a specific volume node.
        /// Used for a specific terrain layer.
        /// </summary>
        /// <param name="session">Session that the volume node resides in.</param>
        /// <param name="volumeNodeID">ID of the target volume node</param>
        /// <param name="partID">Part ID</param>
        /// <param name="heightValues">Array of height or alpha values</param>
        /// <param name="heightFieldName">Name of the layer</param>
        /// <returns>True if successfully uploaded heightfield values</returns>
        public bool SetHeightFieldData(HEU_SessionBase session, HAPI_NodeId volumeNodeID, HAPI_PartId partID, float[] heightValues, string heightFieldName, ref HAPI_VolumeInfo baseVolumeInfo)
        {
            // Cook the node to get infos below
            if (!session.CookNode(volumeNodeID, false))
            {
                return(false);
            }

            // Get Geo, Part, and Volume infos
            HAPI_GeoInfo geoInfo = new HAPI_GeoInfo();

            if (!session.GetGeoInfo(volumeNodeID, ref geoInfo))
            {
                return(false);
            }

            HAPI_PartInfo partInfo = new HAPI_PartInfo();

            if (!session.GetPartInfo(geoInfo.nodeId, partID, ref partInfo))
            {
                return(false);
            }

            HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo();

            if (!session.GetVolumeInfo(volumeNodeID, partInfo.id, ref volumeInfo))
            {
                return(false);
            }

            volumeInfo.tileSize = 1;
            // Use same transform as base layer
            volumeInfo.transform = baseVolumeInfo.transform;

            if (!session.SetVolumeInfo(volumeNodeID, partInfo.id, ref volumeInfo))
            {
                Debug.LogError("Unable to set volume info on input heightfield node!");
                return(false);
            }

            // Now set the height data
            if (!session.SetHeightFieldData(geoInfo.nodeId, partInfo.id, heightFieldName, heightValues, 0, heightValues.Length))
            {
                Debug.LogErrorFormat("Unable to set `{0}` height values on input heightfield node!\n" +
                                     "Check your terrain sizes including Control Texture Resolution is less than the Heightmap Resolution.",
                                     heightFieldName);
                return(false);
            }

            return(true);
        }
Ejemplo n.º 8
0
		/// <summary>
		/// Creates a heightfield network inside the same object as connectNodeID.
		/// Uploads the terrain data from inputObject into the new heightfield network, incuding
		/// all terrain layers/alphamaps.
		/// </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 Terrain components</param>
		/// <param name="inputNodeID">The created heightfield network node ID</param>
		/// <returns>True if created network and uploaded heightfield 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))
			{
				Debug.LogError("Connection node is invalid.");
				return false;
			}

			HEU_InputDataTerrain idt = GenerateTerrainDataFromGameObject(inputObject);
			if (idt == null)
			{
				return false;
			}

			HAPI_NodeId parentNodeID = HEU_HAPIUtility.GetParentNodeID(session, connectNodeID);
			idt._parentNodeID = parentNodeID;

			if (!CreateHeightFieldInputNode(session, idt))
			{
				return false;
			}

			if (!UploadHeightValuesWithTransform(session, idt))
			{
				return false;
			}

			inputNodeID = idt._heightfieldNodeID;

			if (!UploadAlphaMaps(session, idt))
			{
				return false;
			}

			if (!session.CookNode(inputNodeID, false))
			{
				Debug.LogError("New input node failed to cook!");
				return false;
			}

			return true;
		}
Ejemplo n.º 9
0
		/// <summary>
		/// Helper to set heightfield data for a specific volume node.
		/// Used for a specific terrain layer.
		/// </summary>
		/// <param name="session">Session that the volume node resides in.</param>
		/// <param name="volumeNodeID">ID of the target volume node</param>
		/// <param name="partID">Part ID</param>
		/// <param name="heightValues">Array of height or alpha values</param>
		/// <param name="heightFieldName">Name of the layer</param>
		/// <returns>True if successfully uploaded heightfield values</returns>
		public bool SetHeightFieldData(HEU_SessionBase session, HAPI_NodeId volumeNodeID, HAPI_PartId partID, float[] heightValues, string heightFieldName)
		{
			// Cook the node to get infos below
			if (!session.CookNode(volumeNodeID, false))
			{
				return false;
			}

			// Get Geo, Part, and Volume infos
			HAPI_GeoInfo geoInfo = new HAPI_GeoInfo();
			if (!session.GetGeoInfo(volumeNodeID, ref geoInfo))
			{
				return false;
			}

			HAPI_PartInfo partInfo = new HAPI_PartInfo();
			if (!session.GetPartInfo(geoInfo.nodeId, partID, ref partInfo))
			{
				return false;
			}

			HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo();
			if (!session.GetVolumeInfo(volumeNodeID, partInfo.id, ref volumeInfo))
			{
				return false;
			}

			volumeInfo.tileSize = 1;

			if (!session.SetVolumeInfo(volumeNodeID, partInfo.id, ref volumeInfo))
			{
				Debug.LogError("Unable to set volume info on input heightfield node!");
				return false;
			}

			// Now set the height data
			if (!session.SetHeightFieldData(geoInfo.nodeId, partInfo.id, heightFieldName, heightValues, 0, heightValues.Length))
			{
				Debug.LogError("Unable to set height values on input heightfield node!");
				return false;
			}

			return true;
		}
Ejemplo n.º 10
0
		/// <summary>
		/// Create input node for the given inputObject, and upload its mesh data (along with LOD meshes).
		/// Outputs the inputNodeID if successfully uploaded mesh data and returns true.
		/// </summary>
		/// <param name="session">Session to create input node</param>
		/// <param name="assetID">The parent asset ID</param>
		/// <param name="inputObject">The input GameObject to query mesh data from</param>
		/// <param name="inputNodeID">Output of input node ID if successfully created</param>
		/// <returns>True if successfully created and uploaded mesh data</returns>
		public static bool CreateInputNodeWithGeoData(HEU_SessionBase session, HAPI_NodeId assetID, GameObject inputObject, out HAPI_NodeId inputNodeID)
		{
			inputNodeID = HEU_Defines.HEU_INVALID_NODE_ID;

			if (!HEU_HAPIUtility.IsAssetValidInHoudini(session, assetID))
			{
				return false;
			}

			bool bHasLODGroup = false;
			List<HEU_UploadMeshData> uploadMeshDatas = GenerateMeshDatasFromInputObject(inputObject, out bHasLODGroup);
			if (uploadMeshDatas == null || uploadMeshDatas.Count == 0)
			{
				return false;
			}

			// If connected asset is not valid, then need to create an input asset
			if (inputNodeID == HEU_Defines.HEU_INVALID_NODE_ID)
			{
				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.IsAssetValidInHoudini(session, newNodeID))
				{
					Debug.LogErrorFormat("Failed to create new input node in Houdini session!");
					return false;
				}

				inputNodeID = newNodeID;

				if (!session.CookNode(inputNodeID, false))
				{
					Debug.LogErrorFormat("New input node failed to cook!");
					return false;
				}
			}

			return UploadInputMeshData(session, inputNodeID, uploadMeshDatas, bHasLODGroup);
		}
Ejemplo n.º 11
0
		/// <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))
			{
				Debug.LogError("Connection node is invalid.");
				return false;
			}

			// Get upload meshes from input object
			HEU_InputDataMeshes inputMeshes = GenerateMeshDatasFromGameObject(inputObject);
			if (inputMeshes == null || inputMeshes._inputMeshes == null || inputMeshes._inputMeshes.Count == 0)
			{
				Debug.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))
			{
				Debug.LogError("Failed to create new input node in Houdini session!");
				return false;
			}

			inputNodeID = newNodeID;

			if (!session.CookNode(inputNodeID, false))
			{
				Debug.LogError("New input node failed to cook!");
				return false;
			}

			return UploadData(session, inputNodeID, inputMeshes);
		}
	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;
	}
Ejemplo n.º 13
0
        /// <summary>
        /// Creates a heightfield network inside the same object as connectNodeID.
        /// Uploads the terrain data from inputObject into the new heightfield network, incuding
        /// all terrain layers/alphamaps.
        /// </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 Terrain components</param>
        /// <param name="inputNodeID">The created heightfield network node ID</param>
        /// <returns>True if created network and uploaded heightfield 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))
            {
                Debug.LogError("Connection node is invalid.");
                return(false);
            }

            HEU_InputDataTerrain idt = GenerateTerrainDataFromGameObject(inputObject);

            if (idt == null)
            {
                return(false);
            }

            HAPI_NodeId parentNodeID = HEU_HAPIUtility.GetParentNodeID(session, connectNodeID);

            idt._parentNodeID = parentNodeID;

            if (!CreateHeightFieldInputNode(session, idt))
            {
                return(false);
            }

            HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo();

            if (!UploadHeightValuesWithTransform(session, idt, ref volumeInfo))
            {
                return(false);
            }

            inputNodeID = idt._heightfieldNodeID;

            bool bMaskSet = false;

            if (!UploadAlphaMaps(session, idt, ref volumeInfo, out bMaskSet))
            {
                return(false);
            }

            if (!bMaskSet)
            {
                // While the default HF created by the input node also creates a default mask layer,
                // we still need to set the mask layer's transform. So this uses the base VolumeInfo
                // to do just that.
                if (!SetMaskLayer(session, idt, ref volumeInfo))
                {
                    return(false);
                }
            }

            if (!session.CookNode(inputNodeID, false))
            {
                Debug.LogError("New input node failed to cook!");
                return(false);
            }

            return(true);
        }
Ejemplo n.º 14
0
	// This is the old way of getting outputs. Keep it for now for legacy. TODO: Remove this later
	internal void GatherAllAssetOutputsLegacy(HEU_SessionBase session, HAPI_ObjectInfo objectInfo, bool bUseOutputNodes, ref List<HEU_GeoNode> geoNodes)
	{

	    List<HAPI_GeoInfo> geoInfos = new List<HAPI_GeoInfo>();

	    // Get display geo info
	    HAPI_GeoInfo displayGeoInfo = new HAPI_GeoInfo();
	    if (!session.GetDisplayGeoInfo(objectInfo.nodeId, ref displayGeoInfo))
	    {
		return;
	    }
	    //HEU_Logger.LogFormat("Found geoinfo with name {0} and id {1}", HEU_SessionManager.GetString(displayGeoInfo.nameSH, session), displayGeoInfo.nodeId);
	    geoInfos.Add(displayGeoInfo);

	    if (bUseOutputNodes)
	    {

		int outputCount = 0;
		if (!session.GetOutputGeoCount(objectInfo.nodeId, out outputCount))
		{
		    outputCount = 0;
		}

		if (outputCount > 0)
		{
		    HAPI_GeoInfo[] outputGeoInfos = new HAPI_GeoInfo[outputCount];
		    if (!session.GetOutputGeoInfos(objectInfo.nodeId, ref outputGeoInfos, outputCount))
		    {
			outputGeoInfos = new HAPI_GeoInfo[0];
		    }

		    foreach (HAPI_GeoInfo geoInfo in outputGeoInfos)
		    {
			if (geoInfo.nodeId == displayGeoInfo.nodeId)
			{
			    continue;
			}

			bool bValidOutput = true;
			int parentId = HEU_HAPIUtility.GetParentNodeID(session, geoInfo.nodeId);
			while (parentId >= 0)
			{
			    if (parentId == geoInfo.nodeId)
			    {
				    // This output node is inside the display geo
				    // Do not use this output to avoid duplicates
				    bValidOutput = false;
				    break;
			    }

			    parentId = HEU_HAPIUtility.GetParentNodeID(session, parentId);
			}

			if (bValidOutput)
			{
			    // Need to cook output geometry to get their parts
			    HAPI_GeoInfo cookedGeoInfo = new HAPI_GeoInfo();
			    session.CookNode(geoInfo.nodeId, HEU_PluginSettings.CookTemplatedGeos);
			    
			    // Get the refreshed geo info
			    if (session.GetGeoInfo(geoInfo.nodeId, ref cookedGeoInfo))
			    {
				geoInfos.Add(cookedGeoInfo);
			    }

			}
		    }
		}
	    }


	    // Get editable nodes, cook em, then create geo nodes for them
	    HAPI_NodeId[] editableNodes = null;
	    HEU_SessionManager.GetComposedChildNodeList(session, objectInfo.nodeId, (int)HAPI_NodeType.HAPI_NODETYPE_SOP, (int)HAPI_NodeFlags.HAPI_NODEFLAGS_EDITABLE, true, out editableNodes);
	    if (editableNodes != null)
	    {
		foreach (HAPI_NodeId editNodeID in editableNodes)
		{
		    if (editNodeID != displayGeoInfo.nodeId)
		    {
			session.CookNode(editNodeID, HEU_PluginSettings.CookTemplatedGeos);

			HAPI_GeoInfo editGeoInfo = new HAPI_GeoInfo();
			if (session.GetGeoInfo(editNodeID, ref editGeoInfo))
			{
			    geoInfos.Add(editGeoInfo);
			}
		    }
		}
	    }

	    //HEU_Logger.LogFormat("Object id={5}, name={0}, isInstancer={1}, isInstanced={2}, instancePath={3}, instanceId={4}", 
	    //	HEU_SessionManager.GetString(objectInfo.nameSH, session), objectInfo.isInstancer, objectInfo.isInstanced, 
	    //	HEU_SessionManager.GetString(objectInfo.objectInstancePathSH, session), objectInfo.objectToInstanceId, objectInfo.nodeId);

	    // Go through geo infos to create geometry
	    int numGeoInfos = geoInfos.Count;
	    for (int i = 0; i < numGeoInfos; ++i)
	    {
		// Create GeoNode for each
		geoNodes.Add(CreateGeoNode(session, geoInfos[i]));
	    }
	}
	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;
	}
	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;
	}
Ejemplo n.º 18
0
	/// <summary>
	/// Retrieves object info from Houdini session and updates internal state.
	/// New geo nodes are created, unused geo nodes are destroyed.
	/// Geo nodes are then refreshed to be in sync with Houdini session.
	/// </summary>
	/// <returns>True if internal state has changed (including geometry).</returns>
	public void UpdateObject(HEU_SessionBase session, bool bForceUpdate)
	{
	    // Update the geo info
	    if (!session.GetObjectInfo(ObjectID, ref _objectInfo))
	    {
		return;
	    }
	    SyncWithObjectInfo(session);

	    // Update the object transform
	    _objectTransform = ParentAsset.GetObjectTransform(session, ObjectID);

	    // Container for existing geo nodes that are still in use
	    List<HEU_GeoNode> geoNodesToKeep = new List<HEU_GeoNode>();

	    // Container for new geo infos that need to be created
	    List<HAPI_GeoInfo> newGeoInfosToCreate = new List<HAPI_GeoInfo>();

	    if (_objectInfo.haveGeosChanged || bForceUpdate)
	    {
		// Indicates that the geometry nodes have changed
		//Debug.Log("Geos have changed!");

		// Form a list of geo infos that are now present after cooking
		List<HAPI_GeoInfo> postCookGeoInfos = new List<HAPI_GeoInfo>();

		// Get the display geo info
		HAPI_GeoInfo displayGeoInfo = new HAPI_GeoInfo();
		if (session.GetDisplayGeoInfo(_objectInfo.nodeId, ref displayGeoInfo, false))
		{
		    postCookGeoInfos.Add(displayGeoInfo);
		}
		else
		{
		    displayGeoInfo.nodeId = HEU_Defines.HEU_INVALID_NODE_ID;
		}

		// Get editable nodes, cook em, then create geo nodes for them
		HAPI_NodeId[] editableNodes = null;
		HEU_SessionManager.GetComposedChildNodeList(session, _objectInfo.nodeId, (int)HAPI_NodeType.HAPI_NODETYPE_SOP, (int)HAPI_NodeFlags.HAPI_NODEFLAGS_EDITABLE, true, out editableNodes);
		if (editableNodes != null)
		{
		    foreach (HAPI_NodeId editNodeID in editableNodes)
		    {
			if (editNodeID != displayGeoInfo.nodeId)
			{
			    session.CookNode(editNodeID, HEU_PluginSettings.CookTemplatedGeos);

			    HAPI_GeoInfo editGeoInfo = new HAPI_GeoInfo();
			    if (session.GetGeoInfo(editNodeID, ref editGeoInfo))
			    {
				postCookGeoInfos.Add(editGeoInfo);
			    }
			}
		    }
		}

		// Now for each geo node that are present after cooking, we check if its
		// new or whether we already have it prior to cooking.
		int numPostCookGeoInfos = postCookGeoInfos.Count;
		for (int i = 0; i < numPostCookGeoInfos; i++)
		{
		    bool bFound = false;
		    for (int j = 0; j < _geoNodes.Count; j++)
		    {
			string geoName = HEU_SessionManager.GetString(postCookGeoInfos[i].nameSH, session);
			if (geoName.Equals(_geoNodes[j].GeoName))
			{
			    _geoNodes[j].SetGeoInfo(postCookGeoInfos[i]);

			    geoNodesToKeep.Add(_geoNodes[j]);
			    _geoNodes.RemoveAt(j);

			    bFound = true;
			    break;
			}
		    }

		    if (!bFound)
		    {
			newGeoInfosToCreate.Add(postCookGeoInfos[i]);
		    }
		}

		// Whatever is left in _geoNodes is no longer needed so clean up
		int numCurrentGeos = _geoNodes.Count;
		for (int i = 0; i < numCurrentGeos; ++i)
		{
		    _geoNodes[i].DestroyAllData();
		}
	    }
	    else
	    {
		Debug.Assert(_objectInfo.geoCount == _geoNodes.Count, "Expected same number of geometry nodes.");
	    }

	    // Go through the old geo nodes that are still in use and update if necessary.
	    foreach (HEU_GeoNode geoNode in geoNodesToKeep)
	    {
		// Get geo info and check if geo changed
		bool bGeoChanged = bForceUpdate || geoNode.HasGeoNodeChanged(session);
		if (bGeoChanged)
		{
		    geoNode.UpdateGeo(session);
		}
		else
		{
		    if (_objectInfo.haveGeosChanged)
		    {
			// Clear object instances since the object info has changed.
			// Without this, the object instances were never getting updated
			// if only the inputs changed but not outputs (of instancers).
			geoNode.ClearObjectInstances();
		    }

		    // Visiblity might have changed, so update that
		    geoNode.CalculateVisiblity(IsVisible());
		    geoNode.CalculateColliderState();
		}
	    }

	    // Create the new geo infos and add to our keep list
	    foreach (HAPI_GeoInfo newGeoInfo in newGeoInfosToCreate)
	    {
		geoNodesToKeep.Add(CreateGeoNode(session, newGeoInfo));
	    }

	    // Overwrite the old list with new
	    _geoNodes = geoNodesToKeep;

	    // Updating the trasform is done in GenerateGeometry
	}
	/// <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;
	}