private bool LoadLayerFloatFromAttribute(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_NodeId partID, string attrName, ref float floatValue)
		{
			HAPI_AttributeInfo attrInfo = new HAPI_AttributeInfo();
			float[] attrValues = new float[0];
			HEU_GeneralUtility.GetAttribute(session, geoID, partID, attrName, ref attrInfo, ref attrValues, session.GetAttributeFloatData);
			if (attrValues != null && attrValues.Length > 0)
			{
				floatValue = attrValues[0];
				return true;
			}
			return false;
		}
Ejemplo n.º 2
0
		private void LoadLayerVector2FromAttribute(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_NodeId partID, string attrName, ref Vector2 vectorValue)
		{
			HAPI_AttributeInfo attrInfo = new HAPI_AttributeInfo();
			float[] attrValues = new float[0];
			HEU_GeneralUtility.GetAttribute(session, geoID, partID, attrName, ref attrInfo, ref attrValues, session.GetAttributeFloatData);
			if (attrValues != null && attrValues.Length == 2)
			{
				if (attrInfo.tupleSize == 2)
				{
					vectorValue[0] = attrValues[0];
					vectorValue[1] = attrValues[1];
				}
			}
		}
		/// <summary>
		/// Retrieve and set the detail properties from the specified heightfield.
		/// This includes detail distance, density, and resolution per patch.
		/// </summary>
		/// <param name="session">Current Houdini Engine session</param>
		/// <param name="geoID">Heightfield object</param>
		/// <param name="partID">Heightfield layer</param>
		/// <param name="detailProperties">Reference to a HEU_DetailProperties which will
		/// be populated.</param>
		public static void PopulateDetailProperties(HEU_SessionBase session, HAPI_NodeId geoID,
			HAPI_PartId partID, ref HEU_DetailProperties detailProperties)
		{
			// Detail distance
			HAPI_AttributeInfo detailDistanceAttrInfo = new HAPI_AttributeInfo();
			int[] detailDistances = new int[0];
			HEU_GeneralUtility.GetAttribute(session, geoID, partID,
				HEU_Defines.HEIGHTFIELD_DETAIL_DISTANCE, ref detailDistanceAttrInfo, ref detailDistances,
				session.GetAttributeIntData);

			// Detail density
			HAPI_AttributeInfo detailDensityAttrInfo = new HAPI_AttributeInfo();
			float[] detailDensity = new float[0];
			HEU_GeneralUtility.GetAttribute(session, geoID, partID,
				HEU_Defines.HEIGHTFIELD_DETAIL_DENSITY, ref detailDensityAttrInfo, ref detailDensity,
				session.GetAttributeFloatData);

			// Scatter Detail Resolution Per Patch (note that Detail Resolution comes from HF layer size)
			HAPI_AttributeInfo resolutionPatchAttrInfo = new HAPI_AttributeInfo();
			int[] resolutionPatches = new int[0];
			HEU_GeneralUtility.GetAttribute(session, geoID, partID,
				HEU_Defines.HEIGHTFIELD_DETAIL_RESOLUTION_PER_PATCH, ref resolutionPatchAttrInfo,
				ref resolutionPatches, session.GetAttributeIntData);

			if (detailProperties == null)
			{
				detailProperties = new HEU_DetailProperties();
			}

			// Unity only supports 1 set of detail resolution properties per terrain
			int arraySize = 1;

			if (detailDistanceAttrInfo.exists && detailDistances.Length >= arraySize)
			{
				detailProperties._detailDistance = detailDistances[0];
			}

			if (detailDensityAttrInfo.exists && detailDensity.Length >= arraySize)
			{
				detailProperties._detailDensity = detailDensity[0];
			}

			if (resolutionPatchAttrInfo.exists && resolutionPatches.Length >= arraySize)
			{
				detailProperties._detailResolutionPerPatch = resolutionPatches[0];
			}
		}
Ejemplo n.º 4
0
		/// <summary>
		/// Returns the Unity script attribute value, if found, on the specified geo's part.
		/// The attribute must be of string type, and owned by detail.
		/// </summary>
		/// <param name="session">Session that the asset resides in</param>
		/// <param name="geoID">The geo node's ID</param>
		/// <param name="partID">The part's ID</param>
		/// <returns>The name of the Unity script, or null if not found</returns>
		public static string GetUnityScriptAttributeValue(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID)
		{
			HAPI_AttributeInfo scriptAttributeInfo = new HAPI_AttributeInfo();
			int[] scriptAttr = new int[0];
			string scriptString = null;

			HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_PluginSettings.UnityScriptAttributeName, ref scriptAttributeInfo, ref scriptAttr, session.GetAttributeStringData);
			if (scriptAttributeInfo.exists)
			{
				if (scriptAttr.Length > 0)
				{
					scriptString = HEU_SessionManager.GetString(scriptAttr[0]);
				}
			}

			return scriptString;
		}
		private void GetPartLayerAttributes(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_NodeId partID, HEU_VolumeLayer layer)
		{
			// Get the tile index, if it exists, for this part
			HAPI_AttributeInfo tileAttrInfo = new HAPI_AttributeInfo();
			int[] tileAttrData = new int[0];
			HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HAPI_HEIGHTFIELD_TILE_ATTR, ref tileAttrInfo, ref tileAttrData, session.GetAttributeIntData);
			if (tileAttrData != null && tileAttrData.Length > 0)
			{
				layer._tile = tileAttrData[0];
				//Debug.LogFormat("Tile: {0}", tileAttrData[0]);
			}
			else
			{
				layer._tile = 0;
			}

			layer._hasLayerAttributes = HEU_TerrainUtility.VolumeLayerHasAttributes(session, geoID, partID);
		}
		private void GetPartLayerAttributes(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_NodeId partID, HEU_VolumeLayer layer)
		{
			// Get the tile index, if it exists, for this part
			HAPI_AttributeInfo tileAttrInfo = new HAPI_AttributeInfo();
			int[] tileAttrData = new int[0];
			HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HAPI_HEIGHTFIELD_TILE_ATTR, ref tileAttrInfo, ref tileAttrData, session.GetAttributeIntData);
			if (tileAttrData != null && tileAttrData.Length > 0)
			{
				layer._tile = tileAttrData[0];
				//Debug.LogFormat("Tile: {0}", tileAttrData[0]);
			}
			else
			{
				layer._tile = 0;
			}


			string[] layerAttrNames =
			{
				HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TEXTURE_DIFFUSE_ATTR,
				HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TEXTURE_MASK_ATTR,
				HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TEXTURE_NORMAL_ATTR,
				HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_NORMAL_SCALE_ATTR,
				HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_METALLIC_ATTR,
				HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_SMOOTHNESS_ATTR,
				HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_SPECULAR_ATTR,
				HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TILE_OFFSET_ATTR,
				HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TILE_SIZE_ATTR
			};

			// Check if any of the layer attribute names show up in the existing primitive attributes
			layer._hasLayerAttributes = false;
			HAPI_AttributeInfo attrInfo = new HAPI_AttributeInfo();
			bool bResult = false;
			foreach (string layerAttr in layerAttrNames)
			{
				bResult = session.GetAttributeInfo(geoID, partID, layerAttr, HAPI_AttributeOwner.HAPI_ATTROWNER_PRIM, ref attrInfo);
				if (bResult && attrInfo.exists)
				{
					layer._hasLayerAttributes = true;
					break;
				}
			}
		}
		/// <summary>
		/// Returns the Unity script attribute value, if found, on the specified geo's part.
		/// The attribute must be of string type, and owned by detail.
		/// </summary>
		/// <param name="session">Session that the asset resides in</param>
		/// <param name="geoID">The geo node's ID</param>
		/// <param name="partID">The part's ID</param>
		/// <returns>The name of the Unity script, or null if not found</returns>
		public static string GetUnityScriptAttributeValue(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID)
		{
			HAPI_AttributeInfo scriptAttributeInfo = new HAPI_AttributeInfo();
			int[] scriptAttr = new int[0];
			string scriptString = null;

			HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_PluginSettings.UnityScriptAttributeName, ref scriptAttributeInfo, ref scriptAttr, session.GetAttributeStringData);
			if (scriptAttributeInfo.exists)
			{
				if (scriptAttributeInfo.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_DETAIL)
				{
					Debug.LogWarningFormat("Houdini Engine for Unity only supports {0} as detail attributes!", HEU_PluginSettings.UnityScriptAttributeName);
				}
				else if (scriptAttr.Length > 0)
				{
					scriptString = HEU_SessionManager.GetString(scriptAttr[0]);
				}
			}

			return scriptString;
		}
		/// <summary>
		/// Assign Unity layer to the GameObject if found on the part as attribute.
		/// </summary>
		/// <param name="session"></param>
		/// <param name="geoID"></param>
		/// <param name="partID"></param>
		/// <param name="gameObject"></param>
		public static void AssignUnityLayer(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID, GameObject gameObject)
		{
			HAPI_AttributeInfo layerAttrInfo = new HAPI_AttributeInfo();
			int[] layerAttr = new int[0];
			HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_PluginSettings.UnityLayerAttributeName, ref layerAttrInfo, ref layerAttr, session.GetAttributeStringData);
			if (layerAttrInfo.exists)
			{
				string layerStr = HEU_SessionManager.GetString(layerAttr[0]);
				if (layerStr.Length > 0)
				{
					int layer = LayerMask.NameToLayer(layerStr);
					if (layer < 0)
					{
						Debug.LogWarningFormat("Unity layer '{0}' does not exist for current project. Add the layer in order to use it!", layerStr);
					}
					else
					{
						HEU_GeneralUtility.SetLayer(gameObject, layer, true);
					}
				}
			}
		}
		/// <summary>
		/// Assign the Unity tag to the GameObject if found on the part as attribute.
		/// </summary>
		public static void AssignUnityTag(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID, GameObject gameObject)
		{
			HAPI_AttributeInfo tagAttrInfo = new HAPI_AttributeInfo();
			int[] tagAttr = new int[0];
			HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_PluginSettings.UnityTagAttributeName, ref tagAttrInfo, ref tagAttr, session.GetAttributeStringData);
			if (tagAttrInfo.exists)
			{
				string tag = HEU_SessionManager.GetString(tagAttr[0]);
				if (tag.Length > 0)
				{
					try
					{
						SetTag(gameObject, tag, true);
					}
					catch (Exception ex)
					{
						Debug.LogWarning("Tag exception: " + ex.ToString());
						Debug.LogWarningFormat("Unity tag '{0}' does not exist for current project. Add the tag in order to use it!", tag);
					}
				}
			}
		}
Ejemplo n.º 10
0
		/// <summary>
		/// Returns the single string value from Attribute with given name and owner type, or null if failed.
		/// </summary>
		/// <param name="session">Houdini Engine session to query</param>
		/// <param name="geoID">The geometry ID in Houdini</param>
		/// <param name="partID">The part ID in Houdini</param>
		/// <param name="attrName">Name of the attribute to query</param>
		/// <param name="attrOwner">Owner type of the attribute</param>
		/// <returns>Valid string if successful, otherwise returns null</returns>
		public static string GetAttributeStringValueSingle(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID, string attrName, HAPI_AttributeOwner attrOwner)
		{
			if (string.IsNullOrEmpty(attrName))
			{
				return null;
			}

			HAPI_AttributeInfo attrInfo = new HAPI_AttributeInfo();
			int[] stringHandle = new int[0];
			HEU_GeneralUtility.GetAttribute(session, geoID, partID, attrName, ref attrInfo, ref stringHandle, session.GetAttributeStringData);
			if (attrInfo.exists)
			{
				if (attrInfo.owner != attrOwner)
				{
					Debug.LogWarningFormat("Expected {0} attribute owner for attribute {1} but got {2}!", attrOwner, attrName, attrInfo.owner);
				}
				else if (stringHandle.Length > 0)
				{
					return HEU_SessionManager.GetString(stringHandle[0]);
				}
			}
			return null;
		}
		private bool LoadLayerColorFromAttribute(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_NodeId partID, string attrName, ref Color colorValue)
		{
			HAPI_AttributeInfo attrInfo = new HAPI_AttributeInfo();
			float[] attrValues = new float[0];
			HEU_GeneralUtility.GetAttribute(session, geoID, partID, attrName, ref attrInfo, ref attrValues, session.GetAttributeFloatData);
			if (attrValues != null && attrValues.Length >= 3 && attrInfo.tupleSize >= 3)
			{
				colorValue[0] = attrValues[0];
				colorValue[1] = attrValues[1];
				colorValue[2] = attrValues[2];

				if (attrInfo.tupleSize == 4 && attrValues.Length == 4)
				{
					colorValue[3] = attrValues[3];
				}
				else
				{
					colorValue[3] = 1f;
				}
				return true;
			}
			return false;
		}
		/// <summary>
		/// Grab the scatter data for the given part.
		/// This finds the properties of TreeInstances via attributes.
		/// </summary>
		/// <param name="session">Houdini session</param>
		/// <param name="geoID">Geometry ID</param>
		/// <param name="partID">Part (volume layer) ID</param>
		/// <param name="pointCount">Number of expected scatter points</param>
		public static void PopulateScatterTrees(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID, int pointCount,
			ref HEU_VolumeScatterTrees scatterTrees)
		{
			// The HEU_VolumeScatterTrees might already have been created when the volumecache was queried.
			// The "height" layer might have had prototype data which is set in _scatterTrees.
			if (scatterTrees == null)
			{
				scatterTrees = new HEU_VolumeScatterTrees();
			}

			// Get prototype indices. These indices refer to _scatterTrees._treePrototypes.
			HAPI_AttributeInfo indicesAttrInfo = new HAPI_AttributeInfo();
			int[] indices = new int[0];
			if (HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HEIGHTFIELD_TREEINSTANCE_PROTOTYPEINDEX, ref indicesAttrInfo, ref indices, session.GetAttributeIntData))
			{
				if (indices != null && indices.Length == pointCount)
				{
					scatterTrees._prototypeIndices = indices;
				}
				else
				{
					Debug.LogWarningFormat("Scatter instance index count for attribute {0} is not valid. Expected {1} but got {2}",
						HEU_Defines.HEIGHTFIELD_TREEINSTANCE_PROTOTYPEINDEX, pointCount, (indices != null ? indices.Length : 0));
				}
			}

			// Using the UVs as position of the instances, since they are properly mapped to the terrain tile.
			// Also getting other attributes for the TreeInstances, if they are set.
			HAPI_AttributeInfo uvAttrInfo = new HAPI_AttributeInfo();
			float[] uvs = new float[0];
			if (!HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HAPI_ATTRIB_UV, ref uvAttrInfo, ref uvs, session.GetAttributeFloatData))
			{
				Debug.LogWarning("UVs for scatter instances not found or valid.");
			}

			if (uvs != null && uvs.Length == (pointCount * uvAttrInfo.tupleSize))
			{
				// Get height scales
				HAPI_AttributeInfo heightAttrInfo = new HAPI_AttributeInfo();
				float[] heightscales = new float[0];
				HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HEIGHTFIELD_TREEINSTANCE_HEIGHTSCALE, ref heightAttrInfo, ref heightscales, session.GetAttributeFloatData);

				// Get width scales
				HAPI_AttributeInfo widthAttrInfo = new HAPI_AttributeInfo();
				float[] widthscales = new float[0];
				HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HEIGHTFIELD_TREEINSTANCE_WIDTHSCALE, ref widthAttrInfo, ref widthscales, session.GetAttributeFloatData);

				// Get orientation
				HAPI_AttributeInfo orientAttrInfo = new HAPI_AttributeInfo();
				float[] orients = new float[0];
				HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HAPI_ATTRIB_ORIENT, ref orientAttrInfo, ref orients, session.GetAttributeFloatData);

				// Get color
				HAPI_AttributeInfo colorAttrInfo = new HAPI_AttributeInfo();
				float[] colors = new float[0];
				HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HAPI_ATTRIB_COLOR, ref colorAttrInfo, ref colors, session.GetAttributeFloatData);

				// Get lightmap color
				HAPI_AttributeInfo lightmapColorAttrInfo = new HAPI_AttributeInfo();
				float[] lightmapColors = new float[0];
				HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HEIGHTFIELD_TREEINSTANCE_LIGHTMAPCOLOR, ref lightmapColorAttrInfo, ref lightmapColors, session.GetAttributeFloatData);

				scatterTrees._positions = new Vector3[pointCount];

				if (heightAttrInfo.exists && (heightscales.Length == pointCount))
				{
					scatterTrees._heightScales = heightscales;
				}

				if (widthAttrInfo.exists && (widthscales.Length == pointCount))
				{
					scatterTrees._widthScales = widthscales;
				}

				if (orientAttrInfo.exists && (orients.Length == orientAttrInfo.tupleSize * pointCount))
				{
					scatterTrees._rotations = new float[pointCount];
				}

				if (colorAttrInfo.exists && (colors.Length == colorAttrInfo.tupleSize * pointCount))
				{
					scatterTrees._colors = new Color32[pointCount];
				}

				if (lightmapColorAttrInfo.exists && (lightmapColors.Length == lightmapColorAttrInfo.tupleSize * pointCount))
				{
					scatterTrees._lightmapColors = new Color32[pointCount];
				}

				for (int i = 0; i < pointCount; ++i)
				{
					scatterTrees._positions[i] = new Vector3(1.0f - uvs[i * uvAttrInfo.tupleSize + 1],
																	 0,
																	 uvs[i * uvAttrInfo.tupleSize + 0]);

					if (scatterTrees._colors != null)
					{
						scatterTrees._colors[i] =
							new Color32((byte)(colors[i * colorAttrInfo.tupleSize + 0] * 255),
										(byte)(colors[i * colorAttrInfo.tupleSize + 1] * 255),
										(byte)(colors[i * colorAttrInfo.tupleSize + 2] * 255),
										(byte)(colors[i * colorAttrInfo.tupleSize + 3] * 255));
					}

					if (scatterTrees._lightmapColors != null)
					{
						scatterTrees._lightmapColors[i] =
							new Color32((byte)(lightmapColors[i * lightmapColorAttrInfo.tupleSize + 0] * 255),
										(byte)(lightmapColors[i * lightmapColorAttrInfo.tupleSize + 1] * 255),
										(byte)(lightmapColors[i * lightmapColorAttrInfo.tupleSize + 2] * 255),
										(byte)(lightmapColors[i * lightmapColorAttrInfo.tupleSize + 3] * 255));
					}

					if (scatterTrees._rotations != null)
					{
						Quaternion quaternion = new Quaternion(
							orients[i * orientAttrInfo.tupleSize + 0], 
							orients[i * orientAttrInfo.tupleSize + 1], 
							orients[i * orientAttrInfo.tupleSize + 2], 
							orients[i * orientAttrInfo.tupleSize + 3]);
						Vector3 euler = quaternion.eulerAngles;
						euler.y = -euler.y;
						euler.z = -euler.z;
						scatterTrees._rotations[i] = euler.y * Mathf.Deg2Rad;
					}
				}
			}
		}
		public bool GenerateTerrainBuffers(HEU_SessionBase session, HAPI_NodeId nodeID, List<HAPI_PartInfo> volumeParts,
			out List<HEU_LoadBufferVolume> volumeBuffers)
		{
			volumeBuffers = null;
			if (volumeParts.Count == 0)
			{
				return true;
			}

			volumeBuffers = new List<HEU_LoadBufferVolume>();

			int numParts = volumeParts.Count;
			for (int i = 0; i < numParts; ++i)
			{
				HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo();
				bool bResult = session.GetVolumeInfo(nodeID, volumeParts[i].id, ref volumeInfo);
				if (!bResult || volumeInfo.tupleSize != 1 || volumeInfo.zLength != 1 || volumeInfo.storage != HAPI_StorageType.HAPI_STORAGETYPE_FLOAT)
				{
					SetLog(HEU_LoadData.LoadStatus.ERROR, "This heightfield is not supported. Please check documentation.");
					return false;
				}

				if (volumeInfo.xLength != volumeInfo.yLength)
				{
					SetLog(HEU_LoadData.LoadStatus.ERROR, "Non-square sized terrain not supported.");
					return false;
				}

				string volumeName = HEU_SessionManager.GetString(volumeInfo.nameSH, session);
				bool bHeightPart = volumeName.Equals("height");

				//Debug.LogFormat("Part name: {0}, GeoName: {1}, Volume Name: {2}, Display: {3}", part.PartName, geoNode.GeoName, volumeName, geoNode.Displayable);

				HEU_LoadBufferVolumeLayer layer = new HEU_LoadBufferVolumeLayer();
				layer._layerName = volumeName;
				layer._partID = volumeParts[i].id;
				layer._heightMapSize = volumeInfo.xLength;

				Matrix4x4 volumeTransformMatrix = HEU_HAPIUtility.GetMatrixFromHAPITransform(ref volumeInfo.transform, false);
				layer._position = HEU_HAPIUtility.GetPosition(ref volumeTransformMatrix);
				Vector3 scale = HEU_HAPIUtility.GetScale(ref volumeTransformMatrix);

				// Calculate real terrain size in both Houdini and Unity.
				// The height values will be mapped over this terrain size.
				float gridSpacingX = scale.x * 2f;
				float gridSpacingY = scale.y * 2f;
				layer._terrainSizeX = Mathf.Round((volumeInfo.xLength - 1) * gridSpacingX);
				layer._terrainSizeY = Mathf.Round((volumeInfo.yLength - 1) * gridSpacingY);

				// Get volume bounds for calculating position offset
				session.GetVolumeBounds(nodeID, volumeParts[i].id, 
					out layer._minBounds.x, out layer._minBounds.y, out layer._minBounds.z, 
					out layer._maxBounds.x, out layer._maxBounds.y, out layer._maxBounds.z, 
					out layer._center.x, out layer._center.y, out layer._center.z);

				LoadStringFromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TEXTURE_DIFFUSE_ATTR, ref layer._diffuseTexturePath);
				LoadStringFromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TEXTURE_MASK_ATTR, ref layer._maskTexturePath);
				LoadStringFromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TEXTURE_NORMAL_ATTR, ref layer._normalTexturePath);

				LoadFloatFromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_NORMAL_SCALE_ATTR, ref layer._normalScale);
				LoadFloatFromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_METALLIC_ATTR, ref layer._metallic);
				LoadFloatFromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_SMOOTHNESS_ATTR, ref layer._smoothness);

				LoadLayerColorFromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_SPECULAR_ATTR, ref layer._specularColor);
				LoadLayerVector2FromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TILE_OFFSET_ATTR, ref layer._tileOffset);
				LoadLayerVector2FromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TILE_SIZE_ATTR, ref layer._tileSize);

				// Get the height values from Houdini and find the min and max height range.
				if (!HEU_GeometryUtility.GetHeightfieldValues(session, volumeInfo.xLength, volumeInfo.yLength, nodeID, volumeParts[i].id, ref layer._rawHeights, ref layer._minHeight, ref layer._maxHeight))
				{
					return false;
				}

				// TODO: Tried to replace above with this, but it flattens the heights
				//layer._rawHeights = HEU_GeometryUtility.GetHeightfieldFromPart(_session, nodeID, volumeParts[i].id, "part", volumeInfo.xLength);

				// Get the tile index, if it exists, for this part
				HAPI_AttributeInfo tileAttrInfo = new HAPI_AttributeInfo();
				int[] tileAttrData = new int[0];
				HEU_GeneralUtility.GetAttribute(session, nodeID, volumeParts[i].id, "tile", ref tileAttrInfo, ref tileAttrData, session.GetAttributeIntData);

				int tileIndex = 0;
				if (tileAttrInfo.exists && tileAttrData.Length == 1)
				{
					tileIndex = tileAttrData[0];
				}

				// Add layer based on tile index
				if (tileIndex >= 0)
				{
					HEU_LoadBufferVolume volumeBuffer = null;
					for(int j = 0; j < volumeBuffers.Count; ++j)
					{
						if (volumeBuffers[j]._tileIndex == tileIndex)
						{
							volumeBuffer = volumeBuffers[j];
							break;
						}
					}

					if (volumeBuffer == null)
					{
						volumeBuffer = new HEU_LoadBufferVolume();
						volumeBuffer.InitializeBuffer(volumeParts[i].id, volumeName, false, false);

						volumeBuffer._tileIndex = tileIndex;
						volumeBuffers.Add(volumeBuffer);
					}

					if (bHeightPart)
					{
						// Height layer always first layer
						volumeBuffer._layers.Insert(0, layer);

						volumeBuffer._heightMapSize = layer._heightMapSize;
						volumeBuffer._terrainSizeX = layer._terrainSizeX;
						volumeBuffer._terrainSizeY = layer._terrainSizeY;
						volumeBuffer._heightRange = (layer._maxHeight - layer._minHeight);
					}
					else
					{
						volumeBuffer._layers.Add(layer);
					}
				}

				Sleep();
			}

			// Each volume buffer is a self contained terrain tile
			foreach(HEU_LoadBufferVolume volumeBuffer in volumeBuffers)
			{
				List<HEU_LoadBufferVolumeLayer> layers = volumeBuffer._layers;
				//Debug.LogFormat("Heightfield: tile={0}, layers={1}", tile._tileIndex, layers.Count);

				int heightMapSize = volumeBuffer._heightMapSize;

				int numLayers = layers.Count;
				if (numLayers > 0)
				{
					// Convert heightmap values from Houdini to Unity
					volumeBuffer._heightMap = HEU_GeometryUtility.ConvertHeightMapHoudiniToUnity(heightMapSize, layers[0]._rawHeights, layers[0]._minHeight, layers[0]._maxHeight);

					Sleep();

					// Convert splatmap values from Houdini to Unity.
					List<float[]> heightFields = new List<float[]>();
					for(int m = 1; m < numLayers; ++m)
					{
						heightFields.Add(layers[m]._rawHeights);
					}
					volumeBuffer._splatMaps = HEU_GeometryUtility.ConvertHeightSplatMapHoudiniToUnity(heightMapSize, heightFields);

					volumeBuffer._position = new Vector3((volumeBuffer._terrainSizeX + volumeBuffer._layers[0]._minBounds.x), volumeBuffer._layers[0]._minHeight + volumeBuffer._layers[0]._position.y, volumeBuffer._layers[0]._minBounds.z);
				}
			}

			return true;
		}
Ejemplo n.º 14
0
		public void UpdateLayerFromPart(HEU_SessionBase session, HEU_PartData part)
		{
			HEU_GeoNode geoNode = part.ParentGeoNode;

			HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo();
			bool bResult = session.GetVolumeInfo(geoNode.GeoID, part.PartID, ref volumeInfo);
			if (!bResult || volumeInfo.tupleSize != 1 || volumeInfo.zLength != 1 || volumeInfo.storage != HAPI_StorageType.HAPI_STORAGETYPE_FLOAT)
			{
				return;
			}

			string volumeName = HEU_SessionManager.GetString(volumeInfo.nameSH, session);
			part.SetVolumeLayerName(volumeName);

			//Debug.LogFormat("Part name: {0}, GeoName: {1}, Volume Name: {2}, Display: {3}", part.PartName, geoNode.GeoName, volumeName, geoNode.Displayable);

			HEU_VolumeLayer.HFLayerType layerType = GetHeightfieldLayerType(session, geoNode.GeoID, part.PartID, volumeName);

			HEU_VolumeLayer layer = GetLayer(volumeName);
			if (layer == null)
			{
				layer = new HEU_VolumeLayer();
				layer._layerName = volumeName;

				if (layerType == HEU_VolumeLayer.HFLayerType.HEIGHT)
				{
					_layers.Insert(0, layer);
				}
				else if(layerType != HEU_VolumeLayer.HFLayerType.MASK)
				{
					_layers.Add(layer);
				}
			}

			layer._part = part;
			layer._xLength = volumeInfo.xLength;
			layer._yLength = volumeInfo.yLength;
			layer._layerType = layerType;

			if (layerType != HEU_VolumeLayer.HFLayerType.MASK)
			{
				GetPartLayerAttributes(session, geoNode.GeoID, part.PartID, layer);
			}

			if (layerType != HEU_VolumeLayer.HFLayerType.HEIGHT)
			{
				// Non-height parts don't have any outputs as they are simply layers carrying info
				part.DestroyAllData();
			}
			else
			{
				// Height part
				// Might contain terrain properties via attributes (i.e. not layer specific, but for entire terrain)

				// Scatter Tree Prototypes
				List<HEU_TreePrototypeInfo> treePrototypeInfos = HEU_TerrainUtility.GetTreePrototypeInfosFromPart(session, geoNode.GeoID, part.PartID);
				if (treePrototypeInfos != null)
				{
					if (_scatterTrees == null)
					{
						_scatterTrees = new HEU_VolumeScatterTrees();
					}
					_scatterTrees._treePrototypInfos = treePrototypeInfos;
				}

				// Detail distance
				HAPI_AttributeInfo detailDistanceAttrInfo = new HAPI_AttributeInfo();
				int[] detailDistances = new int[0];
				HEU_GeneralUtility.GetAttribute(session, geoNode.GeoID, part.PartID, 
					HEU_Defines.HEIGHTFIELD_DETAIL_DISTANCE, ref detailDistanceAttrInfo, ref detailDistances, 
					session.GetAttributeIntData);

				// Scatter Detail Resolution Per Patch (note that Detail Resolution comes from HF layer size)
				HAPI_AttributeInfo resolutionPatchAttrInfo = new HAPI_AttributeInfo();
				int[] resolutionPatches = new int[0];
				HEU_GeneralUtility.GetAttribute(session, geoNode.GeoID, part.PartID, 
					HEU_Defines.HEIGHTFIELD_DETAIL_RESOLUTION_PER_PATCH, ref resolutionPatchAttrInfo, 
					ref resolutionPatches, session.GetAttributeIntData);


				if (_detailProperties == null)
				{
					_detailProperties = new HEU_DetailProperties();
				}

				// Unity only supports 1 set of detail resolution properties per terrain
				int arraySize = 1;

				if (detailDistanceAttrInfo.exists && detailDistances.Length >= arraySize)
				{
					_detailProperties._detailDistance = detailDistances[0];
				}

				if (resolutionPatchAttrInfo.exists && resolutionPatches.Length >= arraySize)
				{
					_detailProperties._detailResolutionPerPatch = resolutionPatches[0];
				}
			}

			if (!_updatedLayers.Contains(layer))
			{
				if (layerType == HEU_VolumeLayer.HFLayerType.HEIGHT)
				{
					_updatedLayers.Insert(0, layer);
				}
				else if (layerType != HEU_VolumeLayer.HFLayerType.MASK)
				{
					_updatedLayers.Add(layer);
				}
			}
		}
Ejemplo n.º 15
0
        public void ProcessVolumeParts(HEU_SessionBase session, List <HEU_PartData> volumeParts, bool bRebuild)
        {
            int numVolumeParts = volumeParts.Count;

            if (numVolumeParts == 0)
            {
                DestroyVolumeCache();
            }
            else if (_volumeCaches == null)
            {
                _volumeCaches = new List <HEU_VolumeCache>();
            }

            // First update volume caches. Each volume cache represents a set of terrain layers grouped by tile index.
            // Therefore each volume cache represents a potential Unity Terrain (containing layers)
            _volumeCaches = HEU_VolumeCache.UpdateVolumeCachesFromParts(session, this, volumeParts, _volumeCaches);

            // Heightfield scatter nodes come in as mesh-type parts with attribute instancing.
            // So process them here to get all the tree/detail instance scatter information.
            int numParts = _parts.Count;

            for (int i = 0; i < numParts; ++i)
            {
                // Find the terrain tile (use primitive attr). Assume 0 tile if not set (i.e. not split into tiles)
                int terrainTile = 0;
                HAPI_AttributeInfo tileAttrInfo = new HAPI_AttributeInfo();
                int[] tileAttrData = new int[0];
                if (HEU_GeneralUtility.GetAttribute(session, GeoID, _parts[i].PartID, HEU_Defines.HAPI_HEIGHTFIELD_TILE_ATTR, ref tileAttrInfo, ref tileAttrData, session.GetAttributeIntData))
                {
                    if (tileAttrData != null && tileAttrData.Length > 0)
                    {
                        terrainTile = tileAttrData[0];
                    }
                }

                // Find the volumecache associated with this part using the terrain tile index
                HEU_VolumeCache volumeCache = GetVolumeCacheByTileIndex(terrainTile);
                if (volumeCache == null)
                {
                    continue;
                }

                HEU_VolumeLayer volumeLayer = volumeCache.GetLayer(_parts[i].GetVolumeLayerName());
                if (volumeLayer != null && volumeLayer._layerType == HFLayerType.DETAIL)
                {
                    // Clear out outputs since it might have been created when the part was created.
                    _parts[i].DestroyAllData();

                    volumeCache.PopulateDetailPrototype(session, GeoID, _parts[i].PartID, volumeLayer);
                }
                else if (_parts[i].IsAttribInstancer())
                {
                    HAPI_AttributeInfo treeInstAttrInfo = new HAPI_AttributeInfo();
                    if (HEU_GeneralUtility.GetAttributeInfo(session, GeoID, _parts[i].PartID, HEU_Defines.HEIGHTFIELD_TREEINSTANCE_PROTOTYPEINDEX, ref treeInstAttrInfo))
                    {
                        if (treeInstAttrInfo.exists && treeInstAttrInfo.count > 0)
                        {
                            // Clear out outputs since it might have been created when the part was created.
                            _parts[i].DestroyAllData();

                            // Mark the instancers as having been created so that the object instancer step skips this.
                            _parts[i].ObjectInstancesBeenGenerated = true;

                            // Now populate scatter trees based on attributes on this part
                            volumeCache.PopulateScatterTrees(session, GeoID, _parts[i].PartID, treeInstAttrInfo.count);
                        }
                    }
                }
            }

            // Now generate the terrain for each volume cache
            foreach (HEU_VolumeCache cache in _volumeCaches)
            {
                cache.GenerateTerrainWithAlphamaps(session, ParentAsset, bRebuild);

                cache.IsDirty = false;
            }
        }
		//	LOGIC -----------------------------------------------------------------------------------------------------

		public static List<HEU_VolumeCache> UpdateVolumeCachesFromParts(HEU_SessionBase session, HEU_GeoNode ownerNode, List<HEU_PartData> volumeParts, List<HEU_VolumeCache> volumeCaches)
		{
			HEU_HoudiniAsset parentAsset = ownerNode.ParentAsset;

			foreach (HEU_VolumeCache cache in volumeCaches)
			{
				// Remove current volume caches from parent asset.
				// These get added back in below.
				parentAsset.RemoveVolumeCache(cache);

				// Mark the cache for updating
				cache.StartUpdateLayers();
			}

			// This will keep track of volume caches still in use
			List<HEU_VolumeCache> updatedCaches = new List<HEU_VolumeCache>();

			int numParts = volumeParts.Count;
			for (int i = 0; i < numParts; ++i)
			{
				// Get the tile index, if it exists, for this part
				HAPI_AttributeInfo tileAttrInfo = new HAPI_AttributeInfo();
				int[] tileAttrData = new int[0];
				HEU_GeneralUtility.GetAttribute(session, ownerNode.GeoID, volumeParts[i].PartID, HEU_Defines.HAPI_HEIGHTFIELD_TILE_ATTR, ref tileAttrInfo, ref tileAttrData, session.GetAttributeIntData);
				if (tileAttrData != null && tileAttrData.Length > 0)
				{
					//Debug.LogFormat("Tile: {0}", tileAttrData[0]);

					int tile = tileAttrData[0];
					HEU_VolumeCache volumeCache = null;

					// Find cache in updated list
					for (int j = 0; j < updatedCaches.Count; ++j)
					{
						if (updatedCaches[j] != null && updatedCaches[j].TileIndex == tile)
						{
							volumeCache = updatedCaches[j];
							break;
						}
					}

					if (volumeCache != null)
					{
						volumeCache.UpdateLayerFromPart(session, volumeParts[i]);

						// Skip adding new cache since already found in updated list
						continue;
					}

					// Find existing cache in old list
					if (volumeCaches != null && volumeCaches.Count > 0)
					{
						for(int j = 0; j < volumeCaches.Count; ++j)
						{
							if (volumeCaches[j] != null && volumeCaches[j].TileIndex == tile)
							{
								volumeCache = volumeCaches[j];
								break;
							}
						}
					}

					// Create new cache for this tile if not found
					if (volumeCache == null)
					{
						volumeCache = ScriptableObject.CreateInstance<HEU_VolumeCache>();
						volumeCache.Initialize(ownerNode, tile);
						volumeCache.StartUpdateLayers();
					}

					volumeCache.UpdateLayerFromPart(session, volumeParts[i]);

					if (!updatedCaches.Contains(volumeCache))
					{
						updatedCaches.Add(volumeCache);
					}
				}
				else
				{
					// No tile index. Most likely a single terrain tile.

					HEU_VolumeCache volumeCache = null;

					if (updatedCaches.Count == 0)
					{
						// Create a single volume cache, or use existing if it was just 1.
						// If more than 1 volume cache exists, this will recreate a single one

						if (volumeCaches == null || volumeCaches.Count != 1)
						{
							volumeCache = ScriptableObject.CreateInstance<HEU_VolumeCache>();
							volumeCache.Initialize(ownerNode, 0);
							volumeCache.StartUpdateLayers();
						}
						else if (volumeCaches.Count == 1)
						{
							// Keep the single volumecache
							volumeCache = volumeCaches[0];
						}

						if (!updatedCaches.Contains(volumeCache))
						{
							updatedCaches.Add(volumeCache);
						}
					}
					else
					{
						// Reuse the updated cache
						volumeCache = updatedCaches[0];
					}

					volumeCache.UpdateLayerFromPart(session, volumeParts[i]);
				}
			}

			foreach (HEU_VolumeCache cache in updatedCaches)
			{
				// Add to parent for UI and preset
				parentAsset.AddVolumeCache(cache);

				// Finish update by keeping just the layers in use for each volume cache.
				cache.FinishUpdateLayers();
			}

			return updatedCaches;
		}
Ejemplo n.º 17
0
		public bool GenerateTerrainBuffers(HEU_SessionBase session, HAPI_NodeId nodeID, List<HAPI_PartInfo> volumeParts,
			List<HAPI_PartInfo> scatterInstancerParts, out List<HEU_LoadBufferVolume> volumeBuffers)
		{
			volumeBuffers = null;
			if (volumeParts.Count == 0)
			{
				return true;
			}

			volumeBuffers = new List<HEU_LoadBufferVolume>();

			int numParts = volumeParts.Count;
			for (int i = 0; i < numParts; ++i)
			{
				HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo();
				bool bResult = session.GetVolumeInfo(nodeID, volumeParts[i].id, ref volumeInfo);
				if (!bResult || volumeInfo.tupleSize != 1 || volumeInfo.zLength != 1 || volumeInfo.storage != HAPI_StorageType.HAPI_STORAGETYPE_FLOAT)
				{
					SetLog(HEU_LoadData.LoadStatus.ERROR, "This heightfield is not supported. Please check documentation.");
					return false;
				}

				if (volumeInfo.xLength != volumeInfo.yLength)
				{
					SetLog(HEU_LoadData.LoadStatus.ERROR, "Non-square sized terrain not supported.");
					return false;
				}

				string volumeName = HEU_SessionManager.GetString(volumeInfo.nameSH, session);
				bool bHeightPart = volumeName.Equals(HEU_Defines.HAPI_HEIGHTFIELD_LAYERNAME_HEIGHT);
				bool bMaskPart = volumeName.Equals(HEU_Defines.HAPI_HEIGHTFIELD_LAYERNAME_MASK);

				//Debug.LogFormat("Part name: {0}, GeoName: {1}, Volume Name: {2}, Display: {3}", part.PartName, geoNode.GeoName, volumeName, geoNode.Displayable);

				// Ignoring mask layer because it is Houdini-specific (same behaviour as regular HDA terrain generation)
				if (bMaskPart)
				{
					continue;
				}

				HEU_LoadBufferVolumeLayer layer = new HEU_LoadBufferVolumeLayer();
				layer._layerName = volumeName;
				layer._partID = volumeParts[i].id;
				layer._heightMapWidth = volumeInfo.xLength;
				layer._heightMapHeight = volumeInfo.yLength;

				Matrix4x4 volumeTransformMatrix = HEU_HAPIUtility.GetMatrixFromHAPITransform(ref volumeInfo.transform, false);
				layer._position = HEU_HAPIUtility.GetPosition(ref volumeTransformMatrix);
				Vector3 scale = HEU_HAPIUtility.GetScale(ref volumeTransformMatrix);

				// Calculate real terrain size in both Houdini and Unity.
				// The height values will be mapped over this terrain size.
				float gridSpacingX = scale.x * 2f;
				float gridSpacingY = scale.y * 2f;
				layer._terrainSizeX = Mathf.Round((volumeInfo.xLength - 1) * gridSpacingX);
				layer._terrainSizeY = Mathf.Round((volumeInfo.yLength - 1) * gridSpacingY);

				// Get volume bounds for calculating position offset
				session.GetVolumeBounds(nodeID, volumeParts[i].id, 
					out layer._minBounds.x, out layer._minBounds.y, out layer._minBounds.z, 
					out layer._maxBounds.x, out layer._maxBounds.y, out layer._maxBounds.z, 
					out layer._center.x, out layer._center.y, out layer._center.z);

				// Look up TerrainLayer file via attribute if user has set it
				layer._layerPath = HEU_GeneralUtility.GetAttributeStringValueSingle(session, nodeID, volumeParts[i].id,
					HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TERRAINLAYER_FILE_ATTR, HAPI_AttributeOwner.HAPI_ATTROWNER_PRIM);

				LoadStringFromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TEXTURE_DIFFUSE_ATTR, ref layer._diffuseTexturePath);
				LoadStringFromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TEXTURE_MASK_ATTR, ref layer._maskTexturePath);
				LoadStringFromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TEXTURE_NORMAL_ATTR, ref layer._normalTexturePath);

				LoadFloatFromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_NORMAL_SCALE_ATTR, ref layer._normalScale);
				LoadFloatFromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_METALLIC_ATTR, ref layer._metallic);
				LoadFloatFromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_SMOOTHNESS_ATTR, ref layer._smoothness);

				LoadLayerColorFromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_SPECULAR_ATTR, ref layer._specularColor);
				LoadLayerVector2FromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TILE_OFFSET_ATTR, ref layer._tileOffset);
				LoadLayerVector2FromAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TILE_SIZE_ATTR, ref layer._tileSize);

				// Get the height values from Houdini along with the min and max height range.
				layer._normalizedHeights = HEU_TerrainUtility.GetNormalizedHeightmapFromPartWithMinMax(_session, nodeID, volumeParts[i].id, volumeInfo.xLength, volumeInfo.yLength, ref layer._minHeight, ref layer._maxHeight, ref layer._heightRange);

				// Get the tile index, if it exists, for this part
				HAPI_AttributeInfo tileAttrInfo = new HAPI_AttributeInfo();
				int[] tileAttrData = new int[0];
				HEU_GeneralUtility.GetAttribute(session, nodeID, volumeParts[i].id, HEU_Defines.HAPI_HEIGHTFIELD_TILE_ATTR, ref tileAttrInfo, ref tileAttrData, session.GetAttributeIntData);

				int tileIndex = 0;
				if (tileAttrInfo.exists && tileAttrData.Length == 1)
				{
					tileIndex = tileAttrData[0];
				}

				// Add layer based on tile index
				if (tileIndex >= 0)
				{
					HEU_LoadBufferVolume volumeBuffer = null;
					for(int j = 0; j < volumeBuffers.Count; ++j)
					{
						if (volumeBuffers[j]._tileIndex == tileIndex)
						{
							volumeBuffer = volumeBuffers[j];
							break;
						}
					}

					if (volumeBuffer == null)
					{
						volumeBuffer = new HEU_LoadBufferVolume();
						volumeBuffer.InitializeBuffer(volumeParts[i].id, volumeName, false, false);

						volumeBuffer._tileIndex = tileIndex;
						volumeBuffers.Add(volumeBuffer);
					}

					if (bHeightPart)
					{
						// Height layer always first layer
						volumeBuffer._layers.Insert(0, layer);

						volumeBuffer._heightMapWidth = layer._heightMapWidth;
						volumeBuffer._heightMapHeight = layer._heightMapHeight;
						volumeBuffer._terrainSizeX = layer._terrainSizeX;
						volumeBuffer._terrainSizeY = layer._terrainSizeY;
						volumeBuffer._heightRange = (layer._maxHeight - layer._minHeight);

						// Look up TerrainData file path via attribute if user has set it
						volumeBuffer._terrainDataPath = HEU_GeneralUtility.GetAttributeStringValueSingle(session, nodeID, volumeBuffer._id,
							HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TERRAINDATA_FILE_ATTR, HAPI_AttributeOwner.HAPI_ATTROWNER_PRIM);

						// Load the TreePrototype buffers
						List<HEU_TreePrototypeInfo> treePrototypeInfos = HEU_TerrainUtility.GetTreePrototypeInfosFromPart(session, nodeID, volumeBuffer._id);
						if (treePrototypeInfos != null)
						{
							if (volumeBuffer._scatterTrees == null)
							{
								volumeBuffer._scatterTrees = new HEU_VolumeScatterTrees();
							}
							volumeBuffer._scatterTrees._treePrototypInfos = treePrototypeInfos;
						}

					}
					else
					{
						volumeBuffer._layers.Add(layer);
					}
				}

				Sleep();
			}

			// Each volume buffer is a self contained terrain tile
			foreach(HEU_LoadBufferVolume volumeBuffer in volumeBuffers)
			{
				List<HEU_LoadBufferVolumeLayer> layers = volumeBuffer._layers;
				//Debug.LogFormat("Heightfield: tile={0}, layers={1}", tile._tileIndex, layers.Count);

				int heightMapWidth = volumeBuffer._heightMapWidth;
				int heightMapHeight = volumeBuffer._heightMapHeight;

				int numLayers = layers.Count;
				if (numLayers > 0)
				{
					// Convert heightmap values from Houdini to Unity
					volumeBuffer._heightMap = HEU_TerrainUtility.ConvertHeightMapHoudiniToUnity(heightMapWidth, heightMapHeight, layers[0]._normalizedHeights);

					Sleep();

					// Convert splatmap values from Houdini to Unity.
					// Start at 2nd index since height is strictly for height values (not splatmap).
					List<float[]> heightFields = new List<float[]>();
					for(int m = 1; m < numLayers; ++m)
					{
						heightFields.Add(layers[m]._normalizedHeights);
					}

					// The number of maps are the number of splatmaps (ie. non height/mask layers)
					int numMaps = heightFields.Count;
					if (numMaps > 0)
					{
						// Using the first splatmap size for all splatmaps
						volumeBuffer._splatMaps = HEU_TerrainUtility.ConvertHeightFieldToAlphaMap(layers[1]._heightMapWidth, layers[1]._heightMapHeight, heightFields);
					}
					else
					{
						volumeBuffer._splatMaps = null;
					}

					volumeBuffer._position = new Vector3((volumeBuffer._terrainSizeX + volumeBuffer._layers[0]._minBounds.x), volumeBuffer._layers[0]._minHeight + volumeBuffer._layers[0]._position.y, volumeBuffer._layers[0]._minBounds.z);
				}
			}

			// Process the scatter instancer parts to get the scatter data
			for (int i = 0; i < scatterInstancerParts.Count; ++i)
			{
				// Find the terrain tile (use primitive attr). Assume 0 tile if not set (i.e. not split into tiles)
				int terrainTile = 0;
				HAPI_AttributeInfo tileAttrInfo = new HAPI_AttributeInfo();
				int[] tileAttrData = new int[0];
				if (HEU_GeneralUtility.GetAttribute(session, nodeID, scatterInstancerParts[i].id, HEU_Defines.HAPI_HEIGHTFIELD_TILE_ATTR, ref tileAttrInfo, ref tileAttrData, session.GetAttributeIntData))
				{
					if (tileAttrData != null && tileAttrData.Length > 0)
					{
						terrainTile = tileAttrData[0];
					}
				}

				// Find the volume layer associated with this part using the terrain tile index
				HEU_LoadBufferVolume volumeBuffer = GetLoadBufferVolumeFromTileIndex(terrainTile, volumeBuffers);
				if (volumeBuffer == null)
				{
					continue;
				}

				HEU_TerrainUtility.PopulateScatterInfo(session, nodeID, scatterInstancerParts[i].id, scatterInstancerParts[i].pointCount, ref volumeBuffer._scatterTrees);
			}

			return true;
		}
Ejemplo n.º 18
0
		private void GetPartLayerAttributes(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_NodeId partID, HEU_VolumeLayer layer)
		{
			// Get the tile index, if it exists, for this part
			HAPI_AttributeInfo tileAttrInfo = new HAPI_AttributeInfo();
			int[] tileAttrData = new int[0];
			HEU_GeneralUtility.GetAttribute(session, geoID, partID, "tile", ref tileAttrInfo, ref tileAttrData, session.GetAttributeIntData);
			if (tileAttrData != null && tileAttrData.Length > 0)
			{
				layer._tile = tileAttrData[0];
				//Debug.LogFormat("Tile: {0}", tileAttrData[0]);
			}
			else
			{
				layer._tile = 0;
			}

			// Get the layer textures, and other layer values from attributes

			Texture2D defaultTexture = LoadDefaultSplatTexture();

			if (!IsLayerFieldOverriden(layer, HEU_VolumeLayer.Overrides.Diffuse) && (layer._diffuseTexture == null || layer._diffuseTexture == defaultTexture))
			{
				layer._diffuseTexture = LoadLayerTextureFromAttribute(session, geoID, partID, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TEXTURE_DIFFUSE_ATTR);

				if (layer._diffuseTexture == null)
				{
					layer._diffuseTexture = defaultTexture;
				}
			}

			if (!IsLayerFieldOverriden(layer, HEU_VolumeLayer.Overrides.Mask) && layer._maskTexture == null)
			{
				layer._maskTexture = LoadLayerTextureFromAttribute(session, geoID, partID, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TEXTURE_MASK_ATTR);
			}

			if (!IsLayerFieldOverriden(layer, HEU_VolumeLayer.Overrides.Normal) && layer._normalTexture == null)
			{
				layer._normalTexture = LoadLayerTextureFromAttribute(session, geoID, partID, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TEXTURE_NORMAL_ATTR);
			}

			if (!IsLayerFieldOverriden(layer, HEU_VolumeLayer.Overrides.NormalScale))
			{
				LoadLayerFloatFromAttribute(session, geoID, partID, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_NORMAL_SCALE_ATTR, ref layer._normalScale);
			}

			if (!IsLayerFieldOverriden(layer, HEU_VolumeLayer.Overrides.Metallic))
			{
				LoadLayerFloatFromAttribute(session, geoID, partID, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_METALLIC_ATTR, ref layer._metallic);
			}

			if (!IsLayerFieldOverriden(layer, HEU_VolumeLayer.Overrides.Smoothness))
			{
				LoadLayerFloatFromAttribute(session, geoID, partID, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_SMOOTHNESS_ATTR, ref layer._smoothness);
			}

			if (!IsLayerFieldOverriden(layer, HEU_VolumeLayer.Overrides.Specular))
			{
				LoadLayerColorFromAttribute(session, geoID, partID, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_SPECULAR_ATTR, ref layer._specularColor);
			}

			if (!IsLayerFieldOverriden(layer, HEU_VolumeLayer.Overrides.TileOffset))
			{
				LoadLayerVector2FromAttribute(session, geoID, partID, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TILE_OFFSET_ATTR, ref layer._tileOffset);
			}

			if (!IsLayerFieldOverriden(layer, HEU_VolumeLayer.Overrides.TileSize))
			{
				LoadLayerVector2FromAttribute(session, geoID, partID, HEU_Defines.DEFAULT_UNITY_HEIGHTFIELD_TILE_SIZE_ATTR, ref layer._tileSize);
			}
		}
Ejemplo n.º 19
0
	/// <summary>
	/// Generates object instances.
	/// Skips parts that already have their instances generated.
	/// </summary>
	/// <param name="session">Active session to use</param>
	public void GenerateObjectInstances(HEU_SessionBase session)
	{
	    if (!IsInstancer())
	    {
		Debug.LogErrorFormat("Generate object instances called on a non-instancer object {0} for asset {1}!", ObjectName, ParentAsset.AssetName);
		return;
	    }

	    //Debug.LogFormat("Generate Object Instances:: 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);

	    // Is this a Houdini attribute instancer?
	    string instanceAttrName = HEU_PluginSettings.InstanceAttr;
	    string unityInstanceAttrName = HEU_PluginSettings.UnityInstanceAttr;
	    string instancePrefixAttrName = HEU_Defines.DEFAULT_INSTANCE_PREFIX_ATTR;

	    HAPI_AttributeInfo instanceAttrInfo = new HAPI_AttributeInfo();
	    HAPI_AttributeInfo unityInstanceAttrInfo = new HAPI_AttributeInfo();
	    HAPI_AttributeInfo instancePrefixAttrInfo = new HAPI_AttributeInfo();

	    int numGeos = _geoNodes.Count;
	    for (int i = 0; i < numGeos; ++i)
	    {
		if (_geoNodes[i].Displayable)
		{
		    List<HEU_PartData> parts = _geoNodes[i].GetParts();
		    int numParts = parts.Count;
		    for (int j = 0; j < numParts; ++j)
		    {
			if (parts[j].ObjectInstancesBeenGenerated || parts[j].IsPartVolume())
			{
			    // This prevents instances being created unnecessarily (e.g. part hasn't changed since last cook).
			    // Or for volumes that might have instance attributes.
			    continue;
			}

			HEU_GeneralUtility.GetAttributeInfo(session, _geoNodes[i].GeoID, parts[j].PartID, instanceAttrName, ref instanceAttrInfo);
			HEU_GeneralUtility.GetAttributeInfo(session, _geoNodes[i].GeoID, parts[j].PartID, unityInstanceAttrName, ref unityInstanceAttrInfo);

			string[] instancePrefixes = null;
			HEU_GeneralUtility.GetAttributeInfo(session, _geoNodes[i].GeoID, parts[j].PartID, instancePrefixAttrName, ref instancePrefixAttrInfo);
			if (instancePrefixAttrInfo.exists)
			{
			    instancePrefixes = HEU_GeneralUtility.GetAttributeStringData(session, _geoNodes[i].GeoID, parts[j].PartID, instancePrefixAttrName, ref instancePrefixAttrInfo);
			}

			// Must clear out instances, as otherwise we get duplicates
			parts[j].ClearInstances();

			// Clear out invalid object instance infos that no longer have any valid parts
			parts[j].ClearInvalidObjectInstanceInfos();

			if (instanceAttrInfo.exists)
			{
			    // Object instancing via Houdini instance attribute

			    parts[j].GenerateInstancesFromObjectIds(session, instancePrefixes);
			}
			else if (unityInstanceAttrInfo.exists)
			{
			    // Object instancing via existing Unity object (path from point attribute)

			    // Attribute owner type determines whether to use single instanced object (detail) or multiple (point)
			    if (unityInstanceAttrInfo.owner == HAPI_AttributeOwner.HAPI_ATTROWNER_POINT)
			    {
				parts[j].GenerateInstancesFromUnityAssetPathAttribute(session, unityInstanceAttrName);
			    }
			    else if (unityInstanceAttrInfo.owner == HAPI_AttributeOwner.HAPI_ATTROWNER_DETAIL)
			    {
				bool bInstanced = false;
				int[] scriptAttr = new int[unityInstanceAttrInfo.count];
				HEU_GeneralUtility.GetAttribute(session, _geoNodes[i].GeoID, parts[j].PartID, unityInstanceAttrName, ref unityInstanceAttrInfo, ref scriptAttr, session.GetAttributeStringData);
				if (unityInstanceAttrInfo.exists)
				{
				    string assetPath = HEU_SessionManager.GetString(scriptAttr[0]);
				    if (!string.IsNullOrEmpty(assetPath))
				    {
					parts[j].GenerateInstancesFromUnityAssetPath(session, assetPath, instancePrefixes);
					bInstanced = true;
				    }
				}

				if (!bInstanced)
				{
				    Debug.LogWarningFormat("Unable to get instanced object path from detail instance attribute!");
				}
			    }
			    else
			    {
				// Other attribute owned types are unsupported.
				// Originally had a warning here, but unnecessary as in some cases (e.g. heightfield attrbiutes) the
				// attribute owner could be changed in HAPI.
			    }
			}
			else
			{
			    // Standard object instancing via single Houdini object

			    if (_objectInfo.objectToInstanceId == HEU_Defines.HEU_INVALID_NODE_ID)
			    {
				Debug.LogAssertionFormat("Invalid object ID {0} used for object instancing. "
					+ "Make sure to turn on Full point instancing and set the correct Instance Object.", _objectInfo.objectToInstanceId);
				continue;
			    }

			    parts[j].GenerateInstancesFromObjectID(session, _objectInfo.objectToInstanceId, instancePrefixes);
			}
		    }
		}
	    }
	}
Ejemplo n.º 20
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;
		}
Ejemplo n.º 21
0
		public bool PopulateGeometryData(HEU_SessionBase session)
		{
			// Get vertex position
			HAPI_AttributeInfo posAttrInfo = new HAPI_AttributeInfo();
			_posAttr = new float[0];
			HEU_GeneralUtility.GetAttribute(session, GeoID, PartID, HEU_Defines.HAPI_ATTRIB_POSITION, ref posAttrInfo, ref _posAttr, session.GetAttributeFloatData);
			if (!posAttrInfo.exists)
			{
				return false;
			}
			else if (posAttrInfo.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_POINT)
			{
				Debug.LogErrorFormat("{0} only supports position as POINT attribute. Position attribute of {1} type not supported!", HEU_Defines.HEU_PRODUCT_NAME, posAttrInfo.owner);
				return false;
			}

			// Get UV attributes
			_uvAttrInfo = new HAPI_AttributeInfo();
			_uvAttrInfo.tupleSize = 2;
			_uvAttr = new float[0];
			HEU_GeneralUtility.GetAttribute(session, GeoID, PartID, HEU_Defines.HAPI_ATTRIB_UV, ref _uvAttrInfo, ref _uvAttr, session.GetAttributeFloatData);

			// Get UV2 attributes
			_uv2AttrInfo = new HAPI_AttributeInfo();
			_uv2AttrInfo.tupleSize = 2;
			_uv2Attr = new float[0];
			HEU_GeneralUtility.GetAttribute(session, GeoID, PartID, HEU_Defines.HAPI_ATTRIB_UV2, ref _uv2AttrInfo, ref _uv2Attr, session.GetAttributeFloatData);

			// Get UV3 attributes
			_uv3AttrInfo = new HAPI_AttributeInfo();
			_uv3AttrInfo.tupleSize = 2;
			_uv3Attr = new float[0];
			HEU_GeneralUtility.GetAttribute(session, GeoID, PartID, HEU_Defines.HAPI_ATTRIB_UV3, ref _uv3AttrInfo, ref _uv3Attr, session.GetAttributeFloatData);

			// Get normal attributes
			_normalAttrInfo = new HAPI_AttributeInfo();
			_normalAttr = new float[0];
			HEU_GeneralUtility.GetAttribute(session, GeoID, PartID, HEU_Defines.HAPI_ATTRIB_NORMAL, ref _normalAttrInfo, ref _normalAttr, session.GetAttributeFloatData);

			// Get colour attributes
			_colorAttrInfo = new HAPI_AttributeInfo();
			_colorAttr = new float[0];
			HEU_GeneralUtility.GetAttribute(session, GeoID, PartID, HEU_Defines.HAPI_ATTRIB_COLOR, ref _colorAttrInfo, ref _colorAttr, session.GetAttributeFloatData);

			// Get alpha attributes
			_alphaAttrInfo = new HAPI_AttributeInfo();
			_alphaAttr = new float[0];
			HEU_GeneralUtility.GetAttribute(session, GeoID, PartID, HEU_Defines.HAPI_ATTRIB_ALPHA, ref _alphaAttrInfo, ref _alphaAttr, session.GetAttributeFloatData);

			// Get tangent attributes
			_tangentAttrInfo = new HAPI_AttributeInfo();
			_tangentAttr = new float[0];
			HEU_GeneralUtility.GetAttribute(session, GeoID, PartID, HEU_Defines.HAPI_ATTRIB_TANGENT, ref _tangentAttrInfo, ref _tangentAttr, session.GetAttributeFloatData);

			// Warn user since we are splitting points by attributes, might prevent some attrributes
			// to be transferred over properly
			if (_normalAttrInfo.exists && _normalAttrInfo.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_POINT
									&& _normalAttrInfo.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_VERTEX)
			{
				Debug.LogWarningFormat("{0}: Normals are not declared as point or vertex attributes.\nSet them as per point or vertices in HDA.", _partName);
			}

			if (_tangentAttrInfo.exists && _tangentAttrInfo.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_POINT
									&& _tangentAttrInfo.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_VERTEX)
			{
				Debug.LogWarningFormat("{0}: Tangents are not declared as point or vertex attributes.\nSet them as per point or vertices in HDA.", _partName);
			}

			if (_colorAttrInfo.exists && _colorAttrInfo.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_POINT
									&& _colorAttrInfo.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_VERTEX)
			{
				Debug.LogWarningFormat("{0}: Colours are not declared as point or vertex attributes."
					+ "\nCurrently set as owner type {1}. Set them as per point or vertices in HDA.", _partName, _colorAttrInfo.owner);
			}

			_groups = HEU_SessionManager.GetGroupNames(GeoID, HAPI_GroupType.HAPI_GROUPTYPE_PRIM);

			_allCollisionVertexList = new int[_vertexList.Length];
			_allCollisionFaceIndices = new int[_partInfo.faceCount];

			_hasGroupGeometry = false;

			// We go through each group, building up a triangle list of indices that belong to it
			// For strictly colliders (ie. non-rendering), we only create geometry colliders 
			for (int g = 0; g < _groups.Length; ++g)
			{
				string groupName = _groups[g];

				// Query HAPI to get the group membership. 
				// This is returned as an array of 1s for vertices that belong to this group.
				int[] membership = null;
				HEU_SessionManager.GetGroupMembership(session, GeoID, PartID, HAPI_GroupType.HAPI_GROUPTYPE_PRIM, groupName, ref membership);

				bool bIsCollidable = groupName.Contains(HEU_PluginSettings.CollisionGroupName);
				bool bIsRenderCollidable = groupName.Contains(HEU_PluginSettings.RenderedCollisionGroupName);

				if (bIsCollidable || bIsRenderCollidable)
				{
					// Extract vertex indices for this collision group

					int[] groupVertexList = new int[_vertexList.Length];
					groupVertexList.Init<int>(-1);

					int groupVertexListCount = 0;

					List<int> allFaceList = new List<int>();
					for (int f = 0; f < membership.Length; ++f)
					{
						if (membership[f] > 0)
						{
							// This face is a member of the specified group

							allFaceList.Add(f);

							groupVertexList[f * 3 + 0] = _vertexList[f * 3 + 0];
							groupVertexList[f * 3 + 1] = _vertexList[f * 3 + 1];
							groupVertexList[f * 3 + 2] = _vertexList[f * 3 + 2];

							// Mark vertices as used
							_allCollisionVertexList[f * 3 + 0] = 1;
							_allCollisionVertexList[f * 3 + 1] = 1;
							_allCollisionVertexList[f * 3 + 2] = 1;

							// Mark face as used
							_allCollisionFaceIndices[f] = 1;

							groupVertexListCount += 3;
						}
					}

					if (groupVertexListCount > 0)
					{
						_groupSplitVertexIndices.Add(groupName, groupVertexList);
						_groupSplitFaceIndices.Add(groupName, allFaceList);

						_hasGroupGeometry = true;

						//Debug.Log("Adding collision group: " + groupName + " with index count: " + _groupVertexList.Length);
					}
				}
			}

			if (_hasGroupGeometry)
			{
				// Construct vertex list for all other vertices that are not part of collision geometry
				int[] remainingGroupSplitFaces = new int[_vertexList.Length];
				remainingGroupSplitFaces.Init<int>(-1);
				bool bMainSplitGroup = false;

				List<int> remainingGroupSplitFaceIndices = new List<int>();

				for (int cv = 0; cv < _allCollisionVertexList.Length; ++cv)
				{
					if (_allCollisionVertexList[cv] == 0)
					{
						// Unused index, so add it to unused vertex list
						remainingGroupSplitFaces[cv] = _vertexList[cv];
						bMainSplitGroup = true;
					}
				}

				for (int cf = 0; cf < _allCollisionFaceIndices.Length; ++cf)
				{
					if (_allCollisionFaceIndices[cf] == 0)
					{
						remainingGroupSplitFaceIndices.Add(cf);
					}
				}

				if (bMainSplitGroup)
				{
					_groupSplitVertexIndices.Add(HEU_Defines.HEU_DEFAULT_GEO_GROUP_NAME, remainingGroupSplitFaces);
					_groupSplitFaceIndices.Add(HEU_Defines.HEU_DEFAULT_GEO_GROUP_NAME, remainingGroupSplitFaceIndices);

					//Debug.Log("Adding remaining group with index count: " + remainingGroupSplitFaces.Length);
				}
			}
			else
			{
				_groupSplitVertexIndices.Add(HEU_Defines.HEU_DEFAULT_GEO_GROUP_NAME, _vertexList);

				List<int> allFaces = new List<int>();
				for (int f = 0; f < _partInfo.faceCount; ++f)
				{
					allFaces.Add(f);
				}
				_groupSplitFaceIndices.Add(HEU_Defines.HEU_DEFAULT_GEO_GROUP_NAME, allFaces);

				//Debug.Log("Adding single non-group with index count: " + _vertexList.Length);
			}

			// We'll be generating the normals if they're not provided by Houdini
			// For every vertex, we'll hold list of other vertices that it shares faces with (ie. connected to)
			_sharedNormalIndices = null;
			_cosineThreshold = 0f;
			if (!_normalAttrInfo.exists)
			{
				_sharedNormalIndices = new List<VertexEntry>[_vertexList.Length];
				_cosineThreshold = Mathf.Cos(HEU_PluginSettings.NormalGenerationThresholdAngle * Mathf.Deg2Rad);

				for (int i = 0; i < _vertexList.Length; ++i)
				{
					_sharedNormalIndices[i] = new List<VertexEntry>();
				}
			}

			return true;
		}
Ejemplo n.º 22
0
		private void PopulateAttributeData(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID, HEU_AttributeData attributeData, ref HAPI_AttributeInfo attributeInfo)
		{
			attributeData._attributeInfo = attributeInfo;

			int tupleSize = attributeInfo.tupleSize;
			int attributeCount = attributeInfo.count;
			int arraySize = attributeCount * tupleSize;

			// First reset arrays if the type had changed since last sync
			if ((attributeInfo.storage == HAPI_StorageType.HAPI_STORAGETYPE_INT && attributeData._attributeType != HEU_AttributeData.AttributeType.INT) ||
				(attributeInfo.storage == HAPI_StorageType.HAPI_STORAGETYPE_FLOAT && attributeData._attributeType != HEU_AttributeData.AttributeType.FLOAT) ||
				(attributeInfo.storage == HAPI_StorageType.HAPI_STORAGETYPE_STRING && attributeData._attributeType != HEU_AttributeData.AttributeType.STRING))
			{
				// Reset arrays if type is different
				attributeData._floatValues = null;
				attributeData._stringValues = null;
				attributeData._intValues = null;

				attributeData._attributeState = HEU_AttributeData.AttributeState.INVALID;

				if(attributeInfo.storage == HAPI_StorageType.HAPI_STORAGETYPE_INT)
				{
					attributeData._attributeType = HEU_AttributeData.AttributeType.INT;
				}
				else if (attributeInfo.storage == HAPI_StorageType.HAPI_STORAGETYPE_FLOAT)
				{
					attributeData._attributeType = HEU_AttributeData.AttributeType.FLOAT;
				}
				else if (attributeInfo.storage == HAPI_StorageType.HAPI_STORAGETYPE_STRING)
				{
					attributeData._attributeType = HEU_AttributeData.AttributeType.STRING;
				}
			}

			// Make sure the internal array is correctly sized for syncing.
			if (attributeData._attributeType == HEU_AttributeData.AttributeType.INT)
			{
				if (attributeData._intValues == null)
				{
					attributeData._intValues = new int[arraySize];
					attributeData._attributeState = HEU_AttributeData.AttributeState.INVALID;
				}
				else if (attributeData._intValues.Length != arraySize)
				{
					System.Array.Resize<int>(ref attributeData._intValues, arraySize);
					attributeData._attributeState = HEU_AttributeData.AttributeState.INVALID;
				}
				attributeData._floatValues = null;
				attributeData._stringValues = null;

				if (attributeData._attributeState == HEU_AttributeData.AttributeState.INVALID)
				{
					int[] data = new int[0];
					HEU_GeneralUtility.GetAttribute(session, geoID, partID, attributeData._name, ref attributeInfo, ref data, session.GetAttributeIntData);
					for (int i = 0; i < attributeCount; ++i)
					{
						for (int tuple = 0; tuple < tupleSize; ++tuple)
						{
							attributeData._intValues[i * tupleSize + tuple] = data[i * tupleSize + tuple];
						}
					}
				}
			}
			else if (attributeData._attributeType == HEU_AttributeData.AttributeType.FLOAT)
			{
				if (attributeData._floatValues == null)
				{
					attributeData._floatValues = new float[arraySize];
					attributeData._attributeState = HEU_AttributeData.AttributeState.INVALID;
				}
				else if (attributeData._floatValues.Length != arraySize)
				{
					System.Array.Resize<float>(ref attributeData._floatValues, arraySize);
					attributeData._attributeState = HEU_AttributeData.AttributeState.INVALID;
				}
				attributeData._intValues = null;
				attributeData._stringValues = null;

				if (attributeData._attributeState == HEU_AttributeData.AttributeState.INVALID)
				{
					float[] data = new float[0];
					HEU_GeneralUtility.GetAttribute(session, geoID, partID, attributeData._name, ref attributeInfo, ref data, session.GetAttributeFloatData);
					for (int i = 0; i < attributeCount; ++i)
					{
						for (int tuple = 0; tuple < tupleSize; ++tuple)
						{
							attributeData._floatValues[i * tupleSize + tuple] = data[i * tupleSize + tuple];
						}
					}
				}
			}
			else if (attributeData._attributeType == HEU_AttributeData.AttributeType.STRING)
			{
				if (attributeData._stringValues == null)
				{
					attributeData._stringValues = new string[arraySize];
					attributeData._attributeState = HEU_AttributeData.AttributeState.INVALID;
				}
				else if (attributeData._stringValues.Length != arraySize)
				{
					System.Array.Resize<string>(ref attributeData._stringValues, arraySize);
					attributeData._attributeState = HEU_AttributeData.AttributeState.INVALID;
				}
				attributeData._intValues = null;
				attributeData._floatValues = null;

				if (attributeData._attributeState == HEU_AttributeData.AttributeState.INVALID)
				{
					HAPI_StringHandle[] data = new HAPI_StringHandle[0];
					HEU_GeneralUtility.GetAttribute(session, geoID, partID, attributeData._name, ref attributeInfo, ref data, session.GetAttributeStringData);
					for (int i = 0; i < attributeCount; ++i)
					{
						for (int tuple = 0; tuple < tupleSize; ++tuple)
						{
							HAPI_StringHandle stringHandle = data[i * tupleSize + tuple];
							attributeData._stringValues[i * tupleSize + tuple] = HEU_SessionManager.GetString(stringHandle, session);
						}
					}
				}
			}

			SetAttributeDataSyncd(attributeData);
		}
Ejemplo n.º 23
0
		public void PopulateUnityMaterialData(HEU_SessionBase session)
		{
			// First we look for Unity and Substance material attributes on faces.
			// We fill up the following dictionary with unique Unity + Substance material information
			_unityMaterialInfos = new Dictionary<int, HEU_UnityMaterialInfo>();

			_unityMaterialAttrInfo = new HAPI_AttributeInfo();
			_unityMaterialAttrName = new HAPI_StringHandle[0];
			HEU_GeneralUtility.GetAttribute(session, GeoID, PartID, HEU_PluginSettings.UnityMaterialAttribName, ref _unityMaterialAttrInfo, ref _unityMaterialAttrName, session.GetAttributeStringData);

			// Store a local copy of the actual string values since the indices get overwritten by the next call to session.GetAttributeStringData.
			// Using a dictionary to only query the unique strings, as doing all of them is very slow and unnecessary.
			_unityMaterialAttrStringsMap = new Dictionary<HAPI_StringHandle, string>();
			foreach (HAPI_StringHandle strHandle in _unityMaterialAttrName)
			{
				if (!_unityMaterialAttrStringsMap.ContainsKey(strHandle))
				{
					string materialName = HEU_SessionManager.GetString(strHandle, session);
					if (string.IsNullOrEmpty(materialName))
					{
						// Warn user of empty string, but add it anyway to our map so we don't keep trying to parse it
						Debug.LogWarningFormat("Found empty material attribute value for part {0}.", _partName);
					}
					_unityMaterialAttrStringsMap.Add(strHandle, materialName);
					//Debug.LogFormat("Added Unity material: " + materialName);
				}
			}

			_substanceMaterialAttrNameInfo = new HAPI_AttributeInfo();
			_substanceMaterialAttrName = new HAPI_StringHandle[0];
			HEU_GeneralUtility.GetAttribute(session, GeoID, PartID, HEU_PluginSettings.UnitySubMaterialAttribName, ref _substanceMaterialAttrNameInfo, ref _substanceMaterialAttrName, session.GetAttributeStringData);

			_substanceMaterialAttrStringsMap = new Dictionary<HAPI_StringHandle, string>();
			foreach (HAPI_StringHandle strHandle in _substanceMaterialAttrName)
			{
				if (!_substanceMaterialAttrStringsMap.ContainsKey(strHandle))
				{
					string substanceName = HEU_SessionManager.GetString(strHandle, session);
					if (string.IsNullOrEmpty(substanceName))
					{
						// Warn user of empty string, but add it anyway to our map so we don't keep trying to parse it
						Debug.LogWarningFormat("Found invalid substance material attribute value ({0}) for part {1}.",
							_partName, substanceName);
					}
					_substanceMaterialAttrStringsMap.Add(strHandle, substanceName);
					//Debug.LogFormat("Added Substance material: " + substanceName);
				}
			}

			_substanceMaterialAttrIndexInfo = new HAPI_AttributeInfo();
			_substanceMaterialAttrIndex = new int[0];
			HEU_GeneralUtility.GetAttribute(session, GeoID, PartID, HEU_PluginSettings.UnitySubMaterialIndexAttribName, ref _substanceMaterialAttrIndexInfo, ref _substanceMaterialAttrIndex, session.GetAttributeIntData);


			if (_unityMaterialAttrInfo.exists)
			{
				if (_unityMaterialAttrInfo.owner == HAPI_AttributeOwner.HAPI_ATTROWNER_DETAIL && _unityMaterialAttrName.Length > 0)
				{
					CreateMaterialInfoEntryFromAttributeIndex(this, 0);

					// Detail unity material attribute means we can treat it as single material
					_singleFaceUnityMaterial = true;
				}
				else
				{
					for(HAPI_StringHandle i = 0; i < _unityMaterialAttrName.Length; ++i)
					{
						CreateMaterialInfoEntryFromAttributeIndex(this, i);
					}
				}
			}
		}