Ejemplo n.º 1
0
        /// <summary>
        /// Coroutine that performs automatic retopology on a given mesh using the Instant Meshes implementation.
        /// </summary>
        /// <param name="caller"></param> The object calling this method.
        /// <param name="workspace"></param> The workspace from which to launch the command.
        /// <param name="inputFilePath"></param> The full path to the input .PLY or .OBJ file.
        /// <param name="outputFilePath"></param> The full path to the output .PLY or .OBJ file.
        /// <param name="blenderHelper"></param> The helper component for Blender.
        /// <returns></returns>
        public static IEnumerator RunInstantMeshesCoroutine(MonoBehaviour caller, string workspace, string inputFilePath, string outputFilePath, BlenderHelper blenderHelper)
        {
            // Indicate to the user that the process has started.
            GeneralToolkit.ResetCancelableProgressBar(true, true);
            // Initialize the command parameters.
            bool displayProgressBar = true;
            bool stopOnError        = true;

            string[] progressBarParams = new string[3];
            progressBarParams[0] = "2";
            progressBarParams[1] = "Automatic retopology";
            progressBarParams[2] = "Processing canceled by user.";
            // Prepare the command.
            string formattedExePath = InstantMeshesSettings.formattedInstantMeshesExePath;
            string command          = "CALL " + formattedExePath;

            command += " --output " + GeneralToolkit.FormatPathForCommand(outputFilePath);
            command += " --deterministic --boundaries --rosy 6 --posy 6";
            // If there is a Blender helper, use the determined mesh face count to define the desired face count.
            if (blenderHelper != null && blenderHelper.meshFaceCount != -1)
            {
                command += " --faces " + GeneralToolkit.ToString(blenderHelper.meshFaceCount);
            }
            // Launch the command.
            command += " " + GeneralToolkit.FormatPathForCommand(inputFilePath);
            yield return(caller.StartCoroutine(GeneralToolkit.RunCommandCoroutine(typeof(InstantMeshesConnector), command, workspace, displayProgressBar, null, null, stopOnError, progressBarParams)));

            // If there is a Blender helper, update the mesh's face count.
            if (blenderHelper != null)
            {
                blenderHelper.CheckOBJMeshInfo(workspace);
            }
            // Indicate to the user that the process has ended.
            GeneralToolkit.ResetCancelableProgressBar(false, false);
        }
Ejemplo n.º 2
0
        /// <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();
        }
Ejemplo n.º 3
0
        /// <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>
        /// Formats a command for Blender python from the given arguments.
        /// </summary>
        /// <param name="fileName"></param> The name of the python file to call.
        /// <param name="args"></param> The arguments to provide for the python file.
        /// <returns></returns> The formatted command.
        private static string FormatBlenderCommand(string fileName, params string[] args)
        {
            string formattedExePath    = BlenderSettings.formattedBlenderExePath;
            string formattedFileName   = GeneralToolkit.FormatPathForCommand(fileName);
            string formattedScriptsDir = GeneralToolkit.FormatPathForCommand(_externalPythonScriptsDir);
            string commandArgs         = string.Empty;

            foreach (string arg in args)
            {
                commandArgs += GeneralToolkit.FormatPathForCommand(arg) + " ";
            }
            string command = "CALL " + formattedExePath + " --factory-startup --background --python " + formattedFileName + " -- " + formattedScriptsDir + " " + commandArgs;

            return(command);
        }
        /// <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();
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Coroutine that performs automatic retopology on a given mesh using the Instant Meshes implementation.
        /// </summary>
        /// <param name="caller"></param> The Instant Meshes helper calling this method.
        /// <param name="workspace"></param> The workspace from which to launch the command.
        /// <param name="inputFilePath"></param> The full path to the input .PLY or .OBJ file.
        /// <param name="outputFilePath"></param> The full path to the output .PLY or .OBJ file.
        /// <param name="reduceVertexCount"></param> Whether to reduce the vertex count to the recommended value.
        /// <returns></returns>
        public static IEnumerator RunInstantMeshesCoroutine(InstantMeshesHelper caller, string workspace, string inputFilePath, string outputFilePath, bool reduceVertexCount)
        {
            // Indicate to the user that the process has started.
            GeneralToolkit.ResetCancelableProgressBar(true, true);
            // If the initial face count is needed, display the input mesh to get it.
            if (!reduceVertexCount)
            {
                caller.DisplayMeshInSceneView(inputFilePath);
            }
            // Initialize the command parameters.
            bool displayProgressBar = true;
            bool stopOnError        = true;

            string[] progressBarParams = new string[3];
            progressBarParams[0] = "2";
            progressBarParams[1] = "Automatic retopology";
            progressBarParams[2] = "Processing canceled by user.";
            // Prepare the command.
            string formattedExePath = InstantMeshesSettings.formattedInstantMeshesExePath;
            string command          = "CALL " + formattedExePath;

            command += " --output " + GeneralToolkit.FormatPathForCommand(outputFilePath);
            command += " --deterministic --boundaries --rosy 6 --posy 6";
            // If desired, use the determined mesh face count to define the desired face count.
            if (!reduceVertexCount)
            {
                command += " --faces " + GeneralToolkit.ToString(caller.loadedMeshFaceCount);
            }
            // Launch the command.
            command += " " + GeneralToolkit.FormatPathForCommand(inputFilePath);
            yield return(caller.StartCoroutine(GeneralToolkit.RunCommandCoroutine(typeof(InstantMeshesConnector), command, workspace, displayProgressBar, null, null, stopOnError, progressBarParams)));

            // Display the transformed mesh in the Scene view.
            caller.DisplayMeshInSceneView(outputFilePath);
            // Indicate to the user that the process has ended.
            GeneralToolkit.ResetCancelableProgressBar(false, false);
        }
        /// <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();
        }