Exemplo n.º 1
0
	private HEU_GeoNode CreateGeoNode(HEU_SessionBase session, HAPI_GeoInfo geoInfo)
	{
	    HEU_GeoNode geoNode = ScriptableObject.CreateInstance<HEU_GeoNode>();
	    geoNode.Initialize(session, geoInfo, this);
	    geoNode.UpdateGeo(session);
	    return geoNode;
	}
        public void Initialize(HEU_SessionBase session, HAPI_GeoInfo geoInfo, HEU_ObjectNode containerObjectNode)
        {
            _containerObjectNode = containerObjectNode;
            _geoInfo             = geoInfo;
            _geoName             = HEU_SessionManager.GetString(_geoInfo.nameSH, session);

            //Debug.Log(string.Format("GeoNode initialized with ID={0}, name={1}, type={2}", GeoID, GeoName, geoInfo.type));
        }
Exemplo n.º 3
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();
		}
        public void Reset()
        {
            _geoName = "";

            _geoInfo        = new HAPI_GeoInfo();
            _geoInfo.nodeId = -1;
            _geoInfo.type   = HAPI_GeoType.HAPI_GEOTYPE_DEFAULT;
            _parts          = new List <HEU_PartData>();
        }
Exemplo n.º 5
0
		private HAPI_NodeId GetDisplayNodeID(HAPI_NodeId objNodeID)
		{
			HAPI_GeoInfo displayGeoInfo = new HAPI_GeoInfo();
			if (_session.GetDisplayGeoInfo(objNodeID, ref displayGeoInfo))
			{
				return displayGeoInfo.nodeId;
			}

			return HEU_Defines.HEU_INVALID_NODE_ID;
		}
        public void SetGeoInfo(HAPI_GeoInfo geoInfo)
        {
            _geoInfo = geoInfo;

            // Also update input node ID in case of this node
            // being recreated in new session with a different GeoID
            if (_inputNode != null)
            {
                _inputNode.SetInputNodeID(GeoID);
            }
        }
Exemplo n.º 7
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;
		}
Exemplo n.º 8
0
        /// <summary>
        /// Helper to set heightfield data for a specific volume node.
        /// Used for a specific terrain layer.
        /// </summary>
        /// <param name="session">Session that the volume node resides in.</param>
        /// <param name="volumeNodeID">ID of the target volume node</param>
        /// <param name="partID">Part ID</param>
        /// <param name="heightValues">Array of height or alpha values</param>
        /// <param name="heightFieldName">Name of the layer</param>
        /// <returns>True if successfully uploaded heightfield values</returns>
        public bool SetHeightFieldData(HEU_SessionBase session, HAPI_NodeId volumeNodeID, HAPI_PartId partID, float[] heightValues, string heightFieldName, ref HAPI_VolumeInfo baseVolumeInfo)
        {
            // Cook the node to get infos below
            if (!session.CookNode(volumeNodeID, false))
            {
                return(false);
            }

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

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

            HAPI_PartInfo partInfo = new HAPI_PartInfo();

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

            HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo();

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

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

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

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

            return(true);
        }
Exemplo n.º 9
0
        public static bool CreateAndCookInputAsset(HEU_SessionBase session, string assetName, bool bCookTemplatedGeos, out HAPI_NodeId newAssetID)
        {
            newAssetID = HEU_Defines.HEU_INVALID_NODE_ID;
            if (!session.CreateInputNode(out newAssetID, null))
            {
                return(false);
            }

            // Make sure cooking is successfull before proceeding. Any licensing or file data issues will be caught here.
            if (!HEU_HAPIUtility.ProcessHoudiniCookStatus(session, assetName))
            {
                return(false);
            }

            // In case the cooking wasn't done previously, force it now.
            bool bResult = HEU_HAPIUtility.CookNodeInHoudini(session, newAssetID, bCookTemplatedGeos, assetName);

            if (!bResult)
            {
                // When cook failed, deleted the node created earlier
                session.DeleteNode(newAssetID);
                newAssetID = HEU_Defines.HEU_INVALID_NODE_ID;
                return(false);
            }

            // After cooking, set an empty partinfo
            HAPI_GeoInfo inputGeoInfo = new HAPI_GeoInfo();

            if (!session.GetDisplayGeoInfo(newAssetID, ref inputGeoInfo))
            {
                return(false);
            }

            HAPI_PartInfo newPart = new HAPI_PartInfo();

            newPart.init();
            newPart.id          = 0;
            newPart.vertexCount = 0;
            newPart.faceCount   = 0;
            newPart.pointCount  = 0;
            // TODO: always set to mesh type?
            newPart.type = HAPI_PartType.HAPI_PARTTYPE_MESH;

            if (!session.SetPartInfo(inputGeoInfo.nodeId, 0, ref newPart))
            {
                Debug.LogErrorFormat(HEU_Defines.HEU_NAME + ": Failed to set partinfo for input node!");
                return(false);
            }

            return(true);
        }
        internal void Initialize(HEU_SessionBase session, HAPI_GeoInfo geoInfo, HEU_ObjectNode containerObjectNode)
        {
            _containerObjectNode = containerObjectNode;
            _geoInfo             = geoInfo;

            string realName = HEU_SessionManager.GetString(_geoInfo.nameSH, session);

            if (!HEU_PluginSettings.ShortenFolderPaths || realName.Length < 3)
            {
                _geoName = HEU_SessionManager.GetString(_geoInfo.nameSH, session);
            }
            else
            {
                _geoName = realName.Substring(0, 3) + this.GetHashCode();
            }

            //HEU_Logger.Log(string.Format("GeoNode initialized with ID={0}, name={1}, type={2}", GeoID, GeoName, geoInfo.type));
        }
Exemplo n.º 11
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;
		}
	protected virtual bool LoadObjectBuffers(HEU_SessionBase session, ref HAPI_ObjectInfo objectInfo)
	{
	    // Get display SOP geo info and cook the node
	    HAPI_GeoInfo displayGeoInfo = new HAPI_GeoInfo();
	    if (!_session.GetDisplayGeoInfo(objectInfo.nodeId, ref displayGeoInfo))
	    {
		return false;
	    }

	    if (!CookNode(session, displayGeoInfo.nodeId))
	    {
		return false;
	    }

	    bool bResult = true;
	    bool bHasInstancer = false;

	    HEU_LoadObject obj = new HEU_LoadObject();
	    obj._objectNodeID = objectInfo.nodeId;
	    obj._displayNodeID = displayGeoInfo.nodeId;

	    if (LoadNodeBuffer(session, obj._displayNodeID, obj))
	    {
		_loadData._loadedObjects.Add(obj);
		
		if (!bHasInstancer && obj._instancerBuffers != null && obj._instancerBuffers.Count > 0)
		{
		    bHasInstancer = true;
		}
	    }
	    else
	    {
		bResult = false;
	    }

	    if (bResult && bHasInstancer)
	    {
		BuildBufferIDsMap(_loadData);
	    }

	    return bResult;
	}
Exemplo n.º 13
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;
		}
Exemplo n.º 14
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);
		}
Exemplo n.º 15
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;
		}
Exemplo n.º 16
0
		/// <summary>
		/// Upload the given list of mesh data in uploadMeshes into node with inputNodeID.
		/// If the source was a LOD group, then group names are assigned to the geometry.
		/// </summary>
		/// <param name="session">Session to upload to</param>
		/// <param name="inputNodeID">The ID of the input node to upload into</param>
		/// <param name="uploadMeshes">List of mesh data</param>
		/// <param name="bHasLODGroup">Whether the source was a LOD group and therefore treat it specially</param>
		/// <returns></returns>
		public static bool UploadInputMeshData(HEU_SessionBase session, HAPI_NodeId inputNodeID, List<HEU_UploadMeshData> uploadMeshes, bool bHasLODGroup)
		{
			List<Vector3> vertices = new List<Vector3>();
			List<Vector3> normals = new List<Vector3>();
			List<Vector2> uvs = new List<Vector2>();
			List<Color> colors = new List<Color>();

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

			int numMaterials = 0;

			// Accumulate vertices, normals, uvs, colors, and indices.
			// Keep track of indices start and count for each mesh for later when uploading material assignments and groups.
			// Indices need to be reindexed with vertex offset as we accumulate vertices.
			int numMeshes = uploadMeshes.Count;
			for (int i = 0; i < numMeshes; ++i)
			{
				int vertexOffset = vertices.Count;
				vertices.AddRange(uploadMeshes[i]._mesh.vertices);

				normals.AddRange(uploadMeshes[i]._mesh.normals);
				uvs.AddRange(uploadMeshes[i]._mesh.uv);
				colors.AddRange(uploadMeshes[i]._mesh.colors);

				uploadMeshes[i]._indexStart = new uint[uploadMeshes[i]._numSubMeshes];
				uploadMeshes[i]._indexCount = new uint[uploadMeshes[i]._numSubMeshes];

				for (int j = 0; j < uploadMeshes[i]._numSubMeshes; ++j)
				{
					int indexStart = triIndexList.Count;

					// Indices have to be re-indexed with our own offset
					int[] meshIndices = uploadMeshes[i]._mesh.GetTriangles(j);
					int numIndices = meshIndices.Length;
					for (int k = 0; k < numIndices; ++k)
					{
						triIndexList.Add(vertexOffset + meshIndices[k]);
					}

					uploadMeshes[i]._indexStart[j] = (uint)indexStart;
					uploadMeshes[i]._indexCount[j] = (uint)(triIndexList.Count) - uploadMeshes[i]._indexStart[j];
				}

				numMaterials += uploadMeshes[i]._materials != null ? uploadMeshes[i]._materials.Length : 0;
			}

			// It is possible for some meshes to not have normals/uvs/colors while others do.
			// In the case where an attribute is missing on some meshes, we clear out those attributes so we don't upload
			// partial attribute data.
			int numVertices = vertices.Count;
			if (normals.Count != numVertices)
			{
				normals = null;
			}

			if (uvs.Count != numVertices)
			{
				uvs = null;
			}

			if (colors.Count != numVertices)
			{
				colors = null;
			}

			HAPI_PartInfo partInfo = new HAPI_PartInfo();
			partInfo.faceCount = triIndexList.Count / 3;
			partInfo.vertexCount = triIndexList.Count;
			partInfo.pointCount = vertices.Count;
			partInfo.pointAttributeCount = 1;
			partInfo.vertexAttributeCount = 0;
			partInfo.primitiveAttributeCount = 0;
			partInfo.detailAttributeCount = 0;

			if (normals != null && normals.Count > 0)
			{
				partInfo.vertexAttributeCount++;
			}

			if (uvs != null && uvs.Count > 0)
			{
				partInfo.vertexAttributeCount++;
			}

			if (colors != null && colors.Count > 0)
			{
				partInfo.vertexAttributeCount++;
			}

			if (numMaterials > 0)
			{
				partInfo.primitiveAttributeCount++;
			}

			if (numMeshes > 0)
			{
				partInfo.primitiveAttributeCount++;
			}

			if (bHasLODGroup)
			{
				partInfo.primitiveAttributeCount++;
				partInfo.detailAttributeCount++;
			}

			HAPI_GeoInfo displayGeoInfo = new HAPI_GeoInfo();
			if (!session.GetDisplayGeoInfo(inputNodeID, ref displayGeoInfo))
			{
				return false;
			}

			HAPI_NodeId displayNodeID = displayGeoInfo.nodeId;

			if (!session.SetPartInfo(displayNodeID, 0, ref partInfo))
			{
				return false;
			}

			int[] faceCounts = new int[partInfo.faceCount];
			for (int i = 0; i < partInfo.faceCount; ++i)
			{
				faceCounts[i] = 3;
			}

			int[] triIndices = triIndexList.ToArray();

			if (!HEU_GeneralUtility.SetArray2Arg(displayNodeID, 0, session.SetFaceCount, faceCounts, 0, partInfo.faceCount))
			{
				return false;
			}

			if (!HEU_GeneralUtility.SetArray2Arg(displayNodeID, 0, session.SetVertexList, triIndices, 0, partInfo.vertexCount))
			{
				return false;
			}

			if (!SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_POSITION, 3, vertices.ToArray(), ref partInfo, true))
			{
				return false;
			}

			//if(normals != null && !SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_NORMAL, 3, normals, ref partInfo, true))
			if (normals != null && !SetMeshVertexAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_NORMAL, 3, normals.ToArray(), triIndices, ref partInfo, true))
			{
				return false;
			}

			if (uvs != null && uvs.Count > 0)
			{
				Vector3[] uvs3 = new Vector3[uvs.Count];
				for (int i = 0; i < uvs.Count; ++i)
				{
					uvs3[i][0] = uvs[i][0];
					uvs3[i][1] = uvs[i][1];
					uvs3[i][2] = 0;
				}
				//if(!SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_UV, 3, uvs3, ref partInfo, false))
				if (!SetMeshVertexAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_UV, 3, uvs3, triIndices, ref partInfo, false))
				{
					return false;
				}
			}

			if (colors != null && colors.Count > 0)
			{
				Vector3[] rgb = new Vector3[colors.Count];
				float[] alpha = new float[colors.Count];
				for (int i = 0; i < colors.Count; ++i)
				{
					rgb[i][0] = colors[i].r;
					rgb[i][1] = colors[i].g;
					rgb[i][2] = colors[i].b;

					alpha[i] = colors[i].a;
				}

				//if(!SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_COLOR, 3, rgb, ref partInfo, false))
				if (!SetMeshVertexAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_COLOR, 3, rgb, triIndices, ref partInfo, false))
				{
					return false;
				}

				//if(!SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_ALPHA, 1, alpha, ref partInfo, false))
				if (!SetMeshVertexFloatAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_ALPHA, 1, alpha, triIndices, ref partInfo))
				{
					return false;
				}
			}

			// Set material names for round-trip perservation of material assignment
			// Each HEU_UploadMeshData might have a list of submeshes and materials
			// These are all combined into a single mesh, with group names
			if (numMaterials > 0)
			{
				bool bFoundAtleastOneValidMaterial = false;

				string[] materialIDs = new string[partInfo.faceCount];
				for (int g = 0; g < uploadMeshes.Count; ++g)
				{
					if (uploadMeshes[g]._numSubMeshes != uploadMeshes[g]._materials.Length)
					{
						// Number of submeshes should equal number of materials since materials determine submeshes
						continue;
					}

					for (int i = 0; i < uploadMeshes[g]._materials.Length; ++i)
					{
						string materialName = HEU_AssetDatabase.GetAssetPath(uploadMeshes[g]._materials[i]);
						if (materialName == null)
						{
							materialName = "";
						}
						else if (materialName.StartsWith(HEU_Defines.DEFAULT_UNITY_BUILTIN_RESOURCES))
						{
							materialName = HEU_AssetDatabase.GetUniqueAssetPathForUnityAsset(uploadMeshes[g]._materials[i]);
						}

						bFoundAtleastOneValidMaterial |= !string.IsNullOrEmpty(materialName);

						int faceStart = (int)uploadMeshes[g]._indexStart[i] / 3;
						int faceEnd = faceStart + ((int)uploadMeshes[g]._indexCount[i] / 3);
						for (int m = faceStart; m < faceEnd; ++m)
						{
							materialIDs[m] = materialName;
						}
					}
				}

				if (bFoundAtleastOneValidMaterial)
				{
					HAPI_AttributeInfo materialIDAttrInfo = new HAPI_AttributeInfo();
					materialIDAttrInfo.exists = true;
					materialIDAttrInfo.owner = HAPI_AttributeOwner.HAPI_ATTROWNER_PRIM;
					materialIDAttrInfo.storage = HAPI_StorageType.HAPI_STORAGETYPE_STRING;
					materialIDAttrInfo.count = partInfo.faceCount;
					materialIDAttrInfo.tupleSize = 1;
					materialIDAttrInfo.originalOwner = HAPI_AttributeOwner.HAPI_ATTROWNER_INVALID;

					if (!session.AddAttribute(displayNodeID, 0, HEU_PluginSettings.UnityMaterialAttribName, ref materialIDAttrInfo))
					{
						return false;
					}

					if (!session.SetAttributeStringData(displayNodeID, 0, HEU_PluginSettings.UnityMaterialAttribName, ref materialIDAttrInfo, materialIDs, 0, partInfo.faceCount))
					{
						return false;
					}
				}
			}

			// Set mesh name attribute
			HAPI_AttributeInfo attrInfo = new HAPI_AttributeInfo();
			attrInfo.exists = true;
			attrInfo.owner = HAPI_AttributeOwner.HAPI_ATTROWNER_PRIM;
			attrInfo.storage = HAPI_StorageType.HAPI_STORAGETYPE_STRING;
			attrInfo.count = partInfo.faceCount;
			attrInfo.tupleSize = 1;
			attrInfo.originalOwner = HAPI_AttributeOwner.HAPI_ATTROWNER_INVALID;

			if (session.AddAttribute(displayNodeID, 0, HEU_PluginSettings.UnityInputMeshAttr, ref attrInfo))
			{
				string[] primitiveNameAttr = new string[partInfo.faceCount];

				for (int g = 0; g < uploadMeshes.Count; ++g)
				{
					for (int i = 0; i < uploadMeshes[g]._numSubMeshes; ++i)
					{
						int faceStart = (int)uploadMeshes[g]._indexStart[i] / 3;
						int faceEnd = faceStart + ((int)uploadMeshes[g]._indexCount[i] / 3);
						for (int m = faceStart; m < faceEnd; ++m)
						{
							primitiveNameAttr[m] = uploadMeshes[g]._meshPath;
						}
					}
				}

				if (!session.SetAttributeStringData(displayNodeID, 0, HEU_PluginSettings.UnityInputMeshAttr, ref attrInfo, primitiveNameAttr, 0, partInfo.faceCount))
				{
					return false;
				}
			}
			else
			{
				return false;
			}

			// Set LOD group membership
			if (bHasLODGroup)
			{
				int[] membership = new int[partInfo.faceCount];

				for (int g = 0; g < uploadMeshes.Count; ++g)
				{
					if (g > 0)
					{
						// Clear array
						for (int m = 0; m < partInfo.faceCount; ++m)
						{
							membership[m] = 0;
						}
					}

					// Set 1 for faces belonging to this group
					for (int s = 0; s < uploadMeshes[g]._numSubMeshes; ++s)
					{
						int faceStart = (int)uploadMeshes[g]._indexStart[s] / 3;
						int faceEnd = faceStart + ((int)uploadMeshes[g]._indexCount[s] / 3);
						for (int m = faceStart; m < faceEnd; ++m)
						{
							membership[m] = 1;
						}
					}

					if (!session.AddGroup(displayNodeID, 0, HAPI_GroupType.HAPI_GROUPTYPE_PRIM, uploadMeshes[g]._meshName))
					{
						return false;
					}

					if (!session.SetGroupMembership(displayNodeID, 0, HAPI_GroupType.HAPI_GROUPTYPE_PRIM, uploadMeshes[g]._meshName, membership, 0, partInfo.faceCount))
					{
						return false;
					}
				}
			}

			return session.CommitGeo(displayNodeID);
		}
Exemplo n.º 17
0
		/// <summary>
		/// Returns the various geometry types (parts) from the given node.
		/// Only part instancers and point instancers (via attributes) are returned.
		/// </summary>
		private bool QueryParts(HAPI_NodeId nodeID, ref List<HAPI_PartInfo> meshParts, ref List<HAPI_PartInfo> volumeParts,
			ref List<HAPI_PartInfo> instancerParts, ref List<HAPI_PartInfo> curveParts, ref List<HAPI_PartInfo> scatterInstancerParts)
		{
			// Get display geo info
			HAPI_GeoInfo geoInfo = new HAPI_GeoInfo();
			if (!_session.GetGeoInfo(nodeID, ref geoInfo))
			{
				return false;
			}

			//Debug.LogFormat("GeoNode name:{0}, type: {1}, isTemplated: {2}, isDisplayGeo: {3}, isEditable: {4}, parts: {5}",
			//	HEU_SessionManager.GetString(geoInfo.nameSH, _session),
			//	geoInfo.type, geoInfo.isTemplated,
			//	geoInfo.isDisplayGeo, geoInfo.isEditable, geoInfo.partCount);

			if (geoInfo.type == HAPI_GeoType.HAPI_GEOTYPE_DEFAULT)
			{
				int numParts = geoInfo.partCount;
				for(int i = 0; i < numParts; ++i)
				{
					HAPI_PartInfo partInfo = new HAPI_PartInfo();
					if (!_session.GetPartInfo(geoInfo.nodeId, i, ref partInfo))
					{
						return false;
					}

					bool isAttribInstancer = false;
					bool isScatterInstancer = false;
					// Preliminary check for attribute instancing (mesh type with no verts but has points with instances)
					if (HEU_HAPIUtility.IsSupportedPolygonType(partInfo.type) && partInfo.vertexCount == 0 && partInfo.pointCount > 0)
					{
						if (HEU_GeneralUtility.HasValidInstanceAttribute(_session, nodeID, partInfo.id, HEU_PluginSettings.UnityInstanceAttr))
						{
							isAttribInstancer = true;
						}
						else if (HEU_GeneralUtility.HasValidInstanceAttribute(_session, nodeID, partInfo.id, HEU_Defines.HEIGHTFIELD_TREEINSTANCE_PROTOTYPEINDEX))
						{
							isScatterInstancer = true;
						}
					}

					if (isScatterInstancer)
					{
						scatterInstancerParts.Add(partInfo);
					}
					else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_VOLUME)
					{
						volumeParts.Add(partInfo);
					}
					else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_INSTANCER || isAttribInstancer)
					{
						instancerParts.Add(partInfo);
					}
					else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_CURVE)
					{
						curveParts.Add(partInfo);
					}
					else if(HEU_HAPIUtility.IsSupportedPolygonType(partInfo.type))
					{
						meshParts.Add(partInfo);
					}
					else
					{
						string partName = HEU_SessionManager.GetString(partInfo.nameSH, _session);
						SetLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Part {0} with type {1} is not supported for GeoSync.", partName, partInfo.type));
					}
				}
			}
			else if(geoInfo.type == HAPI_GeoType.HAPI_GEOTYPE_CURVE)
			{
				SetLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Currently {0} geo type is not implemented for threaded geo loading!", geoInfo.type));
			}

			return true;
		}
Exemplo n.º 18
0
		// GEOMETRY GETTERS -------------------------------------------------------------------------------------------

		/// <summary>
		/// Get the display geo (SOP) node inside an Object node. If there are multiple display SOP nodes, only
		/// the first one is returned.
		/// </summary>
		/// <param name="nodeID">Object node ID</param>
		/// <param name="geoInfo">Geo info to populate</param>
		/// <returns>True if successfully queried the geo info</returns>
		public virtual bool GetDisplayGeoInfo(HAPI_NodeId nodeID, ref HAPI_GeoInfo geoInfo, bool bLogError = false)
		{
			return false;
		}
Exemplo n.º 19
0
	/// <summary>
	/// Upload the inputData (mesh geometry) into the input node with inputNodeID.
	/// </summary>
	/// <param name="session">Session that the input node exists in</param>
	/// <param name="inputNodeID">ID of the input node</param>
	/// <param name="inputData">Container of the mesh geometry</param>
	/// <returns>True if successfully uploaded data</returns>
	public bool UploadData(HEU_SessionBase session, HAPI_NodeId inputNodeID, HEU_InputData inputData)
	{
	    HEU_InputDataMeshes inputDataMeshes = inputData as HEU_InputDataMeshes;
	    if (inputDataMeshes == null)
	    {
		Debug.LogError("Expected HEU_InputDataMeshes type for inputData, but received unsupported type.");
		return false;
	    }

	    List<Vector3> vertices = new List<Vector3>();
	    List<Vector3> normals = new List<Vector3>();
	    List<Color> colors = new List<Color>();

#if UNITY_2018_2_OR_NEWER
	    const int NumUVSets = 8;
#else
	    const int NumUVSets = 4;
#endif
	    List<Vector3>[] uvs = new List<Vector3>[NumUVSets];
	    for (int u = 0; u < NumUVSets; ++u)
	    {
		uvs[u] = new List<Vector3>();
	    }

	    // Use tempUVs to help with reindexing
	    List<Vector3>[] tempUVs = new List<Vector3>[NumUVSets];
	    for (int u = 0; u < NumUVSets; ++u)
	    {
		tempUVs[u] = new List<Vector3>();
	    }

	    List<int> pointIndexList = new List<int>();
	    List<int> vertIndexList = new List<int>();

	    int numMaterials = 0;

	    int numMeshes = inputDataMeshes._inputMeshes.Count;

	    // Get the parent's world transform, so when there are multiple child meshes,
	    // can merge and apply their local transform after subtracting their parent's world transform
	    Matrix4x4 rootInvertTransformMatrix = Matrix4x4.identity;
	    if (numMeshes > 1)
	    {
		rootInvertTransformMatrix = inputDataMeshes._inputObject.transform.worldToLocalMatrix;
	    }

	    // Always using the first submesh topology. This doesn't support mixed topology (triangles and quads).
	    MeshTopology meshTopology = inputDataMeshes._inputMeshes[0]._mesh.GetTopology(0);

	    int numVertsPerFace = 3;
	    if (meshTopology == MeshTopology.Quads)
	    {
		numVertsPerFace = 4;
	    }

	    // For all meshes:
	    // Accumulate vertices, normals, uvs, colors, and indices.
	    // Keep track of indices start and count for each mesh for later when uploading material assignments and groups.
	    // Find shared vertices, and use unique set of vertices to use as point positions.
	    // Need to reindex indices for both unique vertices, as well as vertex attributes.
	    for (int i = 0; i < numMeshes; ++i)
	    {
		Vector3[] meshVertices = inputDataMeshes._inputMeshes[i]._mesh.vertices;
		Matrix4x4 localToWorld = rootInvertTransformMatrix * inputDataMeshes._inputMeshes[i]._transform.localToWorldMatrix;

		List<Vector3> uniqueVertices = new List<Vector3>();

		// Keep track of old vertex positions (old vertex slot points to new unique vertex slot)
		int[] reindexVertices = new int[meshVertices.Length];
		Dictionary<Vector3, int> reindexMap = new Dictionary<Vector3, int>();

		// For each vertex, check against subsequent vertices for shared positions.
		for (int a = 0; a < meshVertices.Length; ++a)
		{
		    Vector3 va = meshVertices[a];

		    if (!reindexMap.ContainsKey(va))
		    {
			if (numMeshes > 1 && !inputDataMeshes._hasLOD)
			{
			    // For multiple meshes that are not LODs, apply local transform on vertices to get the merged mesh.
			    uniqueVertices.Add(localToWorld.MultiplyPoint(va));
			}
			else
			{
			    uniqueVertices.Add(va);
			}

			// Reindex to point to unique vertex slot
			reindexVertices[a] = uniqueVertices.Count - 1;
			reindexMap[va] = uniqueVertices.Count - 1;
		    }
		    else
		    {
			reindexVertices[a] = reindexMap[va];
		    }
		}

		int vertexOffset = vertices.Count;
		vertices.AddRange(uniqueVertices);

		Vector3[] meshNormals = inputDataMeshes._inputMeshes[i]._mesh.normals;
		Color[] meshColors = inputDataMeshes._inputMeshes[i]._mesh.colors;

		// This is really silly. mesh.GetUVs gives uvs regardless if they exist or not (makes duplicates of
		// first uv if they don't exist), but mesh.uv* gives correct UVs, but in Vector2 format.
		// Since we need to convert to Vector3 later, this checks mesh.uv*, then uses mesh.GetUVs to get in Vector3.
		// Note skipping uv1 as its internally used (i.e. the 2nd uv set is uv2)
		int uindex = 0;
		GetUVsFromMesh(inputDataMeshes._inputMeshes[i]._mesh, inputDataMeshes._inputMeshes[i]._mesh.uv, tempUVs[0], uindex++);
		GetUVsFromMesh(inputDataMeshes._inputMeshes[i]._mesh, inputDataMeshes._inputMeshes[i]._mesh.uv2, tempUVs[1], uindex++);
		GetUVsFromMesh(inputDataMeshes._inputMeshes[i]._mesh, inputDataMeshes._inputMeshes[i]._mesh.uv3, tempUVs[2], uindex++);
		GetUVsFromMesh(inputDataMeshes._inputMeshes[i]._mesh, inputDataMeshes._inputMeshes[i]._mesh.uv4, tempUVs[3], uindex++);
#if UNITY_2018_2_OR_NEWER
		GetUVsFromMesh(inputDataMeshes._inputMeshes[i]._mesh, inputDataMeshes._inputMeshes[i]._mesh.uv5, tempUVs[4], uindex++);
		GetUVsFromMesh(inputDataMeshes._inputMeshes[i]._mesh, inputDataMeshes._inputMeshes[i]._mesh.uv6, tempUVs[5], uindex++);
		GetUVsFromMesh(inputDataMeshes._inputMeshes[i]._mesh, inputDataMeshes._inputMeshes[i]._mesh.uv7, tempUVs[6], uindex++);
		GetUVsFromMesh(inputDataMeshes._inputMeshes[i]._mesh, inputDataMeshes._inputMeshes[i]._mesh.uv8, tempUVs[7], uindex++);
#endif

		inputDataMeshes._inputMeshes[i]._indexStart = new uint[inputDataMeshes._inputMeshes[i]._numSubMeshes];
		inputDataMeshes._inputMeshes[i]._indexCount = new uint[inputDataMeshes._inputMeshes[i]._numSubMeshes];

		// For each submesh:
		// Generate face to point index -> pointIndexList
		// Generate face to vertex attribute index -> vertIndexList
		for (int j = 0; j < inputDataMeshes._inputMeshes[i]._numSubMeshes; ++j)
		{
		    int indexStart = pointIndexList.Count;
		    int vertIndexStart = vertIndexList.Count;

		    // Indices have to be re-indexed with our own offset 
		    // (using GetIndices to generalize triangles and quad indices)
		    int[] meshIndices = inputDataMeshes._inputMeshes[i]._mesh.GetIndices(j);
		    int numIndices = meshIndices.Length;
		    for (int k = 0; k < numIndices; ++k)
		    {
			int originalIndex = meshIndices[k];
			meshIndices[k] = reindexVertices[originalIndex];

			pointIndexList.Add(vertexOffset + meshIndices[k]);
			vertIndexList.Add(vertIndexStart + k);

			if (meshNormals != null && (originalIndex < meshNormals.Length))
			{
			    normals.Add(meshNormals[originalIndex]);
			}

			for (int u = 0; u < NumUVSets; ++u)
			{
			    if (tempUVs[u].Count > 0)
			    {
				uvs[u].Add(tempUVs[u][originalIndex]);
			    }
			}

			if (meshColors != null && (originalIndex < meshColors.Length))
			{
			    colors.Add(meshColors[originalIndex]);
			}
		    }

		    inputDataMeshes._inputMeshes[i]._indexStart[j] = (uint)indexStart;
		    inputDataMeshes._inputMeshes[i]._indexCount[j] = (uint)(pointIndexList.Count) - inputDataMeshes._inputMeshes[i]._indexStart[j];
		}

		numMaterials += inputDataMeshes._inputMeshes[i]._materials != null ? inputDataMeshes._inputMeshes[i]._materials.Length : 0;
	    }

	    // It is possible for some meshes to not have normals/uvs/colors while others do.
	    // In the case where an attribute is missing on some meshes, we clear out those attributes so we don't upload
	    // partial attribute data.
	    int totalAllVertexCount = vertIndexList.Count;
	    if (normals.Count != totalAllVertexCount)
	    {
		normals = null;
	    }

	    if (colors.Count != totalAllVertexCount)
	    {
		colors = null;
	    }

	    HAPI_PartInfo partInfo = new HAPI_PartInfo();
	    partInfo.faceCount = vertIndexList.Count / numVertsPerFace;
	    partInfo.vertexCount = vertIndexList.Count;
	    partInfo.pointCount = vertices.Count;
	    partInfo.pointAttributeCount = 1;
	    partInfo.vertexAttributeCount = 0;
	    partInfo.primitiveAttributeCount = 0;
	    partInfo.detailAttributeCount = 0;

	    //Debug.LogFormat("Faces: {0}; Vertices: {1}; Verts/Face: {2}", partInfo.faceCount, partInfo.vertexCount, numVertsPerFace);

	    if (normals != null && normals.Count > 0)
	    {
		partInfo.vertexAttributeCount++;
	    }

	    for (int u = 0; u < NumUVSets; ++u)
	    {
		if (uvs[u].Count > 0 && uvs[u].Count == totalAllVertexCount)
		{
		    partInfo.vertexAttributeCount++;
		}
		else
		{
		    uvs[u].Clear();
		}
	    }

	    if (colors != null && colors.Count > 0)
	    {
		partInfo.vertexAttributeCount++;
	    }

	    if (numMaterials > 0)
	    {
		partInfo.primitiveAttributeCount++;
	    }

	    if (numMeshes > 0)
	    {
		partInfo.primitiveAttributeCount++;
	    }

	    if (inputDataMeshes._hasLOD)
	    {
		partInfo.primitiveAttributeCount++;
		partInfo.detailAttributeCount++;
	    }

	    HAPI_GeoInfo displayGeoInfo = new HAPI_GeoInfo();
	    if (!session.GetDisplayGeoInfo(inputNodeID, ref displayGeoInfo))
	    {
		return false;
	    }

	    HAPI_NodeId displayNodeID = displayGeoInfo.nodeId;

	    if (!session.SetPartInfo(displayNodeID, 0, ref partInfo))
	    {
		Debug.LogError("Failed to set input part info. ");
		return false;
	    }

	    int[] faceCounts = new int[partInfo.faceCount];
	    for (int i = 0; i < partInfo.faceCount; ++i)
	    {
		faceCounts[i] = numVertsPerFace;
	    }

	    int[] faceIndices = pointIndexList.ToArray();

	    if (!HEU_GeneralUtility.SetArray2Arg(displayNodeID, 0, session.SetFaceCount, faceCounts, 0, partInfo.faceCount))
	    {
		Debug.LogError("Failed to set input geometry face counts.");
		return false;
	    }

	    if (!HEU_GeneralUtility.SetArray2Arg(displayNodeID, 0, session.SetVertexList, faceIndices, 0, partInfo.vertexCount))
	    {
		Debug.LogError("Failed to set input geometry indices.");
		return false;
	    }

	    if (!HEU_InputMeshUtility.SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_POSITION, 3, vertices.ToArray(), ref partInfo, true))
	    {
		Debug.LogError("Failed to set input geometry position.");
		return false;
	    }

	    int[] vertIndices = vertIndexList.ToArray();

	    //if(normals != null && !SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_NORMAL, 3, normals.ToArray(), ref partInfo, true))
	    if (normals != null && !HEU_InputMeshUtility.SetMeshVertexAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_NORMAL, 3, normals.ToArray(), vertIndices, ref partInfo, true))
	    {
		Debug.LogError("Failed to set input geometry normals.");
		return false;
	    }

	    for (int u = 0; u < NumUVSets; ++u)
	    {
		if (uvs[u].Count > 0)
		{
		    // Skip uv1 as its used internally. So it goes: uv, uv2, ..., uv8
		    string uvName = u == 0 ? HEU_Defines.HAPI_ATTRIB_UV : string.Format("{0}{1}", HEU_Defines.HAPI_ATTRIB_UV, u + 1);
		    if (!HEU_InputMeshUtility.SetMeshVertexAttribute(session, displayNodeID, 0, uvName, 3, uvs[u].ToArray(), vertIndices, ref partInfo, false))
		    {
			Debug.LogError("Failed to set input geometry UV" + u);
			return false;
		    }
		}
	    }

	    if (colors != null && colors.Count > 0)
	    {
		Vector3[] rgb = new Vector3[colors.Count];
		float[] alpha = new float[colors.Count];
		for (int i = 0; i < colors.Count; ++i)
		{
		    rgb[i][0] = colors[i].r;
		    rgb[i][1] = colors[i].g;
		    rgb[i][2] = colors[i].b;

		    alpha[i] = colors[i].a;
		}

		//if(!SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_COLOR, 3, rgb, ref partInfo, false))
		if (!HEU_InputMeshUtility.SetMeshVertexAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_COLOR, 3, rgb, vertIndices, ref partInfo, false))
		{
		    Debug.LogError("Failed to set input geometry colors.");
		    return false;
		}

		//if(!SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_ALPHA, 1, alpha, ref partInfo, false))
		if (!HEU_InputMeshUtility.SetMeshVertexFloatAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_ALPHA, 1, alpha, vertIndices, ref partInfo))
		{
		    Debug.LogError("Failed to set input geometry color alpha.");
		    return false;
		}
	    }

	    // Set material names for round-trip perservation of material assignment
	    // Each HEU_UploadMeshData might have a list of submeshes and materials
	    // These are all combined into a single mesh, with group names
	    if (numMaterials > 0)
	    {
		bool bFoundAtleastOneValidMaterial = false;

		string[] materialIDs = new string[partInfo.faceCount];
		for (int g = 0; g < inputDataMeshes._inputMeshes.Count; ++g)
		{
		    if (inputDataMeshes._inputMeshes[g]._numSubMeshes != inputDataMeshes._inputMeshes[g]._materials.Length)
		    {
			// Number of submeshes should equal number of materials since materials determine submeshes
			continue;
		    }

		    for (int i = 0; i < inputDataMeshes._inputMeshes[g]._materials.Length; ++i)
		    {
			string materialName = HEU_AssetDatabase.GetAssetPathWithSubAssetSupport(inputDataMeshes._inputMeshes[g]._materials[i]);
			if (materialName == null)
			{
			    materialName = "";
			}
			else if (materialName.StartsWith(HEU_Defines.DEFAULT_UNITY_BUILTIN_RESOURCES))
			{
			    materialName = HEU_AssetDatabase.GetUniqueAssetPathForUnityAsset(inputDataMeshes._inputMeshes[g]._materials[i]);
			}

			bFoundAtleastOneValidMaterial |= !string.IsNullOrEmpty(materialName);

			int faceStart = (int)inputDataMeshes._inputMeshes[g]._indexStart[i] / numVertsPerFace;
			int faceEnd = faceStart + ((int)inputDataMeshes._inputMeshes[g]._indexCount[i] / numVertsPerFace);
			for (int m = faceStart; m < faceEnd; ++m)
			{
			    materialIDs[m] = materialName;
			}
		    }
		}

		if (bFoundAtleastOneValidMaterial)
		{
		    HAPI_AttributeInfo materialIDAttrInfo = new HAPI_AttributeInfo();
		    materialIDAttrInfo.exists = true;
		    materialIDAttrInfo.owner = HAPI_AttributeOwner.HAPI_ATTROWNER_PRIM;
		    materialIDAttrInfo.storage = HAPI_StorageType.HAPI_STORAGETYPE_STRING;
		    materialIDAttrInfo.count = partInfo.faceCount;
		    materialIDAttrInfo.tupleSize = 1;
		    materialIDAttrInfo.originalOwner = HAPI_AttributeOwner.HAPI_ATTROWNER_INVALID;

		    if (!session.AddAttribute(displayNodeID, 0, HEU_PluginSettings.UnityMaterialAttribName, ref materialIDAttrInfo))
		    {
			Debug.LogError("Failed to add input geometry unity material name attribute.");
			return false;
		    }

		    if (!HEU_GeneralUtility.SetAttributeArray(displayNodeID, 0, HEU_PluginSettings.UnityMaterialAttribName, ref materialIDAttrInfo, materialIDs, session.SetAttributeStringData, partInfo.faceCount))
		    {
			Debug.LogError("Failed to set input geometry unity material name.");
			return false;
		    }
		}
	    }

	    // Set mesh name attribute
	    HAPI_AttributeInfo attrInfo = new HAPI_AttributeInfo();
	    attrInfo.exists = true;
	    attrInfo.owner = HAPI_AttributeOwner.HAPI_ATTROWNER_PRIM;
	    attrInfo.storage = HAPI_StorageType.HAPI_STORAGETYPE_STRING;
	    attrInfo.count = partInfo.faceCount;
	    attrInfo.tupleSize = 1;
	    attrInfo.originalOwner = HAPI_AttributeOwner.HAPI_ATTROWNER_INVALID;

	    if (session.AddAttribute(displayNodeID, 0, HEU_PluginSettings.UnityInputMeshAttr, ref attrInfo))
	    {
		string[] primitiveNameAttr = new string[partInfo.faceCount];

		for (int g = 0; g < inputDataMeshes._inputMeshes.Count; ++g)
		{
		    for (int i = 0; i < inputDataMeshes._inputMeshes[g]._numSubMeshes; ++i)
		    {
			int faceStart = (int)inputDataMeshes._inputMeshes[g]._indexStart[i] / numVertsPerFace;
			int faceEnd = faceStart + ((int)inputDataMeshes._inputMeshes[g]._indexCount[i] / numVertsPerFace);
			for (int m = faceStart; m < faceEnd; ++m)
			{
			    primitiveNameAttr[m] = inputDataMeshes._inputMeshes[g]._meshPath;
			}
		    }
		}

		if (!HEU_GeneralUtility.SetAttributeArray(displayNodeID, 0, HEU_PluginSettings.UnityInputMeshAttr, ref attrInfo, primitiveNameAttr, session.SetAttributeStringData, partInfo.faceCount))
		{
		    Debug.LogError("Failed to set input geometry unity mesh name.");
		    return false;
		}
	    }
	    else
	    {
		return false;
	    }

	    // Set LOD group membership
	    if (inputDataMeshes._hasLOD)
	    {
		int[] membership = new int[partInfo.faceCount];

		for (int g = 0; g < inputDataMeshes._inputMeshes.Count; ++g)
		{
		    if (g > 0)
		    {
			// Clear array
			for (int m = 0; m < partInfo.faceCount; ++m)
			{
			    membership[m] = 0;
			}
		    }

		    // Set 1 for faces belonging to this group
		    for (int s = 0; s < inputDataMeshes._inputMeshes[g]._numSubMeshes; ++s)
		    {
			int faceStart = (int)inputDataMeshes._inputMeshes[g]._indexStart[s] / numVertsPerFace;
			int faceEnd = faceStart + ((int)inputDataMeshes._inputMeshes[g]._indexCount[s] / numVertsPerFace);
			for (int m = faceStart; m < faceEnd; ++m)
			{
			    membership[m] = 1;
			}
		    }

		    if (!session.AddGroup(displayNodeID, 0, HAPI_GroupType.HAPI_GROUPTYPE_PRIM, inputDataMeshes._inputMeshes[g]._meshName))
		    {
			Debug.LogError("Failed to add input geometry LOD group name.");
			return false;
		    }

		    if (!session.SetGroupMembership(displayNodeID, 0, HAPI_GroupType.HAPI_GROUPTYPE_PRIM, inputDataMeshes._inputMeshes[g]._meshName, membership, 0, partInfo.faceCount))
		    {
			Debug.LogError("Failed to set input geometry LOD group name.");
			return false;
		    }
		}
	    }

	    return session.CommitGeo(displayNodeID);
	}
Exemplo n.º 20
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;
		}
        private bool UploadData(HEU_SessionBase session, HAPI_NodeId inputNodeID, HEU_InputData inputData)
        {
            if (settings == null)
            {
                HEU_Logger.LogError("Tilemap Settings not found!");
                return(false);
            }

            HEU_InputDataTilemap inputTilemap = inputData as HEU_InputDataTilemap;

            if (inputTilemap == null)
            {
                HEU_Logger.LogError("Expected HEU_InputDataTilemap type for inputData, but received unssupported type.");
                return(false);
            }

            List <Vector3> vertices = new List <Vector3>();
            List <Vector3> colors   = new List <Vector3>();

            List <string>     tileNames  = new List <string>();
            List <Vector3>    tileSizes  = new List <Vector3>();
            List <Vector3Int> tileCoords = new List <Vector3Int>();

            Tilemap tileMap = inputTilemap._tilemap;

            if (!tileMap.gameObject.activeInHierarchy)
            {
                HEU_Logger.LogWarning("Tilemap inputs must be active in the hierarchy in order to properly send input data");
            }

            Grid gridLayout = tileMap.layoutGrid;

            Matrix4x4 orientation              = tileMap.orientationMatrix;
            Vector3   orientationPosition      = orientation.DecomposeToPosition();
            Vector3   orientationRotationEuler = orientation.DecomposeToRotation().eulerAngles;

            orientationRotationEuler.y = -orientationRotationEuler.y;
            orientationRotationEuler.z = -orientationRotationEuler.z;
            Quaternion orientationRotation = Quaternion.Euler(orientationRotationEuler);
            Vector3    orientationScale    = orientation.DecomposeToScale();

            List <float>   pointOrient = new List <float>();
            List <Vector3> pointScale  = new List <Vector3>();

            TileBase[] tileArray = tileMap.GetTilesBlock(tileMap.cellBounds);

            int     tileCount    = 0;
            Vector3 anchorOffset = tileMap.tileAnchor;

            anchorOffset.Scale(gridLayout.cellSize);

            Vector3 pointPos;

            Vector3Int boundsMin = new Vector3Int(int.MaxValue, int.MaxValue, int.MaxValue);
            Vector3Int boundsMax = new Vector3Int(int.MinValue, int.MinValue, int.MinValue);

            foreach (Vector3Int tilePos in tileMap.cellBounds.allPositionsWithin)
            {
                if (tileMap.HasTile(tilePos))
                {
                    boundsMin = Vector3Int.Min(tilePos, boundsMin);
                    boundsMax = Vector3Int.Max(tilePos, boundsMax);
                }
            }

            boundsMax += Vector3Int.one;
            BoundsInt tileMapBounds = new BoundsInt {
                min = boundsMin, max = boundsMax
            };

            foreach (Vector3Int tilePos in tileMapBounds.allPositionsWithin)
            {
                if (!settings._exportUnusedTiles && !tileMap.HasTile(tilePos))
                {
                    continue;
                }

                Vector3Int usedTilePos = tilePos;
                //For Houdini (to use Labs Wang Tile tools, we need to reverse point order on the x axis)
                //so we just iterate in reverse order on the x
                //usedTilePos.x = tileMapBounds.size.x - 1 - tilePos.x + 2 * tileMapBounds.min.x;

                tileCount++;
                pointPos = tileMap.CellToLocal(usedTilePos) + anchorOffset;
                if (settings._applyTilemapOrientation)
                {
                    pointPos += orientationPosition;
                    pointOrient.Add(orientationRotation[0]);
                    pointOrient.Add(orientationRotation[1]);
                    pointOrient.Add(orientationRotation[2]);
                    pointOrient.Add(orientationRotation[3]);

                    pointScale.Add(orientationScale);
                }

                vertices.Add(pointPos);

                if (tileMap.HasTile(usedTilePos))
                {
                    Tile tile = tileMap.GetTile <Tile>(usedTilePos);
                    tileNames.Add(tile.name);
                    if (settings._applyTileColor)
                    {
                        colors.Add(new Vector3(tile.color.r, tile.color.g, tile.color.b));
                    }
                    tileSizes.Add(new Vector3(tile.sprite.rect.size.x / tile.sprite.pixelsPerUnit, tile.sprite.rect.size.y / tile.sprite.pixelsPerUnit, 0.0f));
                }
                else
                {
                    tileNames.Add("");
                    if (settings._applyTileColor)
                    {
                        colors.Add(Vector3.zero);
                    }
                    tileSizes.Add(Vector3.zero);
                }

                tileCoords.Add(usedTilePos);
            }

            HAPI_PartInfo partInfo = new HAPI_PartInfo();

            partInfo.faceCount               = 0;
            partInfo.vertexCount             = 0;
            partInfo.pointCount              = tileCount;
            partInfo.pointAttributeCount     = 1;
            partInfo.vertexAttributeCount    = 0;
            partInfo.primitiveAttributeCount = 0;
            partInfo.detailAttributeCount    = 1;

            if (tileSizes.Count > 0)
            {
                partInfo.pointAttributeCount++;
            }

            if (settings._applyTileColor && colors.Count > 0)
            {
                partInfo.pointAttributeCount++;
            }

            if (tileCoords.Count > 0)
            {
                partInfo.pointAttributeCount++;
            }

            if (pointOrient.Count > 0)
            {
                partInfo.pointAttributeCount++;
            }

            if (pointScale.Count > 0)
            {
                partInfo.pointAttributeCount++;
            }

            if (!settings._createGroupsForTiles && tileNames.Count > 0)
            {
                partInfo.pointAttributeCount++;
            }


            HAPI_GeoInfo displayGeoInfo = new HAPI_GeoInfo();

            if (!session.GetDisplayGeoInfo(inputNodeID, ref displayGeoInfo))
            {
                return(false);
            }

            HAPI_NodeId displayNodeID = displayGeoInfo.nodeId;

            if (!session.SetPartInfo(displayNodeID, 0, ref partInfo))
            {
                Debug.LogError("Failed to set input part info. ");
                return(false);
            }

            if (!HEU_InputMeshUtility.SetMeshPointAttribute(session, displayNodeID, 0, HEU_HAPIConstants.HAPI_ATTRIB_POSITION, 3, vertices.ToArray(), ref partInfo, true))
            {
                Debug.LogError("Failed to set point positions.");
                return(false);
            }

            if (!HEU_InputMeshUtility.SetMeshPointAttribute(session, displayNodeID, 0, "unity_tile_size", 2, tileSizes.ToArray(), ref partInfo, false))
            {
                Debug.Log("Failed to set tile size attributes. ");
                return(false);
            }

            if (settings._applyTileColor)
            {
                if (!HEU_InputMeshUtility.SetMeshPointAttribute(session, displayNodeID, 0, HEU_HAPIConstants.HAPI_ATTRIB_COLOR, 3, colors.ToArray(), ref partInfo, false))
                {
                    Debug.Log("Failed to set tile color attributes. ");
                    return(false);
                }
            }


            if (!HEU_InputMeshUtility.SetMeshPointAttribute(session, displayNodeID, 0, "unity_tile_pos", 2, tileCoords.ToArray(), ref partInfo))
            {
                Debug.Log("Failed to set point tile coordinates attributes.");
                return(false);
            }

            if (settings._createGroupsForTiles)
            {
                //Get a list of unique tiles used
                TileBase[] usedTiles = new TileBase[tileMap.GetUsedTilesCount()];
                tileMap.GetUsedTilesNonAlloc(usedTiles);

                //Set point groups based on tile type
                int[] pointGroupMembership = new int[tileCount];
                foreach (TileBase tileType in usedTiles)
                {
                    if (!session.AddGroup(displayNodeID, 0, HAPI_GroupType.HAPI_GROUPTYPE_POINT, tileType.name))
                    {
                        return(false);
                    }

                    int index = 0;
                    foreach (string tileName in tileNames)
                    {
                        if (tileName.Equals(tileType.name))
                        {
                            pointGroupMembership[index] = 1;
                        }
                        else
                        {
                            pointGroupMembership[index] = 0;
                        }
                        index++;
                    }

                    if (!session.SetGroupMembership(displayNodeID, 0, HAPI_GroupType.HAPI_GROUPTYPE_POINT, tileType.name, pointGroupMembership, 0, tileCount))
                    {
                        return(false);
                    }
                }
            }
            else
            {
                if (!HEU_InputMeshUtility.SetMeshPointAttribute(session, displayNodeID, 0, "unity_tile_name", tileNames.ToArray(), ref partInfo))
                {
                    Debug.Log("Failed to set point tile name attributes.");
                    return(false);
                }
            }

            if (!HEU_InputMeshUtility.SetMeshDetailAttribute(session, displayNodeID, 0, "unity_tile_bounds", 2, tileMapBounds.size, ref partInfo))
            {
                Debug.Log("Failed to set detail tile map bounds attribute.");
                return(false);
            }

            if (settings._applyTilemapOrientation)
            {
                if (!HEU_InputMeshUtility.SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_ORIENT, 4, pointOrient.ToArray(), ref partInfo))
                {
                    Debug.LogError("Failed to set point rotations.");
                    return(false);
                }

                if (!HEU_InputMeshUtility.SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_SCALE, 3, pointScale.ToArray(), ref partInfo, false))
                {
                    Debug.LogError("Failed to set point scales.");
                    return(false);
                }
            }

            return(session.CommitGeo(displayNodeID));
        }
Exemplo n.º 22
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]));
	    }
	}
Exemplo n.º 23
0
 public void SetGeoInfo(HAPI_GeoInfo geoInfo)
 {
     _geoInfo = geoInfo;
 }
        private bool UploadData( HEU_SessionBase session, HAPI_NodeId inputNodeID, HEU_InputData inputData)
        {
            HEU_InputDataTilemap inputTilemap = inputData as HEU_InputDataTilemap;
            if(inputTilemap == null)
            {
                Debug.LogError("Expected HEU_InputDataTilemap type for inputData, but received unssupported type.");
                return false;
            }

            List<Vector3> vertices = new List<Vector3>();            
            List<Vector3> colors = new List<Vector3>();
            //List<Vector3> uvs = new List<Vector3>();
            List<Vector3> normals = new List<Vector3>();

            List<string> tileNames = new List<string>();            
            List<Vector3> tileSizes = new List<Vector3>();
            List<Vector3Int> tileCoords = new List<Vector3Int>();

            Tilemap tileMap = inputTilemap._tilemap;
            Grid gridLayout = tileMap.layoutGrid;

            //Get a list of unique tiles used
            TileBase[] usedTiles = new TileBase[ tileMap.GetUsedTilesCount() ];
            tileMap.GetUsedTilesNonAlloc(usedTiles);

            TileBase[] tileArray = tileMap.GetTilesBlock( tileMap.cellBounds );
            //tileArray = tileArray.Where( x => x != null).ToArray(); //only existing tiles

            int tileCount = 0;            
            Vector3 anchorOffset = tileMap.tileAnchor;
            anchorOffset.Scale(gridLayout.cellSize);

            Vector3 pointPos;
            Vector3 pointNormal = new Vector3(0.0f, 0.0f, 1.0f);

            Vector3Int boundsMin = new Vector3Int(int.MaxValue, int.MaxValue, int.MaxValue);
            Vector3Int boundsMax = new Vector3Int(int.MinValue, int.MinValue, int.MinValue);

            foreach (Vector3Int tilePos in tileMap.cellBounds.allPositionsWithin)
            {
                if (tileMap.HasTile(tilePos))
                {
                    boundsMin = Vector3Int.Min(tilePos, boundsMin);
                    boundsMax = Vector3Int.Max(tilePos, boundsMax);
                }
            }

            boundsMax += Vector3Int.one;
            BoundsInt tileMapBounds = new BoundsInt
            {
                min = boundsMin,
                max = boundsMax
            };

            //foreach (Vector3Int tilePos in tileMap.cellBounds.allPositionsWithin)
            Vector3Int tilePosReverseX = new Vector3Int();
            foreach(Vector3Int tilePos in tileMapBounds.allPositionsWithin)
            {
#if !EXPORT_RECT_GRID
                if(!tileMap.HasTile(tilePos))
                    continue;
#endif

                tilePosReverseX = tilePos;
                //For Hudini (to use Labs Wang Tile tools, we need to reverse point order on the x axis)
                //so we just iterate in reverse order on the x                
                tilePosReverseX.x = tileMapBounds.size.x - 1 - tilePos.x + 2 * tileMapBounds.min.x;

                tileCount++;
                pointPos = tileMap.CellToLocal(tilePosReverseX) + anchorOffset;
                vertices.Add(pointPos);
                normals.Add(pointNormal);

                if (tileMap.HasTile(tilePosReverseX))
                {
                    Tile tile = tileMap.GetTile<Tile>(tilePosReverseX);
                    tileNames.Add(tile.name);
                    colors.Add(new Vector3(tile.color.r, tile.color.g, tile.color.b));
                    tileSizes.Add(new Vector3(tile.sprite.rect.size.x / tile.sprite.pixelsPerUnit, tile.sprite.rect.size.y / tile.sprite.pixelsPerUnit, 0.0f));

                }
                else
                {
                    tileNames.Add("");
                    colors.Add(Vector3.zero);
                    tileSizes.Add(Vector3.zero);
                }

                tileCoords.Add(tilePosReverseX);
            }            

            HAPI_PartInfo partInfo = new HAPI_PartInfo();
            partInfo.faceCount = 0;
            partInfo.vertexCount = 0;
            partInfo.pointCount = tileCount;
            partInfo.pointAttributeCount = 1;
            partInfo.vertexAttributeCount = 0;
            partInfo.primitiveAttributeCount = 0;
            partInfo.detailAttributeCount = 0;

            HAPI_GeoInfo displayGeoInfo = new HAPI_GeoInfo();
            if(!session.GetDisplayGeoInfo(inputNodeID, ref displayGeoInfo))
            {
                return false;
            }

            HAPI_NodeId displayNodeID = displayGeoInfo.nodeId;
            if(!session.SetPartInfo(displayNodeID, 0, ref partInfo))
            {
                Debug.LogError("Failed to set input part info. ");
		        return false;
            }

            if(!HEU_InputMeshUtility.SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_POSITION, 3, vertices.ToArray(), ref partInfo, true))
            {
                Debug.LogError("Failed to set point positions.");
                return false;
            }

            if (!HEU_InputMeshUtility.SetMeshPointAttribute(session, displayNodeID, 0, "size", 2, tileSizes.ToArray(), ref partInfo, false))
            {
                Debug.Log("Failed to set tile size attributes. ");
                return false;
            }

            if(!HEU_InputMeshUtility.SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_COLOR, 3, colors.ToArray(), ref partInfo, false))
            {
                Debug.Log("Failed to set tile color attributes. ");
                return false;
            }

            if(!HEU_InputMeshUtility.SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_NORMAL, 3, normals.ToArray(), ref partInfo, true))
            {
                Debug.Log("Failed to set point normal attributes.");
                return false;
            }

            if(!HEU_InputMeshUtilityExt.SetMeshPointAttribute(session, displayNodeID, 0, "tilepos", 2, tileCoords.ToArray(), ref partInfo))
            {
                Debug.Log("Failed to set point tile coordinates attributes.");
                return false;
            }


#if TILENAME_GROUPS
            //Set point groups based on tile type
            int[] pointGroupMembership = new int[tileCount];
            foreach(TileBase tileType in usedTiles)
            {
                if(!session.AddGroup( displayNodeID, 0, HAPI_GroupType.HAPI_GROUPTYPE_POINT, tileType.name))
                    return false;

                int index = 0;
                foreach( string tileName in tileNames)
                {
                    if(tileName.Equals(tileType.name))
                        pointGroupMembership[index] = 1;
                    else
                        pointGroupMembership[index] = 0;
                    index++;
                }

                if(!session.SetGroupMembership(displayNodeID, 0, HAPI_GroupType.HAPI_GROUPTYPE_POINT, tileType.name, pointGroupMembership, 0, tileCount))
                    return false;
            }
#else
            if(!HEU_InputMeshUtilityExt.SetMeshPointAttribute(session, displayNodeID, 0, "tilename", tileNames.ToArray(), ref partInfo))
            {
                Debug.Log("Failed to set point tile name attributes.");
                return false;
            }
#endif
            if(!HEU_InputMeshUtilityExt.SetMeshDetailAttribute(session, displayNodeID, 0, "bounds", 2, tileMapBounds.size, ref partInfo))
            {
                Debug.Log("Failed to set detail tile map bounds attribute.");
                return false;
            }

            return session.CommitGeo(displayNodeID);
        }
Exemplo n.º 25
0
	/// <summary>
	/// Retrieves object info from Houdini session and updates internal state.
	/// New geo nodes are created, unused geo nodes are destroyed.
	/// Geo nodes are then refreshed to be in sync with Houdini session.
	/// </summary>
	/// <returns>True if internal state has changed (including geometry).</returns>
	public void UpdateObject(HEU_SessionBase session, bool bForceUpdate)
	{
	    // Update the geo info
	    if (!session.GetObjectInfo(ObjectID, ref _objectInfo))
	    {
		return;
	    }
	    SyncWithObjectInfo(session);

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

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

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

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

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

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

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

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

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

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

			    bFound = true;
			    break;
			}
		    }

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

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

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

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

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

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

	    // Updating the trasform is done in GenerateGeometry
	}
		/// <summary>
		/// Get the geometry info on a SOP node.
		/// </summary>
		/// <param name="nodeID">The SOP node ID</param>
		/// <param name="geoInfo">Geo info to populate</param>
		/// <returns>True if successfully queried the geo info</returns>
		public virtual bool GetGeoInfo(HAPI_NodeId nodeID, ref HAPI_GeoInfo geoInfo)
		{
			return false;
		}
Exemplo n.º 27
0
		/// <summary>
		/// Upload the inputData (mesh geometry) into the input node with inputNodeID.
		/// </summary>
		/// <param name="session">Session that the input node exists in</param>
		/// <param name="inputNodeID">ID of the input node</param>
		/// <param name="inputData">Container of the mesh geometry</param>
		/// <returns>True if successfully uploaded data</returns>
		public bool UploadData(HEU_SessionBase session, HAPI_NodeId inputNodeID, HEU_InputData inputData)
		{
			HEU_InputDataMeshes inputDataMeshes = inputData as HEU_InputDataMeshes;
			if (inputDataMeshes == null)
			{
				Debug.LogError("Expected HEU_InputDataMeshes type for inputData, but received unsupported type.");
				return false;
			}

			List<Vector3> vertices = new List<Vector3>();
			List<Vector3> normals = new List<Vector3>();
			List<Vector2> uvs = new List<Vector2>();
			List<Color> colors = new List<Color>();

			List<int> pointIndexList = new List<int>();
			List<int> vertIndexList = new List<int>();

			int numMaterials = 0;

			int numMeshes = inputDataMeshes._inputMeshes.Count;

			// Get the parent's world transform, so when there are multiple child meshes,
			// can merge and apply their local transform after subtracting their parent's world transform
			Matrix4x4 rootInvertTransformMatrix = Matrix4x4.identity;
			if (numMeshes > 1)
			{
				rootInvertTransformMatrix = inputDataMeshes._inputObject.transform.worldToLocalMatrix;
			}

			// For all meshes:
			// Accumulate vertices, normals, uvs, colors, and indices.
			// Keep track of indices start and count for each mesh for later when uploading material assignments and groups.
			// Find shared vertices, and use unique set of vertices to use as point positions.
			// Need to reindex indices for both unique vertices, as well as vertex attributes.
			for (int i = 0; i < numMeshes; ++i)
			{
				Vector3[] meshVertices = inputDataMeshes._inputMeshes[i]._mesh.vertices;
				Matrix4x4 localToWorld = inputDataMeshes._inputMeshes[i]._transform.localToWorldMatrix * rootInvertTransformMatrix;

				List<Vector3> uniqueVertices = new List<Vector3>();

				// Keep track of old vertex positions (old vertex slot points to new unique vertex slot)
				int[] reindexVertices = new int[meshVertices.Length];

				for (int j = 0; j < meshVertices.Length; ++j)
				{
					reindexVertices[j] = -1;
				}

				// For each vertex, check against subsequent vertices for shared positions.
				for (int a = 0; a < meshVertices.Length; ++a)
				{
					Vector3 va = meshVertices[a];

					if (reindexVertices[a] == -1)
					{
						if (numMeshes > 1 && !inputDataMeshes._hasLOD)
						{
							// For multiple meshes that are not LODs, apply local transform on vertices to get the merged mesh.
							uniqueVertices.Add(localToWorld.MultiplyPoint(va));
						}
						else
						{
							uniqueVertices.Add(va);
						}

						// Reindex to point to unique vertex slot
						reindexVertices[a] = uniqueVertices.Count - 1;
					}

					for (int b = a + 1; b < meshVertices.Length; ++b)
					{
						if (va == meshVertices[b])
						{
							// Shared vertex -> reindex to point to unique vertex slot
							reindexVertices[b] = reindexVertices[a];
						}
					}
				}

				int vertexOffset = vertices.Count;
				vertices.AddRange(uniqueVertices);

				Vector3[] meshNormals = inputDataMeshes._inputMeshes[i]._mesh.normals;
				Vector2[] meshUVs = inputDataMeshes._inputMeshes[i]._mesh.uv;
				Color[] meshColors = inputDataMeshes._inputMeshes[i]._mesh.colors;

				inputDataMeshes._inputMeshes[i]._indexStart = new uint[inputDataMeshes._inputMeshes[i]._numSubMeshes];
				inputDataMeshes._inputMeshes[i]._indexCount = new uint[inputDataMeshes._inputMeshes[i]._numSubMeshes];

				// For each submesh:
				// Generate face to point index -> pointIndexList
				// Generate face to vertex attribute index -> vertIndexList
				for (int j = 0; j < inputDataMeshes._inputMeshes[i]._numSubMeshes; ++j)
				{
					int indexStart = pointIndexList.Count;
					int vertIndexStart = vertIndexList.Count;

					// Indices have to be re-indexed with our own offset
					int[] meshIndices = inputDataMeshes._inputMeshes[i]._mesh.GetTriangles(j);
					int numIndices = meshIndices.Length;
					for (int k = 0; k < numIndices; ++k)
					{
						int originalIndex = meshIndices[k];
						meshIndices[k] = reindexVertices[originalIndex];

						pointIndexList.Add(vertexOffset + meshIndices[k]);
						vertIndexList.Add(vertIndexStart + k);

						if (meshNormals != null && (originalIndex < meshNormals.Length))
						{
							normals.Add(meshNormals[originalIndex]);
						}

						if (meshUVs != null && (originalIndex < meshUVs.Length))
						{
							uvs.Add(meshUVs[originalIndex]);
						}

						if (meshColors != null && (originalIndex < meshColors.Length))
						{
							colors.Add(meshColors[originalIndex]);
						}
					}

					inputDataMeshes._inputMeshes[i]._indexStart[j] = (uint)indexStart;
					inputDataMeshes._inputMeshes[i]._indexCount[j] = (uint)(pointIndexList.Count) - inputDataMeshes._inputMeshes[i]._indexStart[j];
				}

				numMaterials += inputDataMeshes._inputMeshes[i]._materials != null ? inputDataMeshes._inputMeshes[i]._materials.Length : 0;
			}

			// It is possible for some meshes to not have normals/uvs/colors while others do.
			// In the case where an attribute is missing on some meshes, we clear out those attributes so we don't upload
			// partial attribute data.
			int totalAllVertexCount = vertIndexList.Count;
			if (normals.Count != totalAllVertexCount)
			{
				normals = null;
			}

			if (uvs.Count != totalAllVertexCount)
			{
				uvs = null;
			}

			if (colors.Count != totalAllVertexCount)
			{
				colors = null;
			}

			HAPI_PartInfo partInfo = new HAPI_PartInfo();
			partInfo.faceCount = vertIndexList.Count / 3;
			partInfo.vertexCount = vertIndexList.Count;
			partInfo.pointCount = vertices.Count;
			partInfo.pointAttributeCount = 1;
			partInfo.vertexAttributeCount = 0;
			partInfo.primitiveAttributeCount = 0;
			partInfo.detailAttributeCount = 0;

			if (normals != null && normals.Count > 0)
			{
				partInfo.vertexAttributeCount++;
			}

			if (uvs != null && uvs.Count > 0)
			{
				partInfo.vertexAttributeCount++;
			}

			if (colors != null && colors.Count > 0)
			{
				partInfo.vertexAttributeCount++;
			}

			if (numMaterials > 0)
			{
				partInfo.primitiveAttributeCount++;
			}

			if (numMeshes > 0)
			{
				partInfo.primitiveAttributeCount++;
			}

			if (inputDataMeshes._hasLOD)
			{
				partInfo.primitiveAttributeCount++;
				partInfo.detailAttributeCount++;
			}

			HAPI_GeoInfo displayGeoInfo = new HAPI_GeoInfo();
			if (!session.GetDisplayGeoInfo(inputNodeID, ref displayGeoInfo))
			{
				return false;
			}

			HAPI_NodeId displayNodeID = displayGeoInfo.nodeId;

			if (!session.SetPartInfo(displayNodeID, 0, ref partInfo))
			{
				Debug.LogError("Failed to set input part info. ");
				return false;
			}

			int[] faceCounts = new int[partInfo.faceCount];
			for (int i = 0; i < partInfo.faceCount; ++i)
			{
				faceCounts[i] = 3;
			}

			int[] triIndices = pointIndexList.ToArray();

			if (!HEU_GeneralUtility.SetArray2Arg(displayNodeID, 0, session.SetFaceCount, faceCounts, 0, partInfo.faceCount))
			{
				Debug.LogError("Failed to set input geometry face counts.");
				return false;
			}

			if (!HEU_GeneralUtility.SetArray2Arg(displayNodeID, 0, session.SetVertexList, triIndices, 0, partInfo.vertexCount))
			{
				Debug.LogError("Failed to set input geometry indices.");
				return false;
			}

			if (!HEU_InputMeshUtility.SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_POSITION, 3, vertices.ToArray(), ref partInfo, true))
			{
				Debug.LogError("Failed to set input geometry position.");
				return false;
			}

			int[] vertIndices = vertIndexList.ToArray();

			//if(normals != null && !SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_NORMAL, 3, normals.ToArray(), ref partInfo, true))
			if (normals != null && !HEU_InputMeshUtility.SetMeshVertexAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_NORMAL, 3, normals.ToArray(), vertIndices, ref partInfo, true))
			{
				Debug.LogError("Failed to set input geometry normals.");
				return false;
			}

			if (uvs != null && uvs.Count > 0)
			{
				Vector3[] uvs3 = new Vector3[uvs.Count];
				for (int i = 0; i < uvs.Count; ++i)
				{
					uvs3[i][0] = uvs[i][0];
					uvs3[i][1] = uvs[i][1];
					uvs3[i][2] = 0;
				}
				//if(!SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_UV, 3, uvs3, ref partInfo, false))
				if (!HEU_InputMeshUtility.SetMeshVertexAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_UV, 3, uvs3, vertIndices, ref partInfo, false))
				{
					Debug.LogError("Failed to set input geometry UVs.");
					return false;
				}
			}

			if (colors != null && colors.Count > 0)
			{
				Vector3[] rgb = new Vector3[colors.Count];
				float[] alpha = new float[colors.Count];
				for (int i = 0; i < colors.Count; ++i)
				{
					rgb[i][0] = colors[i].r;
					rgb[i][1] = colors[i].g;
					rgb[i][2] = colors[i].b;

					alpha[i] = colors[i].a;
				}

				//if(!SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_COLOR, 3, rgb, ref partInfo, false))
				if (!HEU_InputMeshUtility.SetMeshVertexAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_COLOR, 3, rgb, vertIndices, ref partInfo, false))
				{
					Debug.LogError("Failed to set input geometry colors.");
					return false;
				}

				//if(!SetMeshPointAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_ALPHA, 1, alpha, ref partInfo, false))
				if (!HEU_InputMeshUtility.SetMeshVertexFloatAttribute(session, displayNodeID, 0, HEU_Defines.HAPI_ATTRIB_ALPHA, 1, alpha, vertIndices, ref partInfo))
				{
					Debug.LogError("Failed to set input geometry color alpha.");
					return false;
				}
			}

			// Set material names for round-trip perservation of material assignment
			// Each HEU_UploadMeshData might have a list of submeshes and materials
			// These are all combined into a single mesh, with group names
			if (numMaterials > 0)
			{
				bool bFoundAtleastOneValidMaterial = false;

				string[] materialIDs = new string[partInfo.faceCount];
				for (int g = 0; g < inputDataMeshes._inputMeshes.Count; ++g)
				{
					if (inputDataMeshes._inputMeshes[g]._numSubMeshes != inputDataMeshes._inputMeshes[g]._materials.Length)
					{
						// Number of submeshes should equal number of materials since materials determine submeshes
						continue;
					}

					for (int i = 0; i < inputDataMeshes._inputMeshes[g]._materials.Length; ++i)
					{
						string materialName = HEU_AssetDatabase.GetAssetPathWithSubAssetSupport(inputDataMeshes._inputMeshes[g]._materials[i]);
						if (materialName == null)
						{
							materialName = "";
						}
						else if (materialName.StartsWith(HEU_Defines.DEFAULT_UNITY_BUILTIN_RESOURCES))
						{
							materialName = HEU_AssetDatabase.GetUniqueAssetPathForUnityAsset(inputDataMeshes._inputMeshes[g]._materials[i]);
						}

						bFoundAtleastOneValidMaterial |= !string.IsNullOrEmpty(materialName);

						int faceStart = (int)inputDataMeshes._inputMeshes[g]._indexStart[i] / 3;
						int faceEnd = faceStart + ((int)inputDataMeshes._inputMeshes[g]._indexCount[i] / 3);
						for (int m = faceStart; m < faceEnd; ++m)
						{
							materialIDs[m] = materialName;
						}
					}
				}

				if (bFoundAtleastOneValidMaterial)
				{
					HAPI_AttributeInfo materialIDAttrInfo = new HAPI_AttributeInfo();
					materialIDAttrInfo.exists = true;
					materialIDAttrInfo.owner = HAPI_AttributeOwner.HAPI_ATTROWNER_PRIM;
					materialIDAttrInfo.storage = HAPI_StorageType.HAPI_STORAGETYPE_STRING;
					materialIDAttrInfo.count = partInfo.faceCount;
					materialIDAttrInfo.tupleSize = 1;
					materialIDAttrInfo.originalOwner = HAPI_AttributeOwner.HAPI_ATTROWNER_INVALID;

					if (!session.AddAttribute(displayNodeID, 0, HEU_PluginSettings.UnityMaterialAttribName, ref materialIDAttrInfo))
					{
						Debug.LogError("Failed to add input geometry unity material name attribute.");
						return false;
					}

					if (!HEU_GeneralUtility.SetAttributeArray(displayNodeID, 0, HEU_PluginSettings.UnityMaterialAttribName, ref materialIDAttrInfo, materialIDs, session.SetAttributeStringData, partInfo.faceCount))
					{
						Debug.LogError("Failed to set input geometry unity material name.");
						return false;
					}
				}
			}

			// Set mesh name attribute
			HAPI_AttributeInfo attrInfo = new HAPI_AttributeInfo();
			attrInfo.exists = true;
			attrInfo.owner = HAPI_AttributeOwner.HAPI_ATTROWNER_PRIM;
			attrInfo.storage = HAPI_StorageType.HAPI_STORAGETYPE_STRING;
			attrInfo.count = partInfo.faceCount;
			attrInfo.tupleSize = 1;
			attrInfo.originalOwner = HAPI_AttributeOwner.HAPI_ATTROWNER_INVALID;

			if (session.AddAttribute(displayNodeID, 0, HEU_PluginSettings.UnityInputMeshAttr, ref attrInfo))
			{
				string[] primitiveNameAttr = new string[partInfo.faceCount];

				for (int g = 0; g < inputDataMeshes._inputMeshes.Count; ++g)
				{
					for (int i = 0; i < inputDataMeshes._inputMeshes[g]._numSubMeshes; ++i)
					{
						int faceStart = (int)inputDataMeshes._inputMeshes[g]._indexStart[i] / 3;
						int faceEnd = faceStart + ((int)inputDataMeshes._inputMeshes[g]._indexCount[i] / 3);
						for (int m = faceStart; m < faceEnd; ++m)
						{
							primitiveNameAttr[m] = inputDataMeshes._inputMeshes[g]._meshPath;
						}
					}
				}

				if (!HEU_GeneralUtility.SetAttributeArray(displayNodeID, 0, HEU_PluginSettings.UnityInputMeshAttr, ref attrInfo, primitiveNameAttr, session.SetAttributeStringData, partInfo.faceCount))
				{
					Debug.LogError("Failed to set input geometry unity mesh name.");
					return false;
				}
			}
			else
			{
				return false;
			}

			// Set LOD group membership
			if (inputDataMeshes._hasLOD)
			{
				int[] membership = new int[partInfo.faceCount];

				for (int g = 0; g < inputDataMeshes._inputMeshes.Count; ++g)
				{
					if (g > 0)
					{
						// Clear array
						for (int m = 0; m < partInfo.faceCount; ++m)
						{
							membership[m] = 0;
						}
					}

					// Set 1 for faces belonging to this group
					for (int s = 0; s < inputDataMeshes._inputMeshes[g]._numSubMeshes; ++s)
					{
						int faceStart = (int)inputDataMeshes._inputMeshes[g]._indexStart[s] / 3;
						int faceEnd = faceStart + ((int)inputDataMeshes._inputMeshes[g]._indexCount[s] / 3);
						for (int m = faceStart; m < faceEnd; ++m)
						{
							membership[m] = 1;
						}
					}

					if (!session.AddGroup(displayNodeID, 0, HAPI_GroupType.HAPI_GROUPTYPE_PRIM, inputDataMeshes._inputMeshes[g]._meshName))
					{
						Debug.LogError("Failed to add input geometry LOD group name.");
						return false;
					}

					if (!session.SetGroupMembership(displayNodeID, 0, HAPI_GroupType.HAPI_GROUPTYPE_PRIM, inputDataMeshes._inputMeshes[g]._meshName, membership, 0, partInfo.faceCount))
					{
						Debug.LogError("Failed to set input geometry LOD group name.");
						return false;
					}
				}
			}

			return session.CommitGeo(displayNodeID);
		}
        /// <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);
        }