/// <summary>
        /// Returns true if any of the geo data has changed and
        /// therefore requires regeneration.
        /// </summary>
        /// <returns>True if changes occurred internal to geo data</returns>
        public bool HasGeoNodeChanged(HEU_SessionBase session)
        {
            // Note: _geoInfo.hasMaterialChanged has been deprecated so we're not checking that

            if (!session.GetGeoInfo(GeoID, ref _geoInfo))
            {
                return(false);
            }
            else if (_geoInfo.type == HAPI_GeoType.HAPI_GEOTYPE_INPUT)
            {
                return((_inputNode != null) ? _inputNode.RequiresCook : false);
            }
            else if (_geoInfo.isTemplated && !HEU_PluginSettings.CookTemplatedGeos && !_geoInfo.isEditable)
            {
                return(false);
            }
            else if (!_geoInfo.hasGeoChanged)
            {
                return(false);
            }
            // Commented out to allow non-display geo to be updated
            //else if (!_geoInfo.isDisplayGeo && (_geoInfo.type != HAPI_GeoType.HAPI_GEOTYPE_CURVE && !HEU_PluginSettings.CookTemplatedGeos && _geoInfo.isTemplated))
            //{
            //	return false;
            //}

            return(true);
        }
Esempio n. 2
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();
		}
Esempio n. 3
0
		/// <summary>
		/// Gets the group names for given group type.
		/// </summary>
		/// <param name="nodeID">The node ID</param>
		/// <param name="groupType">The group type to query</param>
		/// <returns>Populated array of string names, or null if failed</returns>
		public static string[] GetGroupNames(HAPI_NodeId nodeID, HAPI_PartId partID, HAPI_GroupType groupType, bool isInstanced)
		{
			HEU_SessionBase session = GetOrCreateDefaultSession();
			if (session != null)
			{
				HAPI_GeoInfo geoInfo = new HAPI_GeoInfo();
				if (session.GetGeoInfo(nodeID, ref geoInfo))
				{
					int groupCount = 0;

					if(!isInstanced)
					{
						groupCount = geoInfo.getGroupCountByType(groupType); ;
					}
					else
					{
						int pointGroupCount = 0;
						int primGroupCount = 0;
						if (session.GetGroupCountOnPackedInstancePart(nodeID, partID, out pointGroupCount, out primGroupCount))
						{
							groupCount = (groupType == HAPI_GroupType.HAPI_GROUPTYPE_POINT) ? pointGroupCount : primGroupCount;
						}
					}

					if(groupCount <= 0)
					{
						return null;
					}

					int[] groupNames = new int[groupCount];
					bool bSuccess = false;
					if(!isInstanced)
					{
						bSuccess = session.GetGroupNames(nodeID, groupType, ref groupNames, groupCount);
					}
					else
					{
						bSuccess = session.GetGroupNamesOnPackedInstancePart(nodeID, partID, groupType, ref groupNames, groupCount);
					}

					if (bSuccess)
					{
						string[] nameStrings = new string[groupCount];
						for (int i = 0; i < groupCount; ++i)
						{
							nameStrings[i] = GetString(groupNames[i]);
						}
						return nameStrings;
					}
				}
			}
			return null;
		}
        /// <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);
        }
Esempio n. 5
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;
		}
Esempio n. 6
0
		/// <summary>
		/// Gets the group names for given group type.
		/// </summary>
		/// <param name="nodeID">The node ID</param>
		/// <param name="groupType">The group type to query</param>
		/// <returns>Populated array of string names, or null if failed</returns>
		public static string[] GetGroupNames(HAPI_NodeId nodeID, HAPI_GroupType groupType)
		{
			HEU_SessionBase sessionBase = GetOrCreateDefaultSession();
			if (sessionBase != null)
			{
				HAPI_GeoInfo geoInfo = new HAPI_GeoInfo();
				if (sessionBase.GetGeoInfo(nodeID, ref geoInfo))
				{
					int count = geoInfo.getGroupCountByType(groupType);
					int[] names = new int[count];
					if (sessionBase.GetGroupNames(nodeID, groupType, ref names, count))
					{
						string[] nameStrings = new string[count];
						for (int i = 0; i < count; ++i)
						{
							nameStrings[i] = GetString(names[i]);
						}
						return nameStrings;
					}
				}
			}
			return null;
		}
Esempio n. 7
0
		public bool UploadAttributeViaMeshInput(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID)
		{
			// Need to upload same geometry as in the original Editable node, and with custom attribute values.

			// First get the current geometry info and data.

			HAPI_GeoInfo geoInfo = new HAPI_GeoInfo();
			if(!session.GetGeoInfo(geoID, ref geoInfo))
			{
				return false;
			}

			HAPI_PartInfo oldPartInfo = new HAPI_PartInfo();
			if(!session.GetPartInfo(geoID, partID, ref oldPartInfo))
			{
				return false;
			}

			int pointCount = oldPartInfo.pointCount;
			int vertexCount = oldPartInfo.vertexCount;
			int faceCount = oldPartInfo.faceCount;

			// Get facecounts
			int[] faceCountData = new int[faceCount];
			if(!HEU_GeneralUtility.GetArray2Arg(geoID, partID, session.GetFaceCounts, faceCountData, 0, faceCount))
			{
				return false;
			}

			// Get indices
			int[] vertexList = new int[vertexCount];
			if (!HEU_GeneralUtility.GetArray2Arg(geoID, partID, session.GetVertexList, vertexList, 0, vertexCount))
			{
				return false;
			}

			List<HEU_AttributeData> pointAttributeDatas = new List<HEU_AttributeData>();
			List<HEU_AttributeData> vertexAttributeDatas = new List<HEU_AttributeData>();
			List<HEU_AttributeData> primitiveAttributeDatas = new List<HEU_AttributeData>();
			List<HEU_AttributeData> detailAttributeDatas = new List<HEU_AttributeData>();

			// Get all attributes, including editted
			GetAttributesList(session, geoID, partID, pointAttributeDatas, HAPI_AttributeOwner.HAPI_ATTROWNER_POINT, oldPartInfo.pointAttributeCount);
			GetAttributesList(session, geoID, partID, vertexAttributeDatas, HAPI_AttributeOwner.HAPI_ATTROWNER_VERTEX, oldPartInfo.vertexAttributeCount);
			GetAttributesList(session, geoID, partID, primitiveAttributeDatas, HAPI_AttributeOwner.HAPI_ATTROWNER_PRIM, oldPartInfo.primitiveAttributeCount);
			GetAttributesList(session, geoID, partID, detailAttributeDatas, HAPI_AttributeOwner.HAPI_ATTROWNER_DETAIL, oldPartInfo.detailAttributeCount);

			// Now create new geometry info and populate it

			HAPI_PartInfo newPartInfo = new HAPI_PartInfo();
			newPartInfo.faceCount = faceCount;
			newPartInfo.vertexCount = vertexCount;
			newPartInfo.pointCount = pointCount;
			newPartInfo.pointAttributeCount = oldPartInfo.pointAttributeCount;
			newPartInfo.vertexAttributeCount = oldPartInfo.vertexAttributeCount;
			newPartInfo.primitiveAttributeCount = oldPartInfo.primitiveAttributeCount;
			newPartInfo.detailAttributeCount = oldPartInfo.detailAttributeCount;

			int newPartID = partID;

			if (!session.SetPartInfo(geoID, newPartID, ref newPartInfo))
			{
				return false;
			}

			if (!HEU_GeneralUtility.SetArray2Arg(geoID, newPartID, session.SetFaceCount, faceCountData, 0, newPartInfo.faceCount))
			{
				return false;
			}

			if (!HEU_GeneralUtility.SetArray2Arg(geoID, newPartID, session.SetVertexList, vertexList, 0, newPartInfo.vertexCount))
			{
				return false;
			}

			// Upload all attributes, include editted
			UpdateAttributeList(session, geoID, partID, pointAttributeDatas);
			UpdateAttributeList(session, geoID, partID, vertexAttributeDatas);
			UpdateAttributeList(session, geoID, partID, primitiveAttributeDatas);
			UpdateAttributeList(session, geoID, partID, detailAttributeDatas);

			return session.CommitGeo(geoID);
		}
Esempio n. 8
0
		public void SyncAllAttributesFrom(HEU_SessionBase session, HEU_HoudiniAsset asset, HAPI_NodeId geoID, ref HAPI_PartInfo partInfo, GameObject outputGameObject)
		{
			_geoID = geoID;
			_partID = partInfo.id;

			HAPI_GeoInfo geoInfo = new HAPI_GeoInfo();
			if(session.GetGeoInfo(_geoID, ref geoInfo))
			{
				_geoName = HEU_SessionManager.GetString(geoInfo.nameSH, session);
			}

			if (outputGameObject != null)
			{
				_outputTransform = outputGameObject.transform;
			}

			// Need the vertex list of indices to map the positions to vertex colors
			_vertexIndices = new int[partInfo.vertexCount];
			if (!HEU_GeneralUtility.GetArray2Arg(geoID, partInfo.id, session.GetVertexList, _vertexIndices, 0, partInfo.vertexCount))
			{
				return;
			}

			// Note that this currently only supports point attributes
			int attributePointCount = partInfo.attributeCounts[(int)HAPI_AttributeOwner.HAPI_ATTROWNER_POINT];
			string[] pointAttributeNames = new string[attributePointCount];
			if(!session.GetAttributeNames(geoID, partInfo.id, HAPI_AttributeOwner.HAPI_ATTROWNER_POINT, ref pointAttributeNames, attributePointCount))
			{
				Debug.LogErrorFormat("Failed to sync attributes. Unable to retrieve attribute names.");
				return;
			}

			// Create new list of attributes. We'll move existing attributes that are still in use as we find them.
			List<HEU_AttributeData> newAttributeDatas = new List<HEU_AttributeData>();

			foreach (string pointAttributeName in pointAttributeNames)
			{
				if(string.IsNullOrEmpty(pointAttributeName))
				{
					continue;
				}

				// Get position attribute values separately. Used for painting and editing points in 3D scene.
				HAPI_AttributeInfo pointAttributeInfo = new HAPI_AttributeInfo();
				if(session.GetAttributeInfo(geoID, partInfo.id, pointAttributeName, HAPI_AttributeOwner.HAPI_ATTROWNER_POINT, ref pointAttributeInfo))
				{
					if (pointAttributeName.Equals(HEU_Defines.HAPI_ATTRIB_POSITION))
					{
						if (pointAttributeInfo.storage != HAPI_StorageType.HAPI_STORAGETYPE_FLOAT)
						{
							Debug.LogErrorFormat("Expected float type for position attribute, but got {0}", pointAttributeInfo.storage);
							return;
						}

						_positionAttributeValues = new Vector3[pointAttributeInfo.count];
						float[] data = new float[0];
						HEU_GeneralUtility.GetAttribute(session, geoID, partInfo.id, pointAttributeName, ref pointAttributeInfo, ref data, session.GetAttributeFloatData);
						for (int i = 0; i < pointAttributeInfo.count; ++i)
						{
							_positionAttributeValues[i] = new Vector3(-data[i * pointAttributeInfo.tupleSize + 0], data[i * pointAttributeInfo.tupleSize + 1], data[i * pointAttributeInfo.tupleSize + 2]);
						}

						// We don't let position attributes be editted (for now anyway)
						continue;
					}


					HEU_AttributeData attrData = GetAttributeData(pointAttributeName);
					if (attrData == null)
					{
						// Attribute data not found. Create it.

						attrData = CreateAttribute(pointAttributeName, ref pointAttributeInfo);
						//Debug.LogFormat("Created attribute data: {0}", pointAttributeName);
					}

					// Add to new list.
					newAttributeDatas.Add(attrData);

					// Sync the attribute info to data.
					PopulateAttributeData(session, geoID, partInfo.id, attrData, ref pointAttributeInfo);

					if(pointAttributeName.Equals(HEU_Defines.HAPI_ATTRIB_COLOR) || pointAttributeInfo.typeInfo == HAPI_AttributeTypeInfo.HAPI_ATTRIBUTE_TYPE_COLOR)
					{
						_hasColorAttribute = true;
					}
				}
				else
				{
					// Failed to get point attribute info!
				}
			}

			// Overwriting the old list with the new should automatically remove unused attribute datas.
			_attributeDatas = newAttributeDatas;
		}
Esempio n. 9
0
		/// <summary>
		/// Upload the base height layer into heightfield network.
		/// </summary>
		/// <param name="session"></param>
		/// <param name="idt"></param>
		/// <returns></returns>
		public bool UploadHeightValuesWithTransform(HEU_SessionBase session, HEU_InputDataTerrain idt)
		{
			// Get Geo, Part, and Volume infos
			HAPI_GeoInfo geoInfo = new HAPI_GeoInfo();
			if (!session.GetGeoInfo(idt._heightNodeID, ref geoInfo))
			{
				Debug.LogError("Unable to get geo info from heightfield node!");
				return false;
			}

			HAPI_PartInfo partInfo = new HAPI_PartInfo();
			if (!session.GetPartInfo(geoInfo.nodeId, 0, ref partInfo))
			{
				Debug.LogError("Unable to get part info from heightfield node!");
				return false;
			}

			HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo();
			if (!session.GetVolumeInfo(idt._heightNodeID, 0, ref volumeInfo))
			{
				Debug.LogError("Unable to get volume info from heightfield node!");
				return false;
			}

			if (volumeInfo.xLength != Mathf.RoundToInt(idt._numPointsX / idt._voxelSize)
				|| volumeInfo.yLength != Mathf.RoundToInt(idt._numPointsY / idt._voxelSize)
				|| idt._terrainData.heightmapResolution != volumeInfo.xLength
				|| idt._terrainData.heightmapResolution != volumeInfo.yLength)
			{
				Debug.LogError("Created heightfield in Houdini differs in voxel size from input terrain!");
				return false;
			}

			// Update volume infos, and set it. This is required.
			volumeInfo.tileSize = 1;
			volumeInfo.type = HAPI_VolumeType.HAPI_VOLUMETYPE_HOUDINI;
			volumeInfo.storage = HAPI_StorageType.HAPI_STORAGETYPE_FLOAT;
			volumeInfo.transform = idt._transform;

			volumeInfo.minX = 0;
			volumeInfo.minY = 0;
			volumeInfo.minZ = 0;

			volumeInfo.tupleSize = 1;
			volumeInfo.tileSize = 1;

			volumeInfo.hasTaper = false;
			volumeInfo.xTaper = 0f;
			volumeInfo.yTaper = 0f;

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

			// Now set the height data
			float[,] heights = idt._terrainData.GetHeights(0, 0, volumeInfo.xLength, volumeInfo.yLength);
			int sizeX = heights.GetLength(0);
			int sizeY = heights.GetLength(1);
			int totalSize = sizeX * sizeY;

			// Convert to single array
			float[] heightsArr = new float[totalSize];
			for (int j = 0; j < sizeY; j++)
			{
				for (int i = 0; i < sizeX; i++)
				{
					// Flip for coordinate system change
					float h = heights[i, (sizeY - j - 1)];

					heightsArr[i + j * sizeX] = h * idt._heightScale;
				}
			}

			// Set the base height layer
			if (!session.SetHeightFieldData(idt._heightNodeID, 0, "height", heightsArr, 0, totalSize))
			{
				Debug.LogError("Unable to set height values on input heightfield node!");
				return false;
			}

			if (!session.CommitGeo(idt._heightNodeID))
			{
				Debug.LogError("Unable to commit geo on input heightfield node!");
				return false;
			}

			return true;
		}
Esempio n. 10
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
	}
Esempio n. 11
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]));
	    }
	}
        /// <summary>
        /// Upload the base height layer into heightfield network.
        /// </summary>
        /// <param name="session"></param>
        /// <param name="idt"></param>
        /// <returns></returns>
        public bool UploadHeightValuesWithTransform(HEU_SessionBase session, HEU_InputDataTerrain idt, ref HAPI_VolumeInfo volumeInfo)
        {
            // Get Geo, Part, and Volume infos
            HAPI_GeoInfo geoInfo = new HAPI_GeoInfo();

            if (!session.GetGeoInfo(idt._heightNodeID, ref geoInfo))
            {
                HEU_Logger.LogError("Unable to get geo info from heightfield node!");
                return(false);
            }

            HAPI_PartInfo partInfo = new HAPI_PartInfo();

            if (!session.GetPartInfo(geoInfo.nodeId, 0, ref partInfo))
            {
                HEU_Logger.LogError("Unable to get part info from heightfield node!");
                return(false);
            }

            volumeInfo = new HAPI_VolumeInfo();
            if (!session.GetVolumeInfo(idt._heightNodeID, 0, ref volumeInfo))
            {
                HEU_Logger.LogError("Unable to get volume info from heightfield node!");
                return(false);
            }

            if ((volumeInfo.xLength - 1) != Mathf.RoundToInt(idt._numPointsX / idt._voxelSize) ||
                (volumeInfo.yLength - 1) != Mathf.RoundToInt(idt._numPointsY / idt._voxelSize) ||
                idt._terrainData.heightmapResolution != volumeInfo.xLength ||
                idt._terrainData.heightmapResolution != volumeInfo.yLength)
            {
                HEU_Logger.LogWarning("Created heightfield in Houdini differs in voxel size from input terrain! Terrain may require resampling.");
            }

            // Update volume infos, and set it. This is required.
            volumeInfo.tileSize  = 1;
            volumeInfo.type      = HAPI_VolumeType.HAPI_VOLUMETYPE_HOUDINI;
            volumeInfo.storage   = HAPI_StorageType.HAPI_STORAGETYPE_FLOAT;
            volumeInfo.transform = idt._transform;

            volumeInfo.minX = 0;
            volumeInfo.minY = 0;
            volumeInfo.minZ = 0;

            volumeInfo.tupleSize = 1;
            volumeInfo.tileSize  = 1;

            volumeInfo.hasTaper = false;
            volumeInfo.xTaper   = 0f;
            volumeInfo.yTaper   = 0f;

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

            // Now set the height data
            float[,] heights = idt._terrainData.GetHeights(0, 0, idt._terrainData.heightmapResolution, idt._terrainData.heightmapResolution);
            int sizeX     = heights.GetLength(0);
            int sizeY     = heights.GetLength(1);
            int totalSize = sizeX * sizeY;

            // Convert to single array
            float[] heightsArr = new float[totalSize];
            for (int j = 0; j < sizeY; j++)
            {
                for (int i = 0; i < sizeX; i++)
                {
                    // Flip for coordinate system change
                    float h = heights[i, (sizeY - j - 1)];

                    heightsArr[i + j * sizeX] = h * idt._heightScale;
                }
            }

            if (volumeInfo.xLength != volumeInfo.yLength)
            {
                HEU_Logger.LogError("Error: Houdini heightmap must be square!");
                return(false);
            }

            if (idt._terrainData.heightmapResolution != volumeInfo.xLength)
            {
                // Resize heightsArr to idt._terrainData.heightmapResolution
                HEU_Logger.LogWarningFormat("Attempting to resize landscape from ({0}x{1}) to ({2}x{3})", idt._terrainData.heightmapResolution, idt._terrainData.heightmapResolution, volumeInfo.xLength, volumeInfo.xLength);
                heightsArr = HEU_TerrainUtility.ResampleData(heightsArr, idt._terrainData.heightmapResolution, idt._terrainData.heightmapResolution, volumeInfo.xLength, volumeInfo.xLength);
                sizeX      = volumeInfo.xLength;
                sizeY      = volumeInfo.yLength;
                totalSize  = sizeX * sizeY;
            }

            // Set the base height layer
            if (!session.SetHeightFieldData(idt._heightNodeID, 0, HEU_Defines.HAPI_HEIGHTFIELD_LAYERNAME_HEIGHT, heightsArr, 0, totalSize))
            {
                HEU_Logger.LogError("Unable to set height values on input heightfield node!");
                return(false);
            }

            SetTerrainDataAttributesToHeightField(session, geoInfo.nodeId, 0, idt._terrainData);

            SetTreePrototypes(session, geoInfo.nodeId, 0, idt._terrainData);

            if (!session.CommitGeo(idt._heightNodeID))
            {
                HEU_Logger.LogError("Unable to commit geo on input heightfield node!");
                return(false);
            }

            return(true);
        }
Esempio n. 13
0
		public static HEU_GenerateGeoCache GetPopulatedGeoCache(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID)
		{
#if HEU_PROFILER_ON
			float generateGeoCacheStartTime = Time.realtimeSinceStartup;
#endif

			HEU_GenerateGeoCache geoCache = new HEU_GenerateGeoCache();

			Debug.Assert(geoID != HEU_Defines.HEU_INVALID_NODE_ID, "Invalid Geo ID! Unable to update materials!");
			Debug.Assert(partID != HEU_Defines.HEU_INVALID_NODE_ID, "Invalid Part ID! Unable to update materials!");

			geoCache._geoInfo = new HAPI_GeoInfo();
			if (!session.GetGeoInfo(geoID, ref geoCache._geoInfo))
			{
				return null;
			}

			geoCache._partInfo = new HAPI_PartInfo();
			if (!session.GetPartInfo(geoID, partID, ref geoCache._partInfo))
			{
				return null;
			}

			geoCache._partName = HEU_SessionManager.GetString(geoCache._partInfo.nameSH, session);

			// Unity max indices limitation!
#if UNITY_2017_3_OR_NEWER
			uint UNITY_MAX_VERTS = uint.MaxValue;
#else
			uint UNITY_MAX_VERTS = ushort.MaxValue;
#endif
			uint maxVertexCount = Convert.ToUInt32(geoCache._partInfo.vertexCount);
			if (maxVertexCount > UNITY_MAX_VERTS)
			{
				Debug.LogErrorFormat("Part {0} has vertex count of {1} which is above Unity maximum of {2}.\nUse Unity 2017.3+ or reduce this in Houdini.",
					geoCache._partName, maxVertexCount, UNITY_MAX_VERTS);
				return null;
			}

			geoCache._vertexList = new int[geoCache._partInfo.vertexCount];
			if (!HEU_GeneralUtility.GetArray2Arg(geoID, partID, session.GetVertexList, geoCache._vertexList, 0, geoCache._partInfo.vertexCount))
			{
				return null;
			}

			geoCache._houdiniMaterialIDs = new HAPI_NodeId[geoCache._partInfo.faceCount];
			if (!session.GetMaterialNodeIDsOnFaces(geoID, partID, ref geoCache._singleFaceHoudiniMaterial, geoCache._houdiniMaterialIDs, geoCache._partInfo.faceCount))
			{
				return null;
			}

			geoCache.PopulateUnityMaterialData(session);

			if (!geoCache.PopulateGeometryData(session))
			{
				return null;
			}

#if HEU_PROFILER_ON
			Debug.LogFormat("GENERATE GEO CACHE TIME:: {0}", (Time.realtimeSinceStartup - generateGeoCacheStartTime));
#endif

			return geoCache;
		}