/// <summary>
        /// Creates an asset bundle from the assets located in the processed data directory.
        /// </summary>
        /// <returns></returns> Returns true if the asset bundle was created successfully, false otherwise.
        public bool CreateAssetBundleFromCreatedAssets()
        {
            // Delete previous asset bundle.
            GeneralToolkit.Delete(bundleDirectory);
            // Copy assets to the temporary directory.
            GeneralToolkit.Replace(PathType.Directory, processedDataDirectory, GeneralToolkit.tempDirectoryAbsolutePath);
            AssetDatabase.Refresh();
            // Get the assets' relative path locations.
            string[] assetFullPaths     = Directory.GetFiles(GeneralToolkit.tempDirectoryAbsolutePath);
            string[] assetRelativePaths = new string[assetFullPaths.Length];
            for (int i = 0; i < assetFullPaths.Length; i++)
            {
                assetRelativePaths[i] = GeneralToolkit.ToRelativePath(assetFullPaths[i]);
            }
            // Create an asset bundle from these assets.
            bool success = GeneralToolkit.CreateAssetBundle(bundleDirectory, bundleName, assetRelativePaths);

            // If successful, indicate to the processing information file that the asset bundle was created.
            if (success && File.Exists(processingInfoFilePath))
            {
                File.AppendAllLines(processingInfoFilePath, new string[] { processingInfoSuccessfulBundle });
            }
            // Delete the temporary directory.
            GeneralToolkit.Delete(GeneralToolkit.tempDirectoryAbsolutePath);
            // Refresh the database.
            AssetDatabase.Refresh();
            // Return whether the operation was successful.
            return(success);
        }
Beispiel #2
0
        /// <summary>
        /// Parses the camera setup from a directory containing an "images" folder with an image dataset from the Stanford Light Field Archive, and saves the parsed setup in this directory.
        /// </summary>
        public void ParseCameraSetup()
        {
            // Inform of process start.
            Debug.Log(GeneralToolkit.FormatScriptMessage(this.GetType(), "Started parsing camera setup for an image dataset from the Stanford Light Field Archive located at: " + dataHandler.colorDirectory + "."));
            // Get the files in the "images" folder.
            FileInfo[] fileInfos = GeneralToolkit.GetFilesByExtension(dataHandler.colorDirectory, ".png");
            // Determine the pixel resolution of the images.
            Texture2D tempTex = new Texture2D(1, 1);

            GeneralToolkit.LoadTexture(fileInfos[0].FullName, ref tempTex);
            Vector2Int pixelResolution = new Vector2Int(tempTex.width, tempTex.height);

            DestroyImmediate(tempTex);
            // Prepare repositioning around center if it is selected.
            Vector3 meanPos = Vector3.zero;

            // Reset the camera models to fit the color count.
            _cameraSetup.ResetCameraModels();
            _cameraSetup.cameraModels = new CameraModel[dataHandler.sourceColorCount];
            // Iteratively add each camera model to the setup.
            for (int iter = 0; iter < dataHandler.sourceColorCount; iter++)
            {
                CameraModel cameraModel = _cameraSetup.AddCameraModel(iter);
                // Store the image's pixel resolution in the camera model.
                cameraModel.pixelResolution = pixelResolution;
                // Store the image's name in the camera model.
                FileInfo fileInfo = fileInfos[iter];
                cameraModel.SetCameraReferenceIndexAndImageName(cameraModel.cameraReferenceIndex, fileInfo.Name);
                // Store the image's position in the model.
                string[] split     = fileInfo.Name.Split('_');
                float    positionY = -GeneralToolkit.ParseFloat(split[split.Length - 3]);
                float    positionX = GeneralToolkit.ParseFloat(split[split.Length - 2]);
                Vector3  pos       = scaleFactor * new Vector3(positionX, positionY, 0);
                cameraModel.transform.position = pos;
                meanPos += pos;
            }
            // If it is selected, reposition the camera setup around its center position.
            if (repositionAroundCenter)
            {
                meanPos /= dataHandler.sourceColorCount;
                for (int iter = 0; iter < dataHandler.sourceColorCount; iter++)
                {
                    CameraModel cameraModel = _cameraSetup.cameraModels[iter];
                    cameraModel.transform.position = cameraModel.transform.position - meanPos;
                }
            }
            // Temporarily move the color images to a safe location.
            string tempDirectoryPath = Path.Combine(GeneralToolkit.GetDirectoryBefore(dataHandler.dataDirectory), "temp");

            GeneralToolkit.Move(PathType.Directory, dataHandler.colorDirectory, tempDirectoryPath);
            // Save the camera setup information (this would also have cleared the "images" folder if it was still there).
            Acquisition.Acquisition.SaveAcquisitionInformation(dataHandler, cameraSetup);
            // Move the color images back into their original location.
            GeneralToolkit.Delete(dataHandler.colorDirectory);
            GeneralToolkit.Move(PathType.Directory, tempDirectoryPath, dataHandler.colorDirectory);
            // Update the camera models of the setup object.
            _cameraSetup.FindCameraModels();
            // Inform of end of process.
            Debug.Log(GeneralToolkit.FormatScriptMessage(this.GetType(), "Finished parsing camera setup. Result can be previewed in the Scene view."));
        }
 /// <summary>
 /// On destroy, destroys the potentially copied mesh in the Resources folder.
 /// </summary>
 public virtual void OnDestroy()
 {
     if (_loadedMeshFullPath != null)
     {
         bool isInResources = _loadedMeshFullPath.Contains(COLIBRIVRSettings.settingsResourcesAbsolutePath);
         if (isInResources && EditorApplication.isPlaying && GeneralToolkit.IsStartingNewScene())
         {
             GeneralToolkit.Delete(_loadedMeshFullPath);
             AssetDatabase.Refresh();
         }
     }
 }
        /// <summary>
        /// Coroutine that saves the specified global mesh asset into the asset bundle.
        /// </summary>
        /// <returns></returns>
        private IEnumerator SaveGlobalMeshAsAssetCoroutine()
        {
            // Set the destination paths to a temporary asset folder.
            string bundledAssetName  = GetBundledAssetName(globalMeshAssetName);
            string assetPathAbsolute = GetAssetPathAbsolute(bundledAssetName);
            string assetPathRelative = GetAssetPathRelative(bundledAssetName);

            // Check if the asset has already been processed.
            if (!dataHandler.IsAssetAlreadyProcessed(assetPathRelative))
            {
                // If the mesh to store is already an asset, move it to the asset bundle path.
                string dstExtension = Path.GetExtension(_globalMeshPathAbsolute);
                if (dstExtension == ".asset")
                {
                    // Copy the asset to the destination path.
                    GeneralToolkit.Replace(PathType.File, _globalMeshPathAbsolute, assetPathAbsolute);
                    // Refresh the asset database.
                    AssetDatabase.Refresh();
                }
                // Otherwise, the mesh first has to be converted into an asset.
                else
                {
                    // Copy the mesh to the resources folder.
                    string dstName     = "COLIBRITempResource";
                    string dstFullPath = Path.Combine(COLIBRIVRSettings.settingsResourcesAbsolutePath, dstName + dstExtension);
                    GeneralToolkit.Replace(PathType.File, _globalMeshPathAbsolute, dstFullPath);
                    // Refresh the asset database.
                    AssetDatabase.Refresh();
                    yield return(null);

                    // Make the mesh readable so that colliders can be added.
                    ModelImporter modelImporter = ModelImporter.GetAtPath(GeneralToolkit.ToRelativePath(dstFullPath)) as ModelImporter;
                    modelImporter.isReadable = true;
                    modelImporter.SaveAndReimport();
                    // Load the mesh from resources.
                    Mesh loadedMesh = Resources.Load <Mesh>(dstName);
                    // Copy the mesh by instantiating it.
                    globalMesh = (Mesh)Instantiate(loadedMesh);
                    // Recalculate the mesh's normals and bounds.
                    globalMesh.RecalculateNormals();
                    globalMesh.RecalculateBounds();
                    // Create an asset from the copied mesh.
                    AssetDatabase.CreateAsset(globalMesh, assetPathRelative);
                    AssetDatabase.Refresh();
                    // Delete the mesh that was copied into the resources folder.
                    GeneralToolkit.Delete(dstFullPath);
                }
            }
            Mesh meshAsset = AssetDatabase.LoadAssetAtPath <Mesh>(assetPathRelative);

            globalMesh = (Mesh)Instantiate(meshAsset);
        }
 /// <summary>
 /// On enable, changes the workspace if entering edit mode after having performed reconstruction in play mode.
 /// </summary>
 void OnEnable()
 {
     if (!EditorApplication.isPlaying && GeneralToolkit.IsStartingNewScene())
     {
         string indicatorPathAbsolute = Path.Combine(Application.dataPath, _updateDirectoryIndicatorPathEnd);
         if (File.Exists(indicatorPathAbsolute))
         {
             ChangeWorkspaceAfterSparseReconstruction();
             GeneralToolkit.Delete(indicatorPathAbsolute);
             AssetDatabase.Refresh();
         }
     }
 }
        /// <summary>
        /// Saves the meshes in the scene as a global mesh asset in the data directory.
        /// </summary>
        public void SaveGlobalMesh()
        {
            // Combines the different meshes in the scene into a single asset.
            Mesh outputMesh = new Mesh();

            MeshFilter[]      meshFilters = FindObjectsOfType <MeshFilter>();
            CombineInstance[] combine     = new CombineInstance[meshFilters.Length];
            for (int i = 0; i < meshFilters.Length; i++)
            {
                combine[i].mesh      = meshFilters[i].sharedMesh;
                combine[i].transform = meshFilters[i].transform.localToWorldMatrix;
            }
            outputMesh.CombineMeshes(combine, false);
            // Saves the asset in the data directory.
            string assetName          = "GlobalMesh.asset";
            string relativeAssetPath  = Path.Combine("Assets", assetName);
            string globalAssetPath    = Path.Combine(Path.GetFullPath(Application.dataPath), assetName);
            string newGlobalAssetPath = Path.Combine(dataHandler.dataDirectory, assetName);

            GeneralToolkit.CreateAndUnloadAsset(outputMesh, relativeAssetPath);
            GeneralToolkit.Replace(PathType.File, globalAssetPath, newGlobalAssetPath);
            GeneralToolkit.Delete(globalAssetPath);
            AssetDatabase.Refresh();
        }
        /// <summary>
        /// Coroutine that runs the sparse reconstruction process.
        /// </summary>
        /// <param name="caller"></param> The processing object calling this method.
        /// <param name="workspace"></param> The workspace from which to perform this method.
        /// <param name="COLMAPCameraIndex"></param> The index of the type of source camera (in the list of COLMAP cameras).
        /// <param name="isSingleCamera"></param> True if the source images were acquired by the same camera, false otherwise.
        /// <param name="maxImageSize"></param> The maximum image size for the undistortion step.
        /// <returns></returns>
        public static IEnumerator RunSparseReconstructionCoroutine(Processing.Processing caller, string workspace, int COLMAPCameraIndex, bool isSingleCamera, int maxImageSize)
        {
            // Indicate to the user that the process has started.
            GeneralToolkit.ResetCancelableProgressBar(true, true);
            // Create or clear the folders needed for the reconstruction.
            GeneralToolkit.Delete(GetDatabaseFile(workspace));
            GeneralToolkit.CreateOrClear(PathType.Directory, GetSparseDir(workspace));
            GeneralToolkit.CreateOrClear(PathType.Directory, GetSparse0Dir(workspace));
            GeneralToolkit.CreateOrClear(PathType.Directory, GetDenseDir(workspace));
            GeneralToolkit.CreateOrClear(PathType.Directory, GetDense0Dir(workspace));
            // Initialize the command parameters.
            bool displayProgressBar = true;
            bool stopOnError        = true;

            string[] progressBarParams = new string[3];
            int      maxStep           = 6;

            progressBarParams[0] = GeneralToolkit.ToString(maxStep);
            progressBarParams[2] = "Processing canceled by user.";
            // Launch the different steps of the sparse reconstruction process.
            float focalLengthFactor = 0;

            for (int step = 1; step <= maxStep; step++)
            {
                // Step one: launch feature extraction.
                if (step == 1)
                {
                    progressBarParams[1] = GetProgressBarParamsOne("Feature extraction", true, step, maxStep);
                    CameraModel[] cameraModels = caller.cameraSetup.cameraModels;
                    if (cameraModels != null && cameraModels.Length > 0)
                    {
                        CameraModel cameraParams = cameraModels[0];
                        float       focalLength  = Camera.FieldOfViewToFocalLength(cameraParams.fieldOfView.x, cameraParams.pixelResolution.x);
                        focalLengthFactor = focalLength / Mathf.Max(cameraParams.pixelResolution.x, cameraParams.pixelResolution.y);
                    }
                    yield return(caller.StartCoroutine(RunFeatureExtractionCommand(caller, workspace, displayProgressBar, stopOnError, progressBarParams, COLMAPCameraIndex, isSingleCamera, focalLengthFactor)));
                }
                // Step two: launch feature matching.
                else if (step == 2)
                {
                    progressBarParams[1] = GetProgressBarParamsOne("Feature matching", true, step, maxStep);
                    yield return(caller.StartCoroutine(RunFeatureMatchingCommand(caller, workspace, displayProgressBar, stopOnError, progressBarParams)));
                }
                // Step three: launch mapping.
                else if (step == 3)
                {
                    progressBarParams[1] = GetProgressBarParamsOne("Mapping", true, step, maxStep);
                    yield return(caller.StartCoroutine(RunMappingCommand(caller, workspace, displayProgressBar, stopOnError, progressBarParams, (focalLengthFactor > 0))));
                }
                // Step four: launch exporting original camera setup as text.
                else if (step == 4)
                {
                    progressBarParams[1] = GetProgressBarParamsOne("Exporting camera setup (original) as text", true, step, maxStep);
                    yield return(caller.StartCoroutine(RunExportModelAsTextCommand(caller, workspace, displayProgressBar, stopOnError, progressBarParams)));
                }
                // Step five: launch image undistortion.
                else if (step == 5)
                {
                    // Launch undistortion.
                    progressBarParams[1] = GetProgressBarParamsOne("Undistortion", true, step, maxStep);
                    yield return(caller.StartCoroutine(RunUndistortionCommand(caller, workspace, displayProgressBar, stopOnError, progressBarParams, maxImageSize)));
                    // Change the workspace and the data directory to the one created in the dense folder.
                    // workspace = GetDense0Dir(workspace);
                    // caller.dataHandler.ChangeDataDirectory(caller, workspace);
                    // Debug.Log(GeneralToolkit.FormatScriptMessage(typeof(COLMAPConnector), "Changed data directory to: " + workspace));
                }
                // Step six: launch exporting undistorted camera setup as text.
                else if (step == 6)
                {
                    // Launch export process.
                    progressBarParams[1] = GetProgressBarParamsOne("Exporting camera setup (undistorted) as text", true, step, maxStep);
                    yield return(caller.StartCoroutine(RunExportModelAsTextCommand(caller, GetDense0Dir(workspace), displayProgressBar, stopOnError, progressBarParams)));

                    // Display the parsed camera setup in the Scene view.
                    caller.Deselected();
                    caller.Selected();
                    yield return(null);
                }
                // For each step, continue only if the user does not cancel the process.
                if (GeneralToolkit.progressBarCanceled)
                {
                    break;
                }
            }
            // Change the data directory to the one created in the dense folder.
            if (!GeneralToolkit.progressBarCanceled)
            {
                Debug.Log(GeneralToolkit.FormatScriptMessage(typeof(COLMAPConnector), "Sparse reconstruction was a success."));
            }
            // Indicate to the user that the process has ended.
            GeneralToolkit.ResetCancelableProgressBar(false, false);
        }