public void Initialize(HEU_GeoNode ownerNode, int tileIndex) { _ownerNode = ownerNode; _geoName = ownerNode.GeoName; _objName = ownerNode.ObjectNode.ObjectName; _tileIndex = tileIndex; }
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_GeoNode ownerNode, int tileIndex) { _ownerNode = ownerNode; _geoName = ownerNode.GeoName; _objName = ownerNode.ObjectNode.ObjectName; _tileIndex = tileIndex; _terrainData = null; _scatterTrees = null; }
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("height"); HEU_VolumeLayer layer = GetLayer(volumeName); if (layer == null) { layer = new HEU_VolumeLayer(); layer._layerName = volumeName; if (bHeightPart) { _layers.Insert(0, layer); } else { _layers.Add(layer); } } layer._part = part; GetPartLayerAttributes(session, geoNode.GeoID, part.PartID, layer); if (!bHeightPart) { part.DestroyAllData(); } if (!_updatedLayers.Contains(layer)) { if (bHeightPart) { _updatedLayers.Insert(0, layer); } else { _updatedLayers.Add(layer); } } }
private void UpdateVolumeLayers(HEU_SessionBase session, HEU_HoudiniAsset houdiniAsset, List<HEU_PartData> volumeParts) { bool bResult; foreach (HEU_PartData part in volumeParts) { HEU_GeoNode geoNode = part.ParentGeoNode; HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo(); bResult = session.GetVolumeInfo(geoNode.GeoID, part.PartID, ref volumeInfo); if (!bResult || volumeInfo.tupleSize != 1 || volumeInfo.zLength != 1 || volumeInfo.storage != HAPI_StorageType.HAPI_STORAGETYPE_FLOAT) { continue; } 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("height"); HEU_VolumeLayer layer = GetLayer(volumeName); if (layer == null) { layer = new HEU_VolumeLayer(); layer._layerName = volumeName; layer._splatTexture = LoadDefaultSplatTexture(); if (bHeightPart) { _layers.Insert(0, layer); } else { _layers.Add(layer); } } layer._part = part; if (!bHeightPart) { part.DestroyAllData(); } } }
private void ParseVolumeDatas(HEU_SessionBase session, List<HEU_PartData> volumeParts) { bool bResult; foreach (HEU_PartData part in volumeParts) { HEU_GeoNode geoNode = part.ParentGeoNode; HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo(); bResult = session.GetVolumeInfo(geoNode.GeoID, part.PartID, ref volumeInfo); if(!bResult || volumeInfo.tupleSize != 1 || volumeInfo.zLength != 1 || volumeInfo.storage != HAPI_StorageType.HAPI_STORAGETYPE_FLOAT) { continue; } string volumeName = HEU_SessionManager.GetString(volumeInfo.nameSH, session); //Debug.LogFormat("Part name: {0}, GeoName: {1}, Volume Name: {2}, Display: {3}", part.PartName, geoNode.GeoName, volumeName, geoNode.Displayable); if(volumeName.Equals("height")) { if (_heightMapVolumeData == null) { _heightMapVolumeData = new HEU_VolumeData(); _heightMapVolumeData._partData = part; _heightMapVolumeData._volumeInfo = volumeInfo; } } else { HEU_VolumeData volumeData = new HEU_VolumeData(); volumeData._partData = part; volumeData._volumeInfo = volumeInfo; _textureVolumeDatas.Add(volumeData); } } }
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); } } }
// LOGIC ----------------------------------------------------------------------------------------------------- public static List<HEU_VolumeCache> UpdateVolumeCachesFromParts(HEU_SessionBase session, HEU_GeoNode ownerNode, List<HEU_PartData> volumeParts, List<HEU_VolumeCache> volumeCaches) { HEU_HoudiniAsset parentAsset = ownerNode.ParentAsset; foreach (HEU_VolumeCache cache in volumeCaches) { // Remove current volume caches from parent asset. // These get added back in below. parentAsset.RemoveVolumeCache(cache); // Mark the cache for updating cache.StartUpdateLayers(); } // This will keep track of volume caches still in use List<HEU_VolumeCache> updatedCaches = new List<HEU_VolumeCache>(); int numParts = volumeParts.Count; for (int i = 0; i < numParts; ++i) { // Get the tile index, if it exists, for this part HAPI_AttributeInfo tileAttrInfo = new HAPI_AttributeInfo(); int[] tileAttrData = new int[0]; HEU_GeneralUtility.GetAttribute(session, ownerNode.GeoID, volumeParts[i].PartID, HEU_Defines.HAPI_HEIGHTFIELD_TILE_ATTR, ref tileAttrInfo, ref tileAttrData, session.GetAttributeIntData); if (tileAttrData != null && tileAttrData.Length > 0) { //Debug.LogFormat("Tile: {0}", tileAttrData[0]); int tile = tileAttrData[0]; HEU_VolumeCache volumeCache = null; // Find cache in updated list for (int j = 0; j < updatedCaches.Count; ++j) { if (updatedCaches[j] != null && updatedCaches[j].TileIndex == tile) { volumeCache = updatedCaches[j]; break; } } if (volumeCache != null) { volumeCache.UpdateLayerFromPart(session, volumeParts[i]); // Skip adding new cache since already found in updated list continue; } // Find existing cache in old list if (volumeCaches != null && volumeCaches.Count > 0) { for(int j = 0; j < volumeCaches.Count; ++j) { if (volumeCaches[j] != null && volumeCaches[j].TileIndex == tile) { volumeCache = volumeCaches[j]; break; } } } // Create new cache for this tile if not found if (volumeCache == null) { volumeCache = ScriptableObject.CreateInstance<HEU_VolumeCache>(); volumeCache.Initialize(ownerNode, tile); volumeCache.StartUpdateLayers(); } volumeCache.UpdateLayerFromPart(session, volumeParts[i]); if (!updatedCaches.Contains(volumeCache)) { updatedCaches.Add(volumeCache); } } else { // No tile index. Most likely a single terrain tile. HEU_VolumeCache volumeCache = null; if (updatedCaches.Count == 0) { // Create a single volume cache, or use existing if it was just 1. // If more than 1 volume cache exists, this will recreate a single one if (volumeCaches == null || volumeCaches.Count != 1) { volumeCache = ScriptableObject.CreateInstance<HEU_VolumeCache>(); volumeCache.Initialize(ownerNode, 0); volumeCache.StartUpdateLayers(); } else if (volumeCaches.Count == 1) { // Keep the single volumecache volumeCache = volumeCaches[0]; } if (!updatedCaches.Contains(volumeCache)) { updatedCaches.Add(volumeCache); } } else { // Reuse the updated cache volumeCache = updatedCaches[0]; } volumeCache.UpdateLayerFromPart(session, volumeParts[i]); } } foreach (HEU_VolumeCache cache in updatedCaches) { // Add to parent for UI and preset parentAsset.AddVolumeCache(cache); // Finish update by keeping just the layers in use for each volume cache. cache.FinishUpdateLayers(); } return updatedCaches; }
public void GenerateGeometry(HEU_SessionBase session, bool bRebuild) { // Volumes could come in as a geonode + part for each heightfield layer. // Otherwise the other geo types can be done individually. bool bResult = false; List<HEU_PartData> meshParts = new List<HEU_PartData>(); List<HEU_PartData> volumeParts = new List<HEU_PartData>(); List<HEU_PartData> partsToDestroy = new List<HEU_PartData>(); HEU_HoudiniAsset parentAsset = ParentAsset; foreach (HEU_GeoNode geoNode in _geoNodes) { geoNode.GetPartsByOutputType(meshParts, volumeParts); if (volumeParts.Count > 0) { // Volumes // Each layer in the volume is retrieved as a volume part, in the display geo node. // But we need to handle all layers as 1 terrain output in Unity, with 1 height layer and // other layers as alphamaps. geoNode.ProcessVolumeParts(session, volumeParts, bRebuild); // Clear the volume parts after processing since we are done with this set volumeParts.Clear(); } } // Meshes foreach (HEU_PartData part in meshParts) { // This returns false when there is no valid geometry or is not instancing. Should remove it as otherwise // stale data sticks around on recook bResult = part.GenerateMesh(session, parentAsset.GenerateUVs, parentAsset.GenerateTangents, parentAsset.GenerateNormals, parentAsset.UseLODGroups); if (!bResult) { partsToDestroy.Add(part); } } int numPartsToDestroy = partsToDestroy.Count; for (int i = 0; i < numPartsToDestroy; ++i) { HEU_GeoNode parentNode = partsToDestroy[i].ParentGeoNode; if (parentNode != null) { parentNode.RemoveAndDestroyPart(partsToDestroy[i]); } else { HEU_PartData.DestroyPart(partsToDestroy[i]); } } partsToDestroy.Clear(); ApplyObjectTransformToGeoNodes(); // Set visibility and attribute-based tag, layer, and scripts bool bIsVisible = IsVisible(); foreach (HEU_GeoNode geoNode in _geoNodes) { geoNode.CalculateVisiblity(bIsVisible); geoNode.CalculateColliderState(); geoNode.SetAttributeModifiersOnPartOutputs(session); } // Create editable attributes. // This should happen after visibility has been calculated above // since we need to show/hide the intermediate geometry during painting. foreach (HEU_PartData part in meshParts) { if (part.ParentGeoNode.IsIntermediateOrEditable()) { part.SetupAttributeGeometry(session); } } }
public void GenerateGeometry(HEU_SessionBase session) { // Volumes could come in as a geonode + part for each heightfield layer. // Otherwise the other geo types can be done individually. bool bResult = false; List<HEU_PartData> meshParts = new List<HEU_PartData>(); List<HEU_PartData> volumeParts = new List<HEU_PartData>(); List<HEU_PartData> partsToDestroy = new List<HEU_PartData>(); HEU_HoudiniAsset parentAsset = ParentAsset; foreach (HEU_GeoNode geoNode in _geoNodes) { geoNode.GetPartsByOutputType(meshParts, volumeParts); } // Meshes foreach (HEU_PartData part in meshParts) { bResult = part.GenerateMesh(session, parentAsset.GenerateUVs, parentAsset.GenerateTangents, parentAsset.GenerateNormals, parentAsset.UseLODGroups); if (!bResult) { partsToDestroy.Add(part); } } #if TERRAIN_SUPPORTED // Volumes // Each layer in the volume is retrieved as a volume part, in the display geo node. // But we need to handle all layers as 1 terrain output in Unity, with 1 height layer and // other layers as alphamaps. if (volumeParts.Count > 0) { HEU_PartData heightLayerPart = null; HEU_VolumeCache volumeCache = new HEU_VolumeCache(); volumeCache.GenerateTerrainFromParts(session, volumeParts, ParentAsset, out heightLayerPart); // Remove volume parts that are not the height layer (even if heightLayerPart is null) foreach (HEU_PartData part in volumeParts) { if (part != heightLayerPart) { partsToDestroy.Add(part); } } } #endif int numPartsToDestroy = partsToDestroy.Count; for(int i = 0; i < numPartsToDestroy; ++i) { HEU_GeoNode parentNode = partsToDestroy[i].ParentGeoNode; if (parentNode != null) { parentNode.RemoveAndDestroyPart(partsToDestroy[i]); } else { HEU_PartData.DestroyPart(partsToDestroy[i]); } } partsToDestroy.Clear(); ApplyObjectTransformToGeoNodes(); // Set visibility bool bIsVisible = IsVisible(); foreach (HEU_GeoNode geoNode in _geoNodes) { geoNode.CalculateVisiblity(bIsVisible); } // Create editable attributes. // This should happen after visibility has been calculated above // since we need to show/hide the intermediate geometry during painting. foreach (HEU_PartData part in meshParts) { if (part.ParentGeoNode.IsIntermediateOrEditable()) { part.SetupAttributeGeometry(session); } } }
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); } } }
// LOGIC ----------------------------------------------------------------------------------------------------- public void Initialize(HEU_GeoNode ownerNode) { _ownerNode = ownerNode; _geoName = ownerNode.GeoName; _objName = ownerNode.ObjectNode.ObjectName; }
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); } } }