예제 #1
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;
		}
예제 #2
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 = pointAttributeDatas.Count;
			newPartInfo.vertexAttributeCount = vertexAttributeDatas.Count;
			newPartInfo.primitiveAttributeCount = primitiveAttributeDatas.Count;
			newPartInfo.detailAttributeCount = detailAttributeDatas.Count;

			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);
		}
예제 #3
0
		/// <summary>
		/// Fill in array of HAPI_Transform list. Use for large arrays where marshalling is done in chunks.
		/// </summary>
		/// <param name="nodeID">The parent node ID</param>
		/// <param name="rstOrder">Transform order</param>
		/// <param name="transforms">Array to fill. Should at least be size of length</param>
		/// <param name="start">At least 0 and at most object count returned by ComposeObjectList</param>
		/// <param name="length">Object count returned by ComposeObjectList. Should be at least 0 and at most object count - start</param>
		/// <returns>True if successfully queuried the transform list</returns>
		public static bool GetComposedObjectTransformsMemorySafe(HEU_SessionBase session, HAPI_NodeId nodeID, HAPI_RSTOrder rstOrder, [Out] HAPI_Transform[] transforms, int start, int length)
		{
			return HEU_GeneralUtility.GetArray2Arg(nodeID, rstOrder, session.GetComposedObjectTransforms, transforms, start, length);
		}
예제 #4
0
		private float[] GetHeightfield(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID, string partName, int terrainSize)
		{
			HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo();
			bool bResult = session.GetVolumeInfo(geoID, partID, ref volumeInfo);
			if (!bResult)
			{
				return null;
			}

			int volumeXLength = volumeInfo.xLength;
			int volumeYLength = volumeInfo.yLength;

			// Number of heightfield values
			int totalHeightValues = volumeXLength * volumeYLength;

			float[] heightValues = new float[totalHeightValues];
			bResult = HEU_GeneralUtility.GetArray2Arg(geoID, partID, session.GetHeightFieldData, heightValues, 0, totalHeightValues);
			if (!bResult)
			{
				Debug.LogErrorFormat("Unable to get heightfield data from part {0}", partName);
				return null;
			}

			float minHeight = heightValues[0];
			float maxHeight = minHeight;
			for (int i = 0; i < totalHeightValues; ++i)
			{
				float f = heightValues[i];
				if (f > maxHeight)
				{
					maxHeight = f;
				}
				else if (f < minHeight)
				{
					minHeight = f;
				}
			}

			float heightRange = (maxHeight - minHeight);
			if(heightRange == 0f)
			{
				heightRange = 1f;
			}
			//Debug.LogFormat("{0} : {1}", HEU_SessionManager.GetString(volumeInfo.nameSH, session), heightRange);

			// Remap height values to fit terrain size
			int paddingWidth = terrainSize - volumeXLength;
			int paddingLeft = Mathf.CeilToInt(paddingWidth * 0.5f);
			int paddingRight = terrainSize - paddingLeft;
			//Debug.LogFormat("Padding: Width={0}, Left={1}, Right={2}", paddingWidth, paddingLeft, paddingRight);

			int paddingHeight = terrainSize - volumeYLength;
			int paddingTop = Mathf.CeilToInt(paddingHeight * 0.5f);
			int paddingBottom = terrainSize - paddingTop;
			//Debug.LogFormat("Padding: Height={0}, Top={1}, Bottom={2}", paddingHeight, paddingTop, paddingBottom);

			// Set height values at centre of the terrain, with padding on the sides if we resized
			float[] resizedHeightValues = new float[terrainSize * terrainSize];
			for (int y = 0; y < terrainSize; ++y)
			{
				for (int x = 0; x < terrainSize; ++x)
				{
					if (y >= paddingTop && y < (paddingBottom) && x >= paddingLeft && x < (paddingRight))
					{
						int ay = x - paddingLeft;
						int ax = y - paddingTop;

						float f = heightValues[ay + ax * volumeXLength] - minHeight;
						f /= heightRange;

						// Flip for right-hand to left-handed coordinate system
						int ix = x;
						int iy = terrainSize - (y + 1);

						// Unity expects height array indexing to be [y, x].
						resizedHeightValues[iy + ix * terrainSize] = f;
					}
				}
			}

			return resizedHeightValues;
		}
		private HEU_LoadBufferInstancer GeneratePointAttributeInstancerBuffer(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID, 
			string partName, HAPI_PartInfo partInfo)
		{
			int numInstances = partInfo.pointCount;
			if (numInstances <= 0)
			{
				return null;
			}

			// Find type of instancer
			string instanceAttrName = HEU_PluginSettings.InstanceAttr;
			string unityInstanceAttrName = HEU_PluginSettings.UnityInstanceAttr;
			string instancePrefixAttrName = HEU_Defines.DEFAULT_INSTANCE_PREFIX_ATTR;

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

			HEU_GeneralUtility.GetAttributeInfo(session, geoID, partID, instanceAttrName, ref instanceAttrInfo);
			HEU_GeneralUtility.GetAttributeInfo(session, geoID, partID, unityInstanceAttrName, ref unityInstanceAttrInfo);

			if (unityInstanceAttrInfo.exists)
			{
				// Object instancing via existing Unity object (path from point attribute)

				HAPI_Transform[] instanceTransforms = new HAPI_Transform[numInstances];
				if (!HEU_GeneralUtility.GetArray2Arg(geoID, HAPI_RSTOrder.HAPI_SRT, session.GetInstanceTransforms, instanceTransforms, 0, numInstances))
				{
					return null;
				}

				string[] instancePrefixes = null;
				HEU_GeneralUtility.GetAttributeInfo(session, geoID, partID, instancePrefixAttrName, ref instancePrefixAttrInfo);
				if (instancePrefixAttrInfo.exists)
				{
					instancePrefixes = HEU_GeneralUtility.GetAttributeStringData(session, geoID, partID, instancePrefixAttrName, ref instancePrefixAttrInfo);
				}

				string[] assetPaths = null;

				// Attribute owner type determines whether to use single (detail) or multiple (point) asset(s) as source
				if (unityInstanceAttrInfo.owner == HAPI_AttributeOwner.HAPI_ATTROWNER_POINT || unityInstanceAttrInfo.owner == HAPI_AttributeOwner.HAPI_ATTROWNER_DETAIL)
				{

					assetPaths = HEU_GeneralUtility.GetAttributeStringData(session, geoID, partID, unityInstanceAttrName, ref unityInstanceAttrInfo);
				}
				else
				{
					// Other attribute owned types are unsupported
					SetLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Unsupported attribute owner {0} for attribute {1}", 
						unityInstanceAttrInfo.owner, unityInstanceAttrName));
					return null;
				}

				if (assetPaths == null)
				{
					SetLog(HEU_LoadData.LoadStatus.ERROR, "Unable to get instanced asset path from attribute!");
					return null;
				}

				HEU_LoadBufferInstancer instancerBuffer = new HEU_LoadBufferInstancer();
				instancerBuffer.InitializeBuffer(partID, partName, partInfo.isInstanced, true);

				instancerBuffer._instanceTransforms = instanceTransforms;
				instancerBuffer._instancePrefixes = instancePrefixes;
				instancerBuffer._assetPaths = assetPaths;

				return instancerBuffer;
			}
			else if (instanceAttrInfo.exists)
			{
				// Object instancing via internal object path is not supported
				SetLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Object instancing is not supported (part {0})!", partName));
			}
			else
			{
				// Standard object instancing via single Houdini object is not supported
				SetLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Object instancing is not supported (part {0})!", partName));
			}

			return null;
		}
예제 #6
0
		public static bool GenerateTerrainFromVolume(HEU_SessionBase session, ref HAPI_VolumeInfo volumeInfo, HAPI_NodeId geoID, HAPI_PartId partID, 
			GameObject gameObject, out TerrainData terrainData, out Vector3 volumePositionOffset)
		{
			terrainData = null;
			volumePositionOffset = Vector3.zero;

			if (volumeInfo.zLength == 1 && volumeInfo.tupleSize == 1)
			{
				// Heightfields will be converted to terrain in Unity.
				// Unity requires terrainData.heightmapResolution to be square power of two plus 1 (eg. 513, 257, 129, 65).
				// Houdini gives volumeInfo.xLength and volumeInfo.yLength which are the number of height values per dimension.
				// Note that volumeInfo.xLength and volumeInfo.yLength is equal to Houdini heightfield size / grid spacing.
				// The heightfield grid spacing is given as volumeTransformMatrix.scale but divided by 2 (grid spacing / 2 = volumeTransformMatrix.scale).
				// It is recommended to use grid spacing of 2.

				// Use the volumeInfo.transform to get the actual heightfield position and size.
				Matrix4x4 volumeTransformMatrix = HEU_HAPIUtility.GetMatrixFromHAPITransform(ref volumeInfo.transform, false);
				Vector3 position = HEU_HAPIUtility.GetPosition(ref volumeTransformMatrix);
				Vector3 scale = HEU_HAPIUtility.GetScale(ref volumeTransformMatrix);

				// Calculate real terrain size in both Houdini and Unity.
				// The height values will be mapped over this terrain size.
				float gridSpacingX = scale.x * 2f;
				float gridSpacingY = scale.y * 2f;
				//float gridSpacingZ = scale.z * 2f;
				float multiplierOffsetX = Mathf.Round(scale.x);
				float multiplierOffsetY = Mathf.Round(scale.y);
				//float multiplierOffsetZ = Mathf.Round(scale.z);
				float terrainSizeX = Mathf.Round(volumeInfo.xLength * gridSpacingX - multiplierOffsetX);
				float terrainSizeY = Mathf.Round(volumeInfo.yLength * gridSpacingY - multiplierOffsetY);

				//Debug.LogFormat("GS = {0},{1},{2}. SX = {1}. SY = {2}", gridSpacingX, gridSpacingY, gridSpacingZ, terrainSizeX, terrainSizeY);

				//Debug.LogFormat("HeightField Pos:{0}, Scale:{1}", position, scale.ToString("{0.00}"));
				//Debug.LogFormat("HeightField tileSize:{0}, xLength:{1}, yLength:{2}", volumeInfo.tileSize.ToString("{0.00}"), volumeInfo.xLength.ToString("{0.00}"), volumeInfo.yLength.ToString("{0.00}"));
				//Debug.LogFormat("HeightField Terrain Size x:{0}, y:{1}", terrainSizeX.ToString("{0.00}"), terrainSizeY.ToString("{0.00}"));
				//Debug.LogFormat("HeightField minX={0}, minY={1}, minZ={2}", volumeInfo.minX.ToString("{0.00}"), volumeInfo.minY.ToString("{0.00}"), volumeInfo.minZ.ToString("{0.00}"));

				const int UNITY_MINIMUM_HEIGHTMAP_RESOLUTION = 33;
				if (terrainSizeX < UNITY_MINIMUM_HEIGHTMAP_RESOLUTION || terrainSizeY < UNITY_MINIMUM_HEIGHTMAP_RESOLUTION)
				{
					Debug.LogWarningFormat("Unity Terrain has a minimum heightmap resolution of {0}. This HDA heightmap size is {1}x{2}."
						+ "\nPlease resize the terrain to a value higher than this.",
						UNITY_MINIMUM_HEIGHTMAP_RESOLUTION, terrainSizeX, terrainSizeY);
					return false;
				}

				Terrain terrain = HEU_GeneralUtility.GetOrCreateComponent<Terrain>(gameObject);
				TerrainCollider collider = HEU_GeneralUtility.GetOrCreateComponent<TerrainCollider>(gameObject);
				
				if (terrain.terrainData == null)
				{
					terrain.terrainData = new TerrainData();
				}

				terrainData = terrain.terrainData;
				collider.terrainData = terrainData;

				// Heightmap resolution must be square power-of-two plus 1. 
				// Unity will automatically resize terrainData.heightmapResolution so need to handle the changed size (if Unity changed it).
				int heightMapResolution = volumeInfo.xLength;
				terrainData.heightmapResolution = heightMapResolution;
				int terrainResizedDelta = terrainData.heightmapResolution - heightMapResolution;
				if (terrainResizedDelta < 0)
				{
					Debug.LogWarningFormat("Note that Unity automatically resized terrain resolution to {0} from {1}. Use terrain size of power of two plus 1, and grid spacing of 2.", heightMapResolution, terrainData.heightmapResolution);
					heightMapResolution = terrainData.heightmapResolution;
				}
				else if(terrainResizedDelta > 0)
				{
					Debug.LogErrorFormat("Unsupported terrain size. Use terrain size of power of two plus 1, and grid spacing of 2. (delta = {0})", terrainResizedDelta);
					return false;
				}

				// Get the height values from Houdini and find the min and max height range.
				int totalHeightValues = volumeInfo.xLength * volumeInfo.yLength;
				float[] heightValues = new float[totalHeightValues];

				bool bResult = HEU_GeneralUtility.GetArray2Arg(geoID, partID, session.GetHeightFieldData, heightValues, 0, totalHeightValues);
				if (!bResult)
				{
					return false;
				}

				float minHeight = heightValues[0];
				float maxHeight = minHeight;
				for (int i = 0; i < totalHeightValues; ++i)
				{
					float f = heightValues[i];
					if (f > maxHeight)
					{
						maxHeight = f;
					}
					else if (f < minHeight)
					{
						minHeight = f;
					}
				} 

				const int UNITY_MAX_HEIGHT_RANGE = 65536;
				float heightRange = (maxHeight - minHeight);
				if (Mathf.RoundToInt(heightRange) > UNITY_MAX_HEIGHT_RANGE)
				{
					Debug.LogWarningFormat("Unity Terrain has maximum height range of {0}. This HDA height range is {1}, so it will be maxed out at {0}.\nPlease resize to within valid range!",
						UNITY_MAX_HEIGHT_RANGE, Mathf.RoundToInt(heightRange));
					heightRange = UNITY_MAX_HEIGHT_RANGE;
				}

				int mapWidth = volumeInfo.xLength;
				int mapHeight = volumeInfo.yLength;

				int paddingWidth = heightMapResolution - mapWidth;
				int paddingLeft = Mathf.CeilToInt(paddingWidth * 0.5f);
				int paddingRight = heightMapResolution - paddingLeft;
				//Debug.LogFormat("Padding: Width={0}, Left={1}, Right={2}", paddingWidth, paddingLeft, paddingRight);

				int paddingHeight = heightMapResolution - mapHeight;
				int paddingTop = Mathf.CeilToInt(paddingHeight * 0.5f);
				int paddingBottom = heightMapResolution - paddingTop;
				//Debug.LogFormat("Padding: Height={0}, Top={1}, Bottom={2}", paddingHeight, paddingTop, paddingBottom);

				// Set height values at centre of the terrain, with padding on the sides if we resized
				float[,] unityHeights = new float[heightMapResolution, heightMapResolution];
				for (int y = 0; y < heightMapResolution; ++y)
				{
					for (int x = 0; x < heightMapResolution; ++x)
					{	
						if (y >= paddingTop && y < (paddingBottom) && x >= paddingLeft && x < (paddingRight))
						{
							int ay = x - paddingLeft;
							int ax = y - paddingTop;

							// Unity expects normalized height values
							float h = heightValues[ay + ax * mapWidth] - minHeight;
							float f = h / heightRange;

							// Flip for right-hand to left-handed coordinate system
							int ix = x;
							int iy = heightMapResolution - (y + 1);

							// Unity expects height array indexing to be [y, x].
							unityHeights[ix, iy] = f;
						}
					}
				}

				terrainData.baseMapResolution = heightMapResolution;
				terrainData.alphamapResolution = heightMapResolution;

				//int detailResolution = heightMapResolution;
				// 128 is the maximum for resolutionPerPatch
				const int resolutionPerPatch = 128;
				terrainData.SetDetailResolution(resolutionPerPatch, resolutionPerPatch);

				// Note SetHeights must be called before setting size in next line, as otherwise
				// the internal terrain size will not change after setting the size.
				terrainData.SetHeights(0, 0, unityHeights);

				terrainData.size = new Vector3(terrainSizeX, heightRange, terrainSizeY);

				terrain.Flush();

				// Unity Terrain has origin at bottom left, whereas Houdini uses centre of terrain. 

				// Use volume bounds to set position offset when using split tiles
				float xmin, xmax, zmin, zmax, ymin, ymax, xcenter, ycenter, zcenter;
				session.GetVolumeBounds(geoID, partID, out xmin, out ymin, out zmin, out xmax, out ymax, out zmax, out xcenter,
					out ycenter, out zcenter);
				//Debug.LogFormat("xmin: {0}, xmax: {1}, ymin: {2}, ymax: {3}, zmin: {4}, zmax: {5}, xc: {6}, yc: {7}, zc: {8}",
				//	xmin, xmax, ymin, ymax, zmin, zmax, xcenter, ycenter, zcenter);

				// Offset position is based on size of heightfield
				float offsetX = (float)heightMapResolution / (float)mapWidth;
				float offsetZ = (float)heightMapResolution / (float)mapHeight;
				//Debug.LogFormat("offsetX: {0}, offsetZ: {1}", offsetX, offsetZ);

				//Debug.LogFormat("position.x: {0}, position.z: {1}", position.x, position.z);

				//volumePositionOffset = new Vector3(-position.x * offsetX, minHeight + position.y, position.z * offsetZ);
				volumePositionOffset = new Vector3((terrainSizeX + xmin) * offsetX, minHeight + position.y, zmin * offsetZ);

				return true;
			}
			else
			{
				Debug.LogWarning("Non-heightfield volume type not supported!");
			}

			return false;
		}
예제 #7
0
		public static HEU_GenerateGeoCache GetPopulatedGeoCache(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID)
		{
#if HEU_PROFILER_ON
			float generateGeoCacheStartTime = Time.realtimeSinceStartup;
#endif

			HEU_GenerateGeoCache geoCache = new HEU_GenerateGeoCache();

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

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

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

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

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

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

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

			geoCache.PopulateUnityMaterialData(session);

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

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

			return geoCache;
		}