コード例 #1
0
        /// <summary>
        /// Generate the instances of instancer parts.
        /// </summary>
        internal void GeneratePartInstances(HEU_SessionBase session)
        {
            List <HEU_PartData> partsToDestroy = new List <HEU_PartData>();
            int numParts = _parts.Count;

            for (int i = 0; i < numParts; ++i)
            {
                if (_parts[i].IsPartInstancer() && !_parts[i].HaveInstancesBeenGenerated())
                {
                    if (!_parts[i].GeneratePartInstances(session))
                    {
                        partsToDestroy.Add(_parts[i]);
                    }
                }
            }

            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();
        }
コード例 #2
0
        /// <summary>
        /// Destroy all generated data.
        /// </summary>
        public void DestroyAllData()
        {
            HEU_PartData.DestroyParts(_parts);

            if (_inputNode != null)
            {
                HEU_SessionBase session = null;
                if (ParentAsset != null)
                {
                    ParentAsset.RemoveInputNode(_inputNode);
                    session = ParentAsset.GetAssetSession(false);
                }

                _inputNode.DestroyAllData(session);
                HEU_GeneralUtility.DestroyImmediate(_inputNode);
                _inputNode = null;
            }

            if (_geoCurve != null)
            {
                if (ParentAsset != null)
                {
                    ParentAsset.RemoveCurve(_geoCurve);
                }
                _geoCurve.DestroyAllData();
                HEU_GeneralUtility.DestroyImmediate(_geoCurve);
                _geoCurve = null;
            }

            DestroyVolumeCache();
        }
コード例 #3
0
        private void SetupGameObjectAndTransform(HEU_PartData partData, HEU_HoudiniAsset parentAsset)
        {
            // Set a valid gameobject for this part
            if (partData.OutputGameObject == null)
            {
                partData.SetGameObject(new GameObject());
            }

            // The parent is either the asset root, OR if this is instanced and not visible, then the HDA data is the parent
            // The parent transform is either the asset root (for a display node),
            // or the HDA_Data gameobject (for instanced, not visible, intermediate, editable non-display nodes)
            Transform partTransform = partData.OutputGameObject.transform;

            if (partData.IsPartInstanced() ||
                (_containerObjectNode.IsInstanced() && !_containerObjectNode.IsVisible()) ||
                partData.IsPartCurve() ||
                (IsIntermediateOrEditable() && !Displayable))
            {
                partTransform.parent = parentAsset.OwnerGameObject.transform;
            }
            else
            {
                partTransform.parent = parentAsset.RootGameObject.transform;
            }

            partData.OutputGameObject.isStatic = partTransform.parent.gameObject.isStatic;

            // Reset to origin
            partTransform.localPosition = Vector3.zero;
            partTransform.localRotation = Quaternion.identity;
            partTransform.localScale    = Vector3.one;
        }
コード例 #4
0
		public void UpdateLayerFromPart(HEU_SessionBase session, HEU_PartData part)
		{
			HEU_GeoNode geoNode = part.ParentGeoNode;

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

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

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

			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);
				}
			}
		}
コード例 #5
0
		public static void DestroyBakedGameObjectsWithEndName(List<GameObject> gameObjectsToDestroy, string endName)
		{
			int numLeft = gameObjectsToDestroy.Count;
			for (int i = 0; i < numLeft; ++i)
			{
				GameObject deleteGO = gameObjectsToDestroy[i];
				if (string.IsNullOrEmpty(endName) || deleteGO.name.EndsWith(endName))
				{
					gameObjectsToDestroy[i] = null;
					HEU_PartData.DestroyExistingGeneratedComponentsMeshData(deleteGO, true);
					HEU_GeneralUtility.DestroyImmediate(deleteGO);
				}
			}
		}
コード例 #6
0
        /// <summary>
        /// Returns the HEU_PartData with the given output gameobject.
        /// </summary>
        /// <param name="outputGameObject">The output gameobject to check</param>
        /// <returns>Valid HEU_PartData or null if no match</returns>
        public HEU_PartData GetHDAPartWithGameObject(GameObject outputGameObject)
        {
            HEU_PartData foundPart = null;

            foreach (HEU_PartData part in _parts)
            {
                foundPart = part.GetHDAPartWithGameObject(outputGameObject);
                if (foundPart != null)
                {
                    return(foundPart);
                }
            }
            return(null);
        }
コード例 #7
0
	/// <summary>
	/// Returns the HEU_PartData with the given output gameobject.
	/// </summary>
	/// <param name="outputGameObject">The output gameobject to check</param>
	/// <returns>Valid HEU_PartData or null if no match</returns>
	public HEU_PartData GetHDAPartWithGameObject(GameObject outputGameObject)
	{
	    HEU_PartData foundPart = null;
	    foreach (HEU_GeoNode geoNode in _geoNodes)
	    {
		foundPart = geoNode.GetHDAPartWithGameObject(outputGameObject);
		if (foundPart != null)
		{
		    return foundPart;
		}
	    }

	    return null;
	}
コード例 #8
0
        public void GetPartsByOutputType(List <HEU_PartData> meshParts, List <HEU_PartData> volumeParts)
        {
            int numParts = _parts.Count;

            for (int i = 0; i < numParts; ++i)
            {
                HEU_PartData part = _parts[i];
                if (part.IsPartMesh() || part.IsPartCurve())
                {
                    meshParts.Add(part);
                }
                else if (part.IsPartVolume())
                {
                    volumeParts.Add(part);
                }
            }
        }
コード例 #9
0
        private void SetupGameObjectAndTransform(HEU_PartData partData, HEU_HoudiniAsset parentAsset)
        {
            // Checking for nulls for undo safety
            if (partData == null || parentAsset == null || parentAsset.OwnerGameObject == null || parentAsset.RootGameObject == null)
            {
                return;
            }

            // Set a valid gameobject for this part
            if (partData.OutputGameObject == null)
            {
                partData.SetGameObject(HEU_GeneralUtility.CreateNewGameObject());
            }

            // The parent is either the asset root, OR if this is instanced and not visible, then the HDA data is the parent
            // The parent transform is either the asset root (for a display node),
            // or the HDA_Data gameobject (for instanced, not visible, intermediate, editable non-display nodes)
            Transform partTransform = partData.OutputGameObject.transform;

            if (partData.IsPartInstanced() ||
                (_containerObjectNode.IsInstanced() && !_containerObjectNode.IsVisible()) ||
                partData.IsPartCurve() ||
                (IsIntermediateOrEditable() && !Displayable))
            {
                partTransform.parent = parentAsset.OwnerGameObject.transform;
            }
            else
            {
                partTransform.parent = parentAsset.RootGameObject.transform;
            }

            HEU_GeneralUtility.CopyFlags(partTransform.parent.gameObject, partData.OutputGameObject, true);

            // Reset to origin
            partTransform.localPosition = Vector3.zero;
            partTransform.localRotation = Quaternion.identity;
            partTransform.localScale    = Vector3.one;

            // Destroy the children generated from ComposeNChildren
            HEU_GeneralUtility.DestroyAutoGeneratedChildren(partData.OutputGameObject);
        }
コード例 #10
0
	public static void BakeGameObjectComponents(GameObject sourceGO, GameObject targetGO, string assetName, string outputPath, bool bIsInstancer)
	{
	    UnityEngine.Object assetDBObject = null;
	    Dictionary<Mesh, Mesh> sourceToTargetMeshMap = new Dictionary<Mesh, Mesh>();
	    Dictionary<Material, Material> sourceToCopiedMaterials = new Dictionary<Material, Material>();
	    string newAssetDBObjectFileName = HEU_AssetDatabase.AppendMeshesAssetFileName(assetName);

	    HEU_PartData.BakePartToGameObject(
		    partData: null,
		    srcGO: sourceGO,
		    targetGO: targetGO,
		    assetName: assetName,
		    bIsInstancer: bIsInstancer,
		    bDeleteExistingComponents: false, // Materials might be overwritten if true
		    bDontDeletePersistantResources: false,
		    bWriteMeshesToAssetDatabase: true,
		    bakedAssetPath: ref outputPath,
		    sourceToTargetMeshMap,
		    sourceToCopiedMaterials,
		    assetDBObject: ref assetDBObject,
		    assetObjectFileName: newAssetDBObjectFileName,
		    bReconnectPrefabInstances: false,
		    bKeepPreviousTransformValues: false ); 
	}
コード例 #11
0
ファイル: HEU_ObjectNode.cs プロジェクト: all-in-one-of/pds
		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);
				}
			}
		}
コード例 #12
0
        /// <summary>
        /// Process the part at the given index, creating its data (geometry),
        /// and adding it to the list of parts.
        /// </summary>
        /// <param name="session"></param>
        /// <param name="partID"></param>
        /// <returns>A valid HEU_PartData if it has been successfully processed.</returns>
        private void ProcessPart(HEU_SessionBase session, int partID, ref HAPI_PartInfo partInfo, ref HEU_PartData partData)
        {
            HEU_HoudiniAsset parentAsset = ParentAsset;
            bool             bResult     = true;

            //Debug.LogFormat("Part: name={0}, id={1}, type={2}, instanced={3}, instance count={4}, instance part count={5}", HEU_SessionManager.GetString(partInfo.nameSH, session), partID, partInfo.type, partInfo.isInstanced, partInfo.instanceCount, partInfo.instancedPartCount);

#if HEU_PROFILER_ON
            float processPartStartTime = Time.realtimeSinceStartup;
#endif

            bool isPartEditable    = IsIntermediateOrEditable();
            bool isAttribInstancer = false;

            if (IsGeoInputType())
            {
                // Setup for input node to accept inputs
                if (_inputNode == null)
                {
                    string partName = HEU_SessionManager.GetString(partInfo.nameSH, session);
                    _inputNode = HEU_InputNode.CreateSetupInput(GeoID, 0, partName, HEU_InputNode.InputNodeType.NODE, ParentAsset);
                    if (_inputNode != null)
                    {
                        ParentAsset.AddInputNode(_inputNode);
                    }
                }

                if (HEU_HAPIUtility.IsSupportedPolygonType(partInfo.type) && partInfo.vertexCount == 0)
                {
                    // No geometry for input asset

                    if (partData != null)
                    {
                        // Clean up existing part
                        HEU_PartData.DestroyPart(partData);
                        partData = null;
                    }

                    // No need to process further since we don't have geometry
                    return;
                }
            }
            else
            {
                // 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)
                {
                    HAPI_AttributeInfo instanceAttrInfo = new HAPI_AttributeInfo();
                    HEU_GeneralUtility.GetAttributeInfo(session, GeoID, partID, HEU_PluginSettings.UnityInstanceAttr, ref instanceAttrInfo);
                    if (instanceAttrInfo.exists && instanceAttrInfo.count > 0)
                    {
                        isAttribInstancer = true;
                    }
                }
            }

            if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_INVALID)
            {
                // Clean up invalid parts
                if (partData != null)
                {
                    HEU_PartData.DestroyPart(partData);
                    partData = null;
                }
            }
            else if (partInfo.type < HAPI_PartType.HAPI_PARTTYPE_MAX)
            {
                // Process the part based on type. Keep or ignore.

                // We treat parts of type curve as curves, along with geo nodes that are editable and type curves
                if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_CURVE)
                {
                    if (partData == null)
                    {
                        partData = ScriptableObject.CreateInstance <HEU_PartData>();
                    }

                    partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo,
                                        HEU_PartData.PartOutputType.CURVE, isPartEditable, _containerObjectNode.IsInstancer(), false);
                    SetupGameObjectAndTransform(partData, parentAsset);
                    partData.ProcessCurvePart(session);
                }
                else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_VOLUME)
                {
                    // We only process "height" volume parts. Other volume parts are ignored for now.

#if TERRAIN_SUPPORTED
                    HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo();
                    bResult = session.GetVolumeInfo(GeoID, partID, ref volumeInfo);
                    if (!bResult)
                    {
                        Debug.LogErrorFormat("Unable to get volume info for geo node {0} and part {1} ", GeoID, partID);
                    }
                    else
                    {
                        if (Displayable && !IsIntermediateOrEditable())
                        {
                            if (partData == null)
                            {
                                partData = ScriptableObject.CreateInstance <HEU_PartData>();
                            }
                            else
                            {
                                // Clear volume data (case where switching from polygonal mesh to volume output)
                                partData.ClearGeneratedMeshOutput();
                            }

                            partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo,
                                                HEU_PartData.PartOutputType.VOLUME, isPartEditable, _containerObjectNode.IsInstancer(), false);
                            SetupGameObjectAndTransform(partData, ParentAsset);
                        }
                    }
#else
                    Debug.LogWarningFormat("Terrain (heightfield volume) is not yet supported.");
#endif
                }
                else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_INSTANCER || isAttribInstancer)
                {
                    if (partData == null)
                    {
                        partData = ScriptableObject.CreateInstance <HEU_PartData>();
                    }
                    else
                    {
                        partData.ClearGeneratedMeshOutput();
                        partData.ClearGeneratedVolumeOutput();
                    }

                    partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo,
                                        HEU_PartData.PartOutputType.INSTANCER, isPartEditable, _containerObjectNode.IsInstancer(), isAttribInstancer);
                    SetupGameObjectAndTransform(partData, parentAsset);
                }
                else if (HEU_HAPIUtility.IsSupportedPolygonType(partInfo.type))
                {
                    if (partData == null)
                    {
                        partData = ScriptableObject.CreateInstance <HEU_PartData>();
                    }
                    else
                    {
                        // Clear volume data (case where switching from something other output to mesh)
                        partData.ClearGeneratedVolumeOutput();
                    }

                    partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo,
                                        HEU_PartData.PartOutputType.MESH, isPartEditable, _containerObjectNode.IsInstancer(), false);

                    // This check allows to ignore editable non-display nodes by default, but commented out to allow
                    // them for now. Users can also ignore them by turning on IgnoreNonDisplayNodes
                    //if (Displayable || (Editable && ParentAsset.EditableNodesToolsEnabled))
                    {
                        SetupGameObjectAndTransform(partData, parentAsset);
                    }
                }
                else
                {
                    Debug.LogWarningFormat("Unsupported part type {0}", partInfo.type);
                }

                if (partData != null)
                {
                    // Success!
                    _parts.Add(partData);

                    // Set unique name for the part
                    string partName = HEU_PluginSettings.UseFullPathNamesForOutput ? GeneratePartFullName(partData.PartName) : partData.PartName;
                    partData.SetGameObjectName(partName);

                    // For intermediate or default-type editable nodes, setup the HEU_AttributeStore
                    if (isPartEditable)
                    {
                        partData.SyncAttributesStore(session, _geoInfo.nodeId, ref partInfo);
                    }
                    else
                    {
                        // Remove attributes store if it has it
                        partData.DestroyAttributesStore();
                    }
                }
            }

#if HEU_PROFILER_ON
            Debug.LogFormat("PART PROCESS TIME:: NAME={0}, TIME={1}", HEU_SessionManager.GetString(partInfo.nameSH, session), (Time.realtimeSinceStartup - processPartStartTime));
#endif
        }
コード例 #13
0
        public void UpdateGeo(HEU_SessionBase session)
        {
            // Create or recreate parts.

            bool bObjectInstancer = _containerObjectNode.IsInstancer();

            // Save list of old parts. We'll destroy these after creating new parts.
            // The reason for temporarily keeping these is to transfer data (eg. instance overrides, attribute data)
            List <HEU_PartData> oldParts = new List <HEU_PartData>(_parts);

            _parts.Clear();

            try
            {
                if (!_geoInfo.isDisplayGeo)
                {
                    if (ParentAsset.IgnoreNonDisplayNodes)
                    {
                        return;
                    }
                    else if (!_geoInfo.isEditable ||
                             (_geoInfo.type != HAPI_GeoType.HAPI_GEOTYPE_DEFAULT &&
                              _geoInfo.type != HAPI_GeoType.HAPI_GEOTYPE_INTERMEDIATE &&
                              _geoInfo.type != HAPI_GeoType.HAPI_GEOTYPE_CURVE))
                    {
                        return;
                    }
                }

                if (IsGeoCurveType())
                {
                    ProcessGeoCurve(session);
                }
                else
                {
                    int numParts = _geoInfo.partCount;
                    //Debug.Log("Number of parts: " + numParts);
                    //Debug.LogFormat("GeoNode type {0}, isTemplated: {1}, isDisplayGeo: {2}, isEditable: {3}", _geoInfo.type, _geoInfo.isTemplated, _geoInfo.isDisplayGeo, _geoInfo.isEditable);
                    for (int i = 0; i < numParts; ++i)
                    {
                        HAPI_PartInfo partInfo = new HAPI_PartInfo();
                        if (!session.GetPartInfo(GeoID, i, ref partInfo))
                        {
                            Debug.LogErrorFormat("Unable to get PartInfo for geo node {0} and part {1}.", GeoID, i);
                            continue;
                        }

                        // Find the old part for this new part.
                        HEU_PartData part           = null;
                        HEU_PartData oldMatchedPart = null;

                        foreach (HEU_PartData oldPart in oldParts)
                        {
                            string partName = HEU_SessionManager.GetString(partInfo.nameSH, session);
                            if (oldPart.PartName.Equals(partName))
                            {
                                oldMatchedPart = oldPart;
                            }
                        }

                        if (oldMatchedPart != null)
                        {
                            //Debug.Log("Found matched part: " + oldMatchedPart.name);

                            List <HEU_ObjectInstanceInfo> sourceObjectInstanceInfos = null;
                            if (bObjectInstancer)
                            {
                                // ProcessPart will clear out the object instances, so hence why
                                // we keep a copy here, then restore after processing the parts.
                                sourceObjectInstanceInfos = oldMatchedPart.GetObjectInstanceInfos();
                            }

                            // Clear out old generated data
                            oldMatchedPart.ClearGeneratedData();

                            part = oldMatchedPart;
                            oldParts.Remove(oldMatchedPart);

                            ProcessPart(session, i, ref partInfo, ref part);

                            if (part != null && bObjectInstancer && sourceObjectInstanceInfos != null)
                            {
                                // Set object instances from old part into new. This keeps the user set object inputs around.
                                part.SetObjectInstanceInfos(sourceObjectInstanceInfos);
                            }
                        }
                        else
                        {
                            ProcessPart(session, i, ref partInfo, ref part);
                        }
                    }
                }
            }
            finally
            {
                HEU_PartData.DestroyParts(oldParts);
            }
        }
コード例 #14
0
 public void RemoveAndDestroyPart(HEU_PartData part)
 {
     _parts.Remove(part);
     HEU_PartData.DestroyPart(part);
 }
コード例 #15
0
		public void UpdateLayerFromPart(HEU_SessionBase session, HEU_PartData part)
		{
			HEU_GeoNode geoNode = part.ParentGeoNode;

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

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

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

			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);
				}
			}
		}
コード例 #16
0
		public void UpdateLayerFromPart(HEU_SessionBase session, HEU_PartData part)
		{
			HEU_GeoNode geoNode = part.ParentGeoNode;

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

			if (!_updatedLayers.Contains(layer))
			{
				if (layerType == HEU_VolumeLayer.HFLayerType.HEIGHT)
				{
					_updatedLayers.Insert(0, layer);
				}
				else if (layerType != HEU_VolumeLayer.HFLayerType.MASK)
				{
					_updatedLayers.Add(layer);
				}
			}
		}
コード例 #17
0
ファイル: HEU_VolumeCache.cs プロジェクト: Raikuns/VR-Dining
		public void GenerateTerrainFromParts(HEU_SessionBase session, List<HEU_PartData> volumeParts, HEU_HoudiniAsset houdiniAsset, out HEU_PartData heightLayerPart)
		{
			_heightMapVolumeData = null;
			_textureVolumeDatas = new List<HEU_VolumeData>();

			ParseVolumeDatas(session, volumeParts);

			TerrainData terrainData = null;
			Vector3 terrainOffsetPosition = Vector3.zero;
			Generate(session, houdiniAsset, out terrainData, out terrainOffsetPosition);

			if(_heightMapVolumeData != null && _heightMapVolumeData._partData != null && terrainData != null)
			{
				UnityEngine.Object terrainDataObject = null;
				houdiniAsset.AddToAssetDBCache(string.Format("Asset_{0}_TerrainData", _heightMapVolumeData._partData.ParentGeoNode.GeoName), terrainData, ref terrainDataObject);

				_heightMapVolumeData._partData.SetTerrainPart(terrainDataObject, terrainOffsetPosition);

				heightLayerPart = _heightMapVolumeData._partData;
			}
			else
			{
				heightLayerPart = null;
			}
		}
コード例 #18
0
	public void UpdateLayerFromPart(HEU_SessionBase session, HEU_PartData part)
	{
	    HEU_GeoNode geoNode = part.ParentGeoNode;

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

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

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

	    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);
		}
	    }
	}
コード例 #19
0
	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);
		}
	    }
	}
コード例 #20
0
        /// <summary>
        /// Process the part at the given index, creating its data (geometry),
        /// and adding it to the list of parts.
        /// </summary>
        /// <param name="session"></param>
        /// <param name="partID"></param>
        /// <returns>A valid HEU_PartData if it has been successfully processed.</returns>
        private void ProcessPart(HEU_SessionBase session, int partID, ref HAPI_PartInfo partInfo, ref HEU_PartData partData)
        {
            HEU_HoudiniAsset parentAsset = ParentAsset;
            bool             bResult     = true;

            //Debug.LogFormat("Part: name={0}, id={1}, type={2}, instanced={3}, instance count={4}, instance part count={5}", HEU_SessionManager.GetString(partInfo.nameSH, session), partID, partInfo.type, partInfo.isInstanced, partInfo.instanceCount, partInfo.instancedPartCount);

#if HEU_PROFILER_ON
            float processPartStartTime = Time.realtimeSinceStartup;
#endif

            bool isPartEditable = IsIntermediateOrEditable();

            if (IsGeoInputType())
            {
                // Setup for input node to accept inputs
                if (_inputNode == null)
                {
                    string partName = HEU_SessionManager.GetString(partInfo.nameSH, session);
                    _inputNode = HEU_InputNode.CreateSetupInput(GeoID, 0, partName, HEU_InputNode.InputNodeType.NODE, ParentAsset);
                    if (_inputNode != null)
                    {
                        ParentAsset.AddInputNode(_inputNode);
                    }
                }

                if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_MESH && partInfo.vertexCount == 0)
                {
                    // No geometry for input asset

                    if (partData != null)
                    {
                        // Clean up existing part
                        HEU_PartData.DestroyPart(partData);
                        partData = null;
                    }

                    // No need to process further since we don't have geometry
                    return;
                }
            }

            if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_INVALID)
            {
                // Clean up invalid parts
                if (partData != null)
                {
                    HEU_PartData.DestroyPart(partData);
                    partData = null;
                }
            }
            else if (partInfo.type < HAPI_PartType.HAPI_PARTTYPE_MAX)
            {
                // Process the part based on type. Keep or ignore.

                // We treat parts of type curve as curves, along with geo nodes that are editable and type curves
                if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_CURVE)
                {
                    if (partData == null)
                    {
                        partData = ScriptableObject.CreateInstance <HEU_PartData>();
                    }

                    partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo, HEU_PartData.PartOutputType.CURVE, isPartEditable);
                    SetupGameObjectAndTransform(partData, parentAsset);
                    partData.ProcessCurvePart(session);
                }
                else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_VOLUME)
                {
                    // We only process "height" volume parts. Other volume parts are ignored for now.

#if TERRAIN_SUPPORTED
                    HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo();
                    bResult = session.GetVolumeInfo(GeoID, partID, ref volumeInfo);
                    if (!bResult)
                    {
                        Debug.LogErrorFormat("Unable to get volume info for geo node {0} and part {1} ", GeoID, partID);
                    }
                    else
                    {
                        if (Displayable && !IsIntermediateOrEditable())
                        {
                            if (partData == null)
                            {
                                partData = ScriptableObject.CreateInstance <HEU_PartData>();
                            }

                            partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo, HEU_PartData.PartOutputType.VOLUME, isPartEditable);
                            SetupGameObjectAndTransform(partData, ParentAsset);
                        }
                    }
#else
                    Debug.LogWarningFormat("Terrain (heightfield volume) is not yet supported.");
#endif
                }
                else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_MESH)
                {
                    if (partData == null)
                    {
                        partData = ScriptableObject.CreateInstance <HEU_PartData>();
                    }

                    partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo, HEU_PartData.PartOutputType.MESH, isPartEditable);
                    SetupGameObjectAndTransform(partData, parentAsset);
                }
                else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_INSTANCER)
                {
                    if (partData == null)
                    {
                        partData = ScriptableObject.CreateInstance <HEU_PartData>();
                    }

                    partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo, HEU_PartData.PartOutputType.INSTANCER, isPartEditable);
                    SetupGameObjectAndTransform(partData, parentAsset);
                }
                else
                {
                    Debug.LogWarningFormat("Unsupported part type {0}", partInfo.type);
                }

                if (partData != null)
                {
                    // Success!
                    _parts.Add(partData);

                    // Set unique name for the part
                    string partFullName = GeneratePartFullName(partData.PartName);
                    partFullName = HEU_EditorUtility.GetUniqueNameForSibling(ParentAsset.RootGameObject.transform, partFullName);
                    partData.SetGameObjectName(partFullName);

                    // For intermediate or default-type editable nodes, setup the HEU_AttributeStore
                    if (isPartEditable)
                    {
                        partData.SyncAttributesStore(session, _geoInfo.nodeId, ref partInfo);
                    }
                    else
                    {
                        // Remove attributes store if it has it
                        partData.DestroyAttributesStore();
                    }

                    HEU_GeneralUtility.AssignUnityTag(session, GeoID, partData.PartID, partData._gameObject);
                    HEU_GeneralUtility.MakeStaticIfHasAttribute(session, GeoID, partData.PartID, partData._gameObject);
                }
            }

#if HEU_PROFILER_ON
            Debug.LogFormat("PART PROCESS TIME:: NAME={0}, TIME={1}", HEU_SessionManager.GetString(partInfo.nameSH, session), (Time.realtimeSinceStartup - processPartStartTime));
#endif
        }