/// <summary> /// Enables the user to perform automatic retopology on the .OBJ mesh via Instant Meshes. /// </summary> /// <param name="serializedObject"></param> The serialized object to modify. public void SubsectionRunInstantMeshesOBJ(SerializedObject serializedObject) { EditorGUILayout.Space(); string workspace = dataHandler.dataDirectory; string inputFilePath = Path.Combine(workspace, BlenderConnector.convertPLYtoOBJOutputFileName); string outputFilePath = inputFilePath; string label = "Perform automatic retopology."; string tooltip = "This will re-mesh the .OBJ file at \"" + GeneralToolkit.FormatPathForCommand(inputFilePath) + "\"."; // Check if this option is available. bool isGUIEnabled = GUI.enabled; GUI.enabled = isGUIEnabled && File.Exists(inputFilePath) && Application.isPlaying; GeneralToolkit.EditorRequirePlayMode(ref tooltip);// Display a button to launch the helper method. bool hasPressed = GeneralToolkit.EditorWordWrapLeftButton(new GUIContent("Run", tooltip), new GUIContent(label, tooltip)); // If the button is pressed, launch the method. if (hasPressed) { StartCoroutine(InstantMeshesConnector.RunInstantMeshesCoroutine(this, workspace, inputFilePath, outputFilePath, _reduceVertexCountToRecommended)); } // Provide the option to reduce the face count to the value recommended by Instant Meshes, or to use the current vertex count. SerializedProperty propertyReduceVertexCountToRecommended = serializedObject.FindProperty(_propertyNameReduceVertexCountToRecommended); label = "Reduce vertex count:"; tooltip = "If true, reduces the vertex count to the value recommended by Instant Meshes. Otherwise, aims to keep the same vertex count."; tooltip += " For scenes in which the region of interest is small compared to the bounds of the mesh, it is recommended to turn this off."; propertyReduceVertexCountToRecommended.boolValue = EditorGUILayout.Toggle(new GUIContent(label, tooltip), propertyReduceVertexCountToRecommended.boolValue); // Reset the GUI. GUI.enabled = isGUIEnabled; EditorGUILayout.Space(); }
/// <summary> /// Enables the user to launch dense 3D reconstruction and meshing via COLMAP. /// </summary> /// <param name="workspace"></param> The workspace from which to perform this method. private void SubsectionDenseReconstruction() { EditorGUILayout.Space(); string workspace = dataHandler.dataDirectory; string label = "Reconstruct 3D mesh (.PLY) from sparse camera setup."; string tooltip = "Processed geometry will be stored at: \"" + COLMAPConnector.GetDelaunayFile(workspace) + "\"."; // Check if this option is available. bool isGUIEnabled = GUI.enabled; GUI.enabled = isGUIEnabled && (cameraSetup != null && cameraSetup.cameraModels != null) && workspace.Contains(COLMAPConnector.dense0DirName) && Application.isPlaying; GeneralToolkit.EditorRequirePlayMode(ref tooltip); // Display a button to launch the helper method. bool hasPressed = GeneralToolkit.EditorWordWrapLeftButton(new GUIContent("Run", tooltip), new GUIContent(label, tooltip)); // If the button is pressed, display a dialog to confirm. if (hasPressed) { label = "Existing data will be erased. Are you ready to proceed?"; tooltip = "Launching this process will erase data in the folder: \"" + workspace + "\". Are you ready to proceed?"; // If the user confirms, update the workspace directory and launch the method. if (EditorUtility.DisplayDialog(label, tooltip, "Yes", "No")) { StartCoroutine(COLMAPConnector.RunDenseReconstructionCoroutine(this, workspace)); } } // Reset the GUI. GUI.enabled = isGUIEnabled; EditorGUILayout.Space(); }
/// <summary> /// Enables the user to launch dense 3D reconstruction and meshing via COLMAP. /// </summary> /// <param name="workspace"></param> The workspace from which to perform this method. private void SubsectionDenseReconstruction() { EditorGUILayout.Space(); string workspace = dataHandler.dataDirectory; string label = "Reconstruct 3D mesh (.PLY) from sparse camera setup."; string tooltip = "Processed geometry will be stored at: \"" + COLMAPConnector.GetDelaunayFile(workspace) + "\"."; // Check if this option is available. bool isGUIEnabled = GUI.enabled; GUI.enabled = isGUIEnabled && (cameraSetup != null && cameraSetup.cameraModels != null && cameraSetup.cameraModels.Length > 0) && (dataHandler != null && dataHandler.imagePointCorrespondencesExist) && Application.isPlaying; GeneralToolkit.EditorRequirePlayMode(ref tooltip); // Display a button to launch the helper method. bool hasPressed = GeneralToolkit.EditorWordWrapLeftButton(new GUIContent("Run", tooltip), new GUIContent(label, tooltip)); // If the button is pressed, display a dialog to confirm. if (hasPressed) { label = "Existing data will be erased. Are you ready to proceed?"; tooltip = "WARNING: Before launching this step, please check that you are using a CUDA-capable GPU. Your current GPU is a " + SystemInfo.graphicsDeviceName + "."; tooltip += "\n\nLaunching this process will erase data in the folder: \"" + workspace + "\". Are you ready to proceed?"; // If the user confirms, update the workspace directory and launch the method. int chosenButton = EditorUtility.DisplayDialogComplex(label, tooltip, "Yes", "No", "Check whether my GPU is CUDA-capable"); if (chosenButton == 0) { StartCoroutine(COLMAPConnector.RunDenseReconstructionCoroutine(this, workspace, cameraSetup.cameraModels.Length)); } else if (chosenButton == 2) { Application.OpenURL("https://developer.nvidia.com/cuda-gpus"); } } // Reset the GUI. GUI.enabled = isGUIEnabled; EditorGUILayout.Space(); }
/// <summary> /// Enables the user to perform automatic retopology on the .OBJ mesh via Instant Meshes. /// </summary> /// <param name="serializedObject"></param> The serialized object to modify. public void SubsectionRunInstantMeshesOBJ(SerializedObject serializedObject) { EditorGUILayout.Space(); string workspace = dataHandler.dataDirectory; string inputFilePath = Path.Combine(workspace, BlenderConnector.convertPLYtoOBJOutputFileName); string outputFilePath = inputFilePath; string label = "Perform automatic retopology."; string tooltip = "This will re-mesh the .OBJ file at \"" + GeneralToolkit.FormatPathForCommand(inputFilePath) + "\"."; // Check if this option is available. bool isGUIEnabled = GUI.enabled; GUI.enabled = isGUIEnabled && File.Exists(inputFilePath) && Application.isPlaying; GeneralToolkit.EditorRequirePlayMode(ref tooltip); // Display a button to launch the helper method. bool hasPressed = GeneralToolkit.EditorWordWrapLeftButton(new GUIContent("Run", tooltip), new GUIContent(label, tooltip)); // If the button is pressed, launch the method. if (hasPressed) { BlenderHelper blenderHelper = GetComponent <BlenderHelper>(); StartCoroutine(InstantMeshesConnector.RunInstantMeshesCoroutine(this, workspace, inputFilePath, outputFilePath, blenderHelper)); } // Reset the GUI. GUI.enabled = isGUIEnabled; EditorGUILayout.Space(); }
/// <summary> /// Enables the user to launch sparse 3D reconstruction via COLMAP. /// </summary> /// <param name="serializedObject"></param> The serialized object to modify. private void SubsectionSparseReconstruction(SerializedObject serializedObject) { EditorGUILayout.Space(); string workspace = dataHandler.dataDirectory; string label = "Recover sparse camera setup from images."; string tooltip = "Images should be stored in the \"" + COLMAPConnector.GetImagesDir(workspace) + "\" folder.\n"; tooltip += "Camera setup information will be stored at: \"" + COLMAPConnector.GetCamerasFile(workspace) + "\"."; // Check if this option is available. bool isGUIEnabled = GUI.enabled; GUI.enabled = isGUIEnabled && (processingCaller.sourceColorCount > 1) && !(workspace.Contains(COLMAPConnector.dense0DirName)) && Application.isPlaying; GeneralToolkit.EditorRequirePlayMode(ref tooltip); // Display a button to launch the helper method. bool hasPressed = GeneralToolkit.EditorWordWrapLeftButton(new GUIContent("Run", tooltip), new GUIContent(label, tooltip)); // Display additional parameters. EditorGUILayout.Space(); if (GUI.enabled) { label = "Camera type"; tooltip = "COLMAP camera type of the camera(s) that acquired the source images."; SerializedProperty propertyCOLMAPCameraIndex = serializedObject.FindProperty(_propertyNameCOLMAPCameraIndex); propertyCOLMAPCameraIndex.intValue = EditorGUILayout.Popup(new GUIContent(label, tooltip), propertyCOLMAPCameraIndex.intValue, COLMAPConnector.COLMAPCameraTypes.ToArray()); label = "Is single camera"; tooltip = "This value should be set to true if the source images were acquired by the same camera, false otherwise."; SerializedProperty propertyIsSingleCamera = serializedObject.FindProperty(_propertyNameIsSingleCamera); propertyIsSingleCamera.boolValue = EditorGUILayout.Toggle(new GUIContent(label, tooltip), propertyIsSingleCamera.boolValue); label = "Max. image size: "; tooltip = "Maximum image size for the undistortion step. The resized images will be the ones used for rendering."; SerializedProperty propertyMaxImageSize = serializedObject.FindProperty(_propertyNameMaxImageSize); propertyMaxImageSize.intValue = EditorGUILayout.IntSlider(new GUIContent(label, tooltip), propertyMaxImageSize.intValue, 1, 8192); } // If the button is pressed, display a dialog to confirm. if (hasPressed) { label = "Existing data will be erased. Are you ready to proceed?"; tooltip = "Launching this process will erase data in the folder: \"" + workspace + "\". Are you ready to proceed?"; // If the user confirms, launch the method. if (EditorUtility.DisplayDialog(label, tooltip, "Yes", "No")) { StartCoroutine(COLMAPConnector.RunSparseReconstructionCoroutine(processingCaller, workspace, _COLMAPCameraIndex, _isSingleCamera, _maxImageSize)); } hasPerformedSparseReconstruction = true; ChangeWorkspaceAfterSparseReconstruction(); } // Reset the GUI. GUI.enabled = isGUIEnabled; EditorGUILayout.Space(); }
/// <summary> /// Enables the user to convert the .PLY mesh file to .OBJ via Blender. /// </summary> public void SubsectionConvertPLYtoOBJ() { EditorGUILayout.Space(); string inputFilePath = Path.Combine(_meshWorkspace, COLMAPConnector.delaunayFileName); string outputFilePath = Path.Combine(_meshWorkspace, BlenderConnector.convertPLYtoOBJOutputFileName); string label = "Convert .PLY mesh to .OBJ file."; string tooltip = "File " + GeneralToolkit.FormatPathForCommand(inputFilePath) + " will be converted to file " + GeneralToolkit.FormatPathForCommand(outputFilePath) + "."; // Check if this option is available. bool isGUIEnabled = GUI.enabled; GUI.enabled = isGUIEnabled && File.Exists(inputFilePath) && Application.isPlaying; GeneralToolkit.EditorRequirePlayMode(ref tooltip); // Display a button to launch the helper method. bool hasPressed = GeneralToolkit.EditorWordWrapLeftButton(new GUIContent("Run", tooltip), new GUIContent(label, tooltip)); if (hasPressed) { StartCoroutine(BlenderConnector.RunConvertPLYtoOBJCoroutine(processingCaller, inputFilePath, outputFilePath, ReadMeshFaceCount)); } // Reset the GUI. GUI.enabled = isGUIEnabled; EditorGUILayout.Space(); }
/// <summary> /// Enables the user to UV-map the given .OBJ mesh using Blender's Smart UV Project algorithm. /// </summary> public void SubsectionSmartUVProjectOBJ() { EditorGUILayout.Space(); string inputFilePath = Path.Combine(_meshWorkspace, BlenderConnector.convertPLYtoOBJOutputFileName); string outputFilePath = inputFilePath; string label = "UV-map .OBJ file."; string tooltip = "Mesh in file " + GeneralToolkit.FormatPathForCommand(inputFilePath) + " will be UV-mapped using Blender's Smart UV Project algorithm."; // Check if this option is available. bool isGUIEnabled = GUI.enabled; GUI.enabled = isGUIEnabled && File.Exists(inputFilePath) && Application.isPlaying; GeneralToolkit.EditorRequirePlayMode(ref tooltip); // Display a button to launch the helper method. bool hasPressed = GeneralToolkit.EditorWordWrapLeftButton(new GUIContent("Run", tooltip), new GUIContent(label, tooltip)); if (hasPressed) { StartCoroutine(BlenderConnector.RunSmartUVProjectOBJCoroutine(this, inputFilePath, outputFilePath)); } // Reset the GUI. GUI.enabled = isGUIEnabled; EditorGUILayout.Space(); }
/// <summary> /// Enables the user to check the mesh information contained in the .OBJ file via Blender. /// </summary> public void SubsectionCheckOBJMeshInfo() { EditorGUILayout.Space(); string inputFilePath = Path.Combine(_meshWorkspace, BlenderConnector.convertPLYtoOBJOutputFileName); string label = "Check .OBJ mesh information."; string tooltip = "File " + GeneralToolkit.FormatPathForCommand(inputFilePath) + " will be read from, to check its number of triangle faces."; // Check if this option is available. bool isGUIEnabled = GUI.enabled; GUI.enabled = isGUIEnabled && File.Exists(inputFilePath) && Application.isPlaying; GeneralToolkit.EditorRequirePlayMode(ref tooltip); // Display a button to launch the helper method. bool hasPressed = GeneralToolkit.EditorWordWrapLeftButton(new GUIContent("Run", tooltip), new GUIContent(label, tooltip)); if (hasPressed) { CheckOBJMeshInfo(_meshWorkspace); } // Display the current face count. GUIStyle grey = GeneralToolkit.wordWrapStyle; grey.normal.textColor = Color.grey; label = "Mesh face count: "; if (meshFaceCount == -1) { label += "not determined."; } else { label += GeneralToolkit.ToString(meshFaceCount) + "."; } tooltip = "Number of faces on the mesh."; EditorGUILayout.LabelField(new GUIContent(label, tooltip), grey); // Reset the GUI. GUI.enabled = isGUIEnabled; EditorGUILayout.Space(); }
/// <summary> /// Enables the user to simplify the .OBJ mesh via Blender. /// </summary> /// <param name="serializedObject"></param> The serialized object to modify. public void SubsectionSimplifyOBJ(SerializedObject serializedObject) { EditorGUILayout.Space(); string inputFilePath = Path.Combine(_meshWorkspace, BlenderConnector.convertPLYtoOBJOutputFileName); string outputFilePath = inputFilePath; string label = "Simplify .OBJ mesh."; string tooltip = "Mesh in file " + GeneralToolkit.FormatPathForCommand(inputFilePath) + " will be simplified, reducing its face count."; // Check if this option is available. bool isGUIEnabled = GUI.enabled; GUI.enabled = isGUIEnabled && File.Exists(inputFilePath) && Application.isPlaying; GeneralToolkit.EditorRequirePlayMode(ref tooltip); // Display a button to launch the helper method. bool hasPressed = GeneralToolkit.EditorWordWrapLeftButton(new GUIContent("Run", tooltip), new GUIContent(label, tooltip)); // If the button is pressed, launch the method. if (hasPressed) { StartCoroutine(BlenderConnector.RunSimplifyOBJCoroutine(this, inputFilePath, outputFilePath, ReadMeshFaceCount)); } // Reset the GUI. GUI.enabled = isGUIEnabled; EditorGUILayout.Space(); }