public void Initialize(HEU_GeoNode ownerNode, int tileIndex) { _ownerNode = ownerNode; _geoName = ownerNode.GeoName; _objName = ownerNode.ObjectNode.ObjectName; _tileIndex = tileIndex; _terrainData = null; _scatterTrees = null; }
public void ResetParameters() { _terrainData = null; _scatterTrees = null; HEU_VolumeLayer defaultLayer = new HEU_VolumeLayer(); foreach (HEU_VolumeLayer layer in _layers) { CopyLayer(defaultLayer, layer); } }
/// <summary> /// Apply the cached scatter prototypes and instances to the given TerrainData. /// </summary> public static void ApplyScatterTrees(TerrainData terrainData, HEU_VolumeScatterTrees scatterTrees) { #if UNITY_2019_1_OR_NEWER if (scatterTrees == null || scatterTrees._treePrototypInfos == null || scatterTrees._treePrototypInfos.Count == 0) { return; } // Load and set TreePrototypes GameObject prefabGO; List<TreePrototype> treePrototypes = new List<TreePrototype>(); for (int i = 0; i < scatterTrees._treePrototypInfos.Count; ++i) { prefabGO = HEU_AssetDatabase.LoadAssetAtPath(scatterTrees._treePrototypInfos[i]._prefabPath, typeof(GameObject)) as GameObject; if (prefabGO != null) { TreePrototype prototype = new TreePrototype(); prototype.prefab = prefabGO; prototype.bendFactor = scatterTrees._treePrototypInfos[i]._bendfactor; treePrototypes.Add(prototype); //Debug.LogFormat("Added Tree Prototype: {0} - {1}", scatterTrees._treePrototypInfos[i]._prefabPath, scatterTrees._treePrototypInfos[i]._bendfactor); } } terrainData.treePrototypes = treePrototypes.ToArray(); terrainData.RefreshPrototypes(); if (scatterTrees._positions != null && scatterTrees._positions.Length > 0 && scatterTrees._prototypeIndices != null && scatterTrees._prototypeIndices.Length == scatterTrees._positions.Length) { TreeInstance[] treeInstances = new TreeInstance[scatterTrees._positions.Length]; for (int i = 0; i < scatterTrees._positions.Length; ++i) { treeInstances[i] = new TreeInstance(); treeInstances[i].color = scatterTrees._colors != null ? scatterTrees._colors[i] : new Color32(255, 255, 255, 255); treeInstances[i].heightScale = scatterTrees._heightScales != null ? scatterTrees._heightScales[i] : 1f; treeInstances[i].lightmapColor = scatterTrees._lightmapColors != null ? scatterTrees._lightmapColors[i] : new Color32(255, 255, 255, 255); treeInstances[i].position = scatterTrees._positions[i]; treeInstances[i].prototypeIndex = scatterTrees._prototypeIndices[i]; treeInstances[i].rotation = scatterTrees._rotations[i]; treeInstances[i].widthScale = scatterTrees._widthScales != null ? scatterTrees._widthScales[i] : 1f; } terrainData.SetTreeInstances(treeInstances, true); } #endif }
public void UpdateLayerFromPart(HEU_SessionBase session, HEU_PartData part) { HEU_GeoNode geoNode = part.ParentGeoNode; HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo(); bool bResult = session.GetVolumeInfo(geoNode.GeoID, part.PartID, ref volumeInfo); if (!bResult || volumeInfo.tupleSize != 1 || volumeInfo.zLength != 1 || volumeInfo.storage != HAPI_StorageType.HAPI_STORAGETYPE_FLOAT) { return; } string volumeName = HEU_SessionManager.GetString(volumeInfo.nameSH, session); part.SetVolumeLayerName(volumeName); //Debug.LogFormat("Part name: {0}, GeoName: {1}, Volume Name: {2}, Display: {3}", part.PartName, geoNode.GeoName, volumeName, geoNode.Displayable); bool bHeightPart = volumeName.Equals(HEU_Defines.HAPI_HEIGHTFIELD_LAYERNAME_HEIGHT); bool bMaskPart = volumeName.Equals(HEU_Defines.HAPI_HEIGHTFIELD_LAYERNAME_MASK); HEU_VolumeLayer layer = GetLayer(volumeName); if (layer == null) { layer = new HEU_VolumeLayer(); layer._layerName = volumeName; if (bHeightPart) { _layers.Insert(0, layer); } else if(!bMaskPart) { _layers.Add(layer); } } layer._part = part; layer._xLength = volumeInfo.xLength; layer._yLength = volumeInfo.yLength; if (!bMaskPart) { GetPartLayerAttributes(session, geoNode.GeoID, part.PartID, layer); } if (!bHeightPart) { // Non-height parts don't have any outputs as they are simply layers carrying info part.DestroyAllData(); } else { // Height part List<HEU_TreePrototypeInfo> treePrototypeInfos = HEU_TerrainUtility.GetTreePrototypeInfosFromPart(session, geoNode.GeoID, part.PartID); if (treePrototypeInfos != null) { if (_scatterTrees == null) { _scatterTrees = new HEU_VolumeScatterTrees(); } _scatterTrees._treePrototypInfos = treePrototypeInfos; } } if (!_updatedLayers.Contains(layer)) { if (bHeightPart) { _updatedLayers.Insert(0, layer); } else if (!bMaskPart) { _updatedLayers.Add(layer); } } }
/// <summary> /// Grab the scatter data for the given part. /// This finds the properties of TreeInstances via attributes. /// </summary> /// <param name="session">Houdini session</param> /// <param name="geoID">Geometry ID</param> /// <param name="partID">Part (volume layer) ID</param> /// <param name="pointCount">Number of expected scatter points</param> public static void PopulateScatterTrees(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID, int pointCount, ref HEU_VolumeScatterTrees scatterTrees) { // The HEU_VolumeScatterTrees might already have been created when the volumecache was queried. // The "height" layer might have had prototype data which is set in _scatterTrees. if (scatterTrees == null) { scatterTrees = new HEU_VolumeScatterTrees(); } // Get prototype indices. These indices refer to _scatterTrees._treePrototypes. HAPI_AttributeInfo indicesAttrInfo = new HAPI_AttributeInfo(); int[] indices = new int[0]; if (HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HEIGHTFIELD_TREEINSTANCE_PROTOTYPEINDEX, ref indicesAttrInfo, ref indices, session.GetAttributeIntData)) { if (indices != null && indices.Length == pointCount) { scatterTrees._prototypeIndices = indices; } else { Debug.LogWarningFormat("Scatter instance index count for attribute {0} is not valid. Expected {1} but got {2}", HEU_Defines.HEIGHTFIELD_TREEINSTANCE_PROTOTYPEINDEX, pointCount, (indices != null ? indices.Length : 0)); } } // Using the UVs as position of the instances, since they are properly mapped to the terrain tile. // Also getting other attributes for the TreeInstances, if they are set. HAPI_AttributeInfo uvAttrInfo = new HAPI_AttributeInfo(); float[] uvs = new float[0]; if (!HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HAPI_ATTRIB_UV, ref uvAttrInfo, ref uvs, session.GetAttributeFloatData)) { Debug.LogWarning("UVs for scatter instances not found or valid."); } if (uvs != null && uvs.Length == (pointCount * uvAttrInfo.tupleSize)) { // Get height scales HAPI_AttributeInfo heightAttrInfo = new HAPI_AttributeInfo(); float[] heightscales = new float[0]; HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HEIGHTFIELD_TREEINSTANCE_HEIGHTSCALE, ref heightAttrInfo, ref heightscales, session.GetAttributeFloatData); // Get width scales HAPI_AttributeInfo widthAttrInfo = new HAPI_AttributeInfo(); float[] widthscales = new float[0]; HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HEIGHTFIELD_TREEINSTANCE_WIDTHSCALE, ref widthAttrInfo, ref widthscales, session.GetAttributeFloatData); // Get orientation HAPI_AttributeInfo orientAttrInfo = new HAPI_AttributeInfo(); float[] orients = new float[0]; HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HAPI_ATTRIB_ORIENT, ref orientAttrInfo, ref orients, session.GetAttributeFloatData); // Get color HAPI_AttributeInfo colorAttrInfo = new HAPI_AttributeInfo(); float[] colors = new float[0]; HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HAPI_ATTRIB_COLOR, ref colorAttrInfo, ref colors, session.GetAttributeFloatData); // Get lightmap color HAPI_AttributeInfo lightmapColorAttrInfo = new HAPI_AttributeInfo(); float[] lightmapColors = new float[0]; HEU_GeneralUtility.GetAttribute(session, geoID, partID, HEU_Defines.HEIGHTFIELD_TREEINSTANCE_LIGHTMAPCOLOR, ref lightmapColorAttrInfo, ref lightmapColors, session.GetAttributeFloatData); scatterTrees._positions = new Vector3[pointCount]; if (heightAttrInfo.exists && (heightscales.Length == pointCount)) { scatterTrees._heightScales = heightscales; } if (widthAttrInfo.exists && (widthscales.Length == pointCount)) { scatterTrees._widthScales = widthscales; } if (orientAttrInfo.exists && (orients.Length == orientAttrInfo.tupleSize * pointCount)) { scatterTrees._rotations = new float[pointCount]; } if (colorAttrInfo.exists && (colors.Length == colorAttrInfo.tupleSize * pointCount)) { scatterTrees._colors = new Color32[pointCount]; } if (lightmapColorAttrInfo.exists && (lightmapColors.Length == lightmapColorAttrInfo.tupleSize * pointCount)) { scatterTrees._lightmapColors = new Color32[pointCount]; } for (int i = 0; i < pointCount; ++i) { scatterTrees._positions[i] = new Vector3(1.0f - uvs[i * uvAttrInfo.tupleSize + 1], 0, uvs[i * uvAttrInfo.tupleSize + 0]); if (scatterTrees._colors != null) { scatterTrees._colors[i] = new Color32((byte)(colors[i * colorAttrInfo.tupleSize + 0] * 255), (byte)(colors[i * colorAttrInfo.tupleSize + 1] * 255), (byte)(colors[i * colorAttrInfo.tupleSize + 2] * 255), (byte)(colors[i * colorAttrInfo.tupleSize + 3] * 255)); } if (scatterTrees._lightmapColors != null) { scatterTrees._lightmapColors[i] = new Color32((byte)(lightmapColors[i * lightmapColorAttrInfo.tupleSize + 0] * 255), (byte)(lightmapColors[i * lightmapColorAttrInfo.tupleSize + 1] * 255), (byte)(lightmapColors[i * lightmapColorAttrInfo.tupleSize + 2] * 255), (byte)(lightmapColors[i * lightmapColorAttrInfo.tupleSize + 3] * 255)); } if (scatterTrees._rotations != null) { Quaternion quaternion = new Quaternion( orients[i * orientAttrInfo.tupleSize + 0], orients[i * orientAttrInfo.tupleSize + 1], orients[i * orientAttrInfo.tupleSize + 2], orients[i * orientAttrInfo.tupleSize + 3]); Vector3 euler = quaternion.eulerAngles; euler.y = -euler.y; euler.z = -euler.z; scatterTrees._rotations[i] = euler.y * Mathf.Deg2Rad; } } } }
public void UpdateLayerFromPart(HEU_SessionBase session, HEU_PartData part) { HEU_GeoNode geoNode = part.ParentGeoNode; HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo(); bool bResult = session.GetVolumeInfo(geoNode.GeoID, part.PartID, ref volumeInfo); if (!bResult || volumeInfo.tupleSize != 1 || volumeInfo.zLength != 1 || volumeInfo.storage != HAPI_StorageType.HAPI_STORAGETYPE_FLOAT) { return; } string volumeName = HEU_SessionManager.GetString(volumeInfo.nameSH, session); part.SetVolumeLayerName(volumeName); //Debug.LogFormat("Part name: {0}, GeoName: {1}, Volume Name: {2}, Display: {3}", part.PartName, geoNode.GeoName, volumeName, geoNode.Displayable); HFLayerType layerType = HEU_TerrainUtility.GetHeightfieldLayerType(session, geoNode.GeoID, part.PartID, volumeName); HEU_VolumeLayer layer = GetLayer(volumeName); if (layer == null) { layer = new HEU_VolumeLayer(); layer._layerName = volumeName; if (layerType == HFLayerType.HEIGHT) { _layers.Insert(0, layer); } else if (layerType != HFLayerType.MASK) { _layers.Add(layer); } } layer._part = part; layer._xLength = volumeInfo.xLength; layer._yLength = volumeInfo.yLength; layer._layerType = layerType; if (layerType != HFLayerType.MASK) { GetPartLayerAttributes(session, geoNode.GeoID, part.PartID, layer); } if (layerType != HFLayerType.HEIGHT) { // Non-height parts don't have any outputs as they are simply layers carrying info part.DestroyAllData(); } else { // Height part // Might contain terrain properties via attributes (i.e. not layer specific, but for entire terrain) // Scatter Tree Prototypes List<HEU_TreePrototypeInfo> treePrototypeInfos = HEU_TerrainUtility.GetTreePrototypeInfosFromPart(session, geoNode.GeoID, part.PartID); if (treePrototypeInfos != null) { if (_scatterTrees == null) { _scatterTrees = new HEU_VolumeScatterTrees(); } _scatterTrees._treePrototypInfos = treePrototypeInfos; } HEU_TerrainUtility.PopulateDetailProperties(session, geoNode.GeoID, part.PartID, ref _detailProperties); } if (!_updatedLayers.Contains(layer)) { if (layerType == HFLayerType.HEIGHT) { _updatedLayers.Insert(0, layer); } else if (layerType != HFLayerType.MASK) { _updatedLayers.Add(layer); } } }
public void UpdateLayerFromPart(HEU_SessionBase session, HEU_PartData part) { HEU_GeoNode geoNode = part.ParentGeoNode; HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo(); bool bResult = session.GetVolumeInfo(geoNode.GeoID, part.PartID, ref volumeInfo); if (!bResult || volumeInfo.tupleSize != 1 || volumeInfo.zLength != 1 || volumeInfo.storage != HAPI_StorageType.HAPI_STORAGETYPE_FLOAT) { return; } string volumeName = HEU_SessionManager.GetString(volumeInfo.nameSH, session); part.SetVolumeLayerName(volumeName); //Debug.LogFormat("Part name: {0}, GeoName: {1}, Volume Name: {2}, Display: {3}", part.PartName, geoNode.GeoName, volumeName, geoNode.Displayable); HEU_VolumeLayer.HFLayerType layerType = GetHeightfieldLayerType(session, geoNode.GeoID, part.PartID, volumeName); HEU_VolumeLayer layer = GetLayer(volumeName); if (layer == null) { layer = new HEU_VolumeLayer(); layer._layerName = volumeName; if (layerType == HEU_VolumeLayer.HFLayerType.HEIGHT) { _layers.Insert(0, layer); } else if(layerType != HEU_VolumeLayer.HFLayerType.MASK) { _layers.Add(layer); } } layer._part = part; layer._xLength = volumeInfo.xLength; layer._yLength = volumeInfo.yLength; layer._layerType = layerType; if (layerType != HEU_VolumeLayer.HFLayerType.MASK) { GetPartLayerAttributes(session, geoNode.GeoID, part.PartID, layer); } if (layerType != HEU_VolumeLayer.HFLayerType.HEIGHT) { // Non-height parts don't have any outputs as they are simply layers carrying info part.DestroyAllData(); } else { // Height part // Might contain terrain properties via attributes (i.e. not layer specific, but for entire terrain) // Scatter Tree Prototypes List<HEU_TreePrototypeInfo> treePrototypeInfos = HEU_TerrainUtility.GetTreePrototypeInfosFromPart(session, geoNode.GeoID, part.PartID); if (treePrototypeInfos != null) { if (_scatterTrees == null) { _scatterTrees = new HEU_VolumeScatterTrees(); } _scatterTrees._treePrototypInfos = treePrototypeInfos; } // Detail distance HAPI_AttributeInfo detailDistanceAttrInfo = new HAPI_AttributeInfo(); int[] detailDistances = new int[0]; HEU_GeneralUtility.GetAttribute(session, geoNode.GeoID, part.PartID, HEU_Defines.HEIGHTFIELD_DETAIL_DISTANCE, ref detailDistanceAttrInfo, ref detailDistances, session.GetAttributeIntData); // Scatter Detail Resolution Per Patch (note that Detail Resolution comes from HF layer size) HAPI_AttributeInfo resolutionPatchAttrInfo = new HAPI_AttributeInfo(); int[] resolutionPatches = new int[0]; HEU_GeneralUtility.GetAttribute(session, geoNode.GeoID, part.PartID, HEU_Defines.HEIGHTFIELD_DETAIL_RESOLUTION_PER_PATCH, ref resolutionPatchAttrInfo, ref resolutionPatches, session.GetAttributeIntData); if (_detailProperties == null) { _detailProperties = new HEU_DetailProperties(); } // Unity only supports 1 set of detail resolution properties per terrain int arraySize = 1; if (detailDistanceAttrInfo.exists && detailDistances.Length >= arraySize) { _detailProperties._detailDistance = detailDistances[0]; } if (resolutionPatchAttrInfo.exists && resolutionPatches.Length >= arraySize) { _detailProperties._detailResolutionPerPatch = resolutionPatches[0]; } } if (!_updatedLayers.Contains(layer)) { if (layerType == HEU_VolumeLayer.HFLayerType.HEIGHT) { _updatedLayers.Insert(0, layer); } else if (layerType != HEU_VolumeLayer.HFLayerType.MASK) { _updatedLayers.Add(layer); } } }