public void SetupMeshAndMaterials(HEU_HoudiniAsset asset, HAPI_PartType partType, GameObject outputGameObject) { _outputMesh = null; _outputGameObject = null; if (HEU_HAPIUtility.IsSupportedPolygonType(partType)) { // Get the generated mesh. If mesh is missing, nothing we can do. MeshFilter meshFilter = outputGameObject.GetComponent<MeshFilter>(); if (meshFilter != null && meshFilter.sharedMesh != null) { _outputMesh = meshFilter.sharedMesh; } else { // Without a valid mesh, we won't be able to paint so nothing else to do return; } _outputGameObject = outputGameObject; if (_localMaterial == null) { MeshRenderer meshRenderer = _outputGameObject.GetComponent<MeshRenderer>(); if(meshRenderer != null) { _localMaterial = HEU_MaterialFactory.GetNewMaterialWithShader(null, HEU_MaterialFactory.GetHoudiniShaderPath(HEU_Defines.DEFAULT_VERTEXCOLOR_SHADER), HEU_Defines.EDITABLE_MATERIAL, false); } } } }
/// <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 }
/// <summary> /// Returns the various geometry types (parts) from the given node. /// Only part instancers and point instancers (via attributes) are returned. /// </summary> private bool QueryParts(HAPI_NodeId nodeID, ref List<HAPI_PartInfo> meshParts, ref List<HAPI_PartInfo> volumeParts, ref List<HAPI_PartInfo> instancerParts, ref List<HAPI_PartInfo> curveParts, ref List<HAPI_PartInfo> scatterInstancerParts) { // Get display geo info HAPI_GeoInfo geoInfo = new HAPI_GeoInfo(); if (!_session.GetGeoInfo(nodeID, ref geoInfo)) { return false; } //Debug.LogFormat("GeoNode name:{0}, type: {1}, isTemplated: {2}, isDisplayGeo: {3}, isEditable: {4}, parts: {5}", // HEU_SessionManager.GetString(geoInfo.nameSH, _session), // geoInfo.type, geoInfo.isTemplated, // geoInfo.isDisplayGeo, geoInfo.isEditable, geoInfo.partCount); if (geoInfo.type == HAPI_GeoType.HAPI_GEOTYPE_DEFAULT) { int numParts = geoInfo.partCount; for(int i = 0; i < numParts; ++i) { HAPI_PartInfo partInfo = new HAPI_PartInfo(); if (!_session.GetPartInfo(geoInfo.nodeId, i, ref partInfo)) { return false; } bool isAttribInstancer = false; bool isScatterInstancer = false; // Preliminary check for attribute instancing (mesh type with no verts but has points with instances) if (HEU_HAPIUtility.IsSupportedPolygonType(partInfo.type) && partInfo.vertexCount == 0 && partInfo.pointCount > 0) { if (HEU_GeneralUtility.HasValidInstanceAttribute(_session, nodeID, partInfo.id, HEU_PluginSettings.UnityInstanceAttr)) { isAttribInstancer = true; } else if (HEU_GeneralUtility.HasValidInstanceAttribute(_session, nodeID, partInfo.id, HEU_Defines.HEIGHTFIELD_TREEINSTANCE_PROTOTYPEINDEX)) { isScatterInstancer = true; } } if (isScatterInstancer) { scatterInstancerParts.Add(partInfo); } else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_VOLUME) { volumeParts.Add(partInfo); } else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_INSTANCER || isAttribInstancer) { instancerParts.Add(partInfo); } else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_CURVE) { curveParts.Add(partInfo); } else if(HEU_HAPIUtility.IsSupportedPolygonType(partInfo.type)) { meshParts.Add(partInfo); } else { string partName = HEU_SessionManager.GetString(partInfo.nameSH, _session); SetLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Part {0} with type {1} is not supported for GeoSync.", partName, partInfo.type)); } } } else if(geoInfo.type == HAPI_GeoType.HAPI_GEOTYPE_CURVE) { SetLog(HEU_LoadData.LoadStatus.ERROR, string.Format("Currently {0} geo type is not implemented for threaded geo loading!", geoInfo.type)); } return true; }
public void SetupMeshAndMaterials(HEU_HoudiniAsset asset, HAPI_PartType partType, GameObject outputGameObject) { Color[] oldColors = _outputMesh != null && _outputMesh.isReadable ? _outputMesh.colors : null; _outputMesh = null; _outputGameObject = null; if (HEU_HAPIUtility.IsSupportedPolygonType(partType)) { // Get the generated mesh. If mesh is missing, nothing we can do. MeshFilter meshFilter = outputGameObject.GetComponent<MeshFilter>(); if (meshFilter != null && meshFilter.sharedMesh != null) { _outputMesh = meshFilter.sharedMesh; if (_outputMesh.isReadable) { Color[] newColors = _outputMesh.colors; if (oldColors != null) { // Restore old colors back to newly generated mesh so // as to keep color "state" for visualization int oldLen = oldColors.Length; if (newColors == null || newColors.Length == 0) { newColors = new Color[_outputMesh.vertices.Length]; } int newLen = newColors.Length; for (int i = 0; i < newLen && i < oldLen; ++i) { newColors[i] = oldColors[i]; } _outputMesh.colors = newColors; _outputMesh.UploadMeshData(false); } else if (newColors == null || newColors.Length == 0) { // Assign new default colors int count = _outputMesh.vertices.Length; newColors = new Color[count]; for (int i = 0; i < count; ++i) { newColors[i] = new Color(0.3f, 0.06f, 0.62f); } _outputMesh.colors = newColors; _outputMesh.UploadMeshData(false); } } } else { // Without a valid mesh, we won't be able to paint so nothing else to do return; } _outputGameObject = outputGameObject; MeshRenderer meshRenderer = _outputGameObject.GetComponent<MeshRenderer>(); if (meshRenderer != null) { _outputMeshRendererInitiallyEnabled = meshRenderer.enabled; if (_localMaterial == null) { _localMaterial = HEU_MaterialFactory.GetNewMaterialWithShader(null, HEU_PluginSettings.DefaultVertexColorShader, HEU_Defines.EDITABLE_MATERIAL, false); } } } }