Example #1
0
        /// <summary>
        /// Computes camera poses on a grid.
        /// </summary>
        /// <param name="parentTransform"></param> The parent transform.
        /// <param name="cameraCount"></param> The number of cameras on each of the axes of the grid.
        public void ComputeGridPoses(Transform parentTransform, Vector2Int cameraCount)
        {
            // Compute several preliminary values.
            Vector2 numberOfIntervals = cameraCount - Vector2.one;
            Vector2 intervalSize      = new Vector2(parentTransform.lossyScale.x / Mathf.Max(1, numberOfIntervals.x), parentTransform.lossyScale.y / Mathf.Max(1, numberOfIntervals.y));

            // Update the camera model of all source cameras.
            for (int j = 0; j < cameraCount.y; j++)
            {
                for (int i = 0; i < cameraCount.x; i++)
                {
                    int         index       = j * cameraCount.x + i;
                    CameraModel cameraModel = cameraModels[index];
                    cameraModel.SetCameraReferenceIndexAndImageName(index, index.ToString("0000") + ".png");
                    Vector2 planePos = (new Vector2(i, j) - 0.5f * numberOfIntervals) * intervalSize;
                    cameraModel.transform.position = parentTransform.position + planePos.x * parentTransform.right + planePos.y * parentTransform.up;
                    cameraModel.transform.rotation = parentTransform.rotation;
                }
            }
            // Set the initial viewing position so that the viewer will initially look at the center of the grid.
            Vector2 absScale   = new Vector2(Mathf.Abs(parentTransform.lossyScale.x), Mathf.Abs(parentTransform.lossyScale.y));
            float   largestDim = Mathf.Max(absScale.x, absScale.y);

            initialViewingPosition = parentTransform.position - 0.5f * largestDim * parentTransform.forward;
            // Compute inter-camera distance factor (here: minimum inter-camera distance).
            float interCamDistanceFactor = Mathf.Min(intervalSize.x, intervalSize.y);

#if UNITY_EDITOR
            // Compute the gizmo size.
            gizmoSize = ComputeGizmoSize(cameraModels, interCamDistanceFactor);
            UpdateGizmosSize();
#endif //UNITY_EDITOR
        }
        /// <summary>
        /// Computes camera poses on a sphere.
        /// </summary>
        /// <param name="cameraCount"></param> The number of cameras on each of the arcs of the sphere.
        /// <param name="setupDirection"></param> The direction of the sphere setup, inward or outward.
        public void ComputeSpherePoses(Vector2Int cameraCount, SetupDirection setupDirection)
        {
            // Compute several preliminary values.
            Transform parentTransform     = cameraModels[0].transform.parent;
            Vector3   lossyScale          = parentTransform.lossyScale;
            Vector2   intervalArcDistance = Vector2.one / cameraCount;
            Vector2   degreesPerIteration = new Vector2(360f, 180f) * intervalArcDistance;
            int       facingDirection     = (setupDirection == SetupDirection.Outwards) ? 1 : -1;

            // Update the camera model of all source cameras.
            for (int j = 0; j < cameraCount.y; j++)
            {
                for (int i = 0; i < cameraCount.x; i++)
                {
                    int         index       = j * cameraCount.x + i;
                    CameraModel cameraModel = cameraModels[index];
                    cameraModel.SetCameraReferenceIndexAndImageName(index + 1, index.ToString("0000") + ".png");
                    cameraModel.transform.localRotation = Quaternion.AngleAxis(i * degreesPerIteration.x, -Vector3.up) * Quaternion.AngleAxis(-90f + (j + 0.5f) * degreesPerIteration.y, -Vector3.right);
                    cameraModel.transform.localPosition = facingDirection * (cameraModel.transform.localRotation * Vector3.forward);
                    CheckCamDistanceWithOthersInSetup(index, Mathf.Max(0, index - cameraCount.x), index);
                }
            }
            // Set the initial viewing position so that the viewer will look outwards from within, or inwards from without, based on the specified setup direction.
            initialViewingPosition = (facingDirection == 1) ? parentTransform.position : parentTransform.position - 1.5f * parentTransform.localScale.magnitude * parentTransform.forward;
        }
        /// <summary>
        /// Updates the camera setup to have the given number of cameras.
        /// </summary>
        /// <param name="cameraCount"></param> The number of cameras for the setup.
        public void ChangeCameraCount(int cameraCount)
        {
            CameraModel cameraParams = CameraModel.CreateCameraModel();

            // If there are already cameras in the setup, use one of them as the model.
            if (cameraModels != null && cameraModels.Length > 0)
            {
                cameraParams.ParametersFromCameraModel(cameraModels[0]);
            }
            else
            {
                cameraParams.SetCameraReferenceIndexAndImageName(cameraParams.cameraReferenceIndex, "Image");
            }
            // Update the camera setup, using this camera as a model.
            ResetCameraModels();
            cameraModels = new CameraModel[cameraCount];
            for (int iter = 0; iter < cameraModels.Length; iter++)
            {
                CameraModel cameraModel = AddCameraModel(iter);
                cameraModel.ParametersFromCameraModel(cameraParams);
                cameraModel.SetCameraReferenceIndexAndImageName(cameraModel.cameraReferenceIndex, cameraModel.imageName + GeneralToolkit.ToString(iter));
            }
            // Destroy the temporary camera model.
            DestroyImmediate(cameraParams.gameObject);
        }
        /// <summary>
        /// Computes camera poses on a cylinder.
        /// </summary>
        /// <param name="cameraCount"></param> The number of cameras on the circular section and on the vertical side of the cylinder.
        /// <param name="setupDirection"></param> The direction of the cylinder setup, inward or outward.
        public void ComputeCylinderPoses(Vector2Int cameraCount, SetupDirection setupDirection)
        {
            // Compute several preliminary values.
            Transform parentTransform = cameraModels[0].transform.parent;
            float     horizontalDegreesPerIteration = 360f / cameraCount.x;
            int       facingDirection              = (setupDirection == SetupDirection.Outwards) ? 1 : -1;
            int       numberOfVerticalIntervals    = cameraCount.y - 1;
            float     verticalIntervalSize         = 1f / Mathf.Max(1, numberOfVerticalIntervals);
            float     distanceToClosestVerticalCam = Mathf.Abs(parentTransform.lossyScale.y) * verticalIntervalSize;

            // Update the camera model of all source cameras.
            for (int j = 0; j < cameraCount.y; j++)
            {
                for (int i = 0; i < cameraCount.x; i++)
                {
                    int         index       = j * cameraCount.x + i;
                    CameraModel cameraModel = cameraModels[index];
                    cameraModel.SetCameraReferenceIndexAndImageName(index + 1, index.ToString("0000") + ".png");
                    cameraModel.transform.localRotation = Quaternion.AngleAxis(i * horizontalDegreesPerIteration, -Vector3.up);
                    cameraModel.transform.localPosition = facingDirection * (cameraModel.transform.localRotation * Vector3.forward) + ((j - 0.5f * numberOfVerticalIntervals) * verticalIntervalSize) * Vector3.up;
                    cameraModel.UpdateDistanceToClosestCam(distanceToClosestVerticalCam);
                    CheckCamDistanceWithOthersInSetup(index, Mathf.Max(0, index - 1), index);
                }
            }
            // Set the initial viewing position so that the viewer will look outwards from within, or inwards from without, based on the specified setup direction.
            initialViewingPosition = (facingDirection == 1) ? parentTransform.position : parentTransform.position - 1.5f * parentTransform.localScale.magnitude * parentTransform.forward;
        }
        /// <summary>
        /// Computes camera poses on a grid.
        /// </summary>
        /// <param name="cameraCount"></param> The number of cameras on each of the axes of the grid.
        public void ComputeGridPoses(Vector2Int cameraCount)
        {
            // Compute several preliminary values.
            Transform parentTransform   = cameraModels[0].transform.parent;
            Vector3   lossyScale        = parentTransform.lossyScale;
            Vector2   absScale          = new Vector2(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y));
            Vector2   numberOfIntervals = cameraCount - Vector2.one;
            Vector2   intervalSize      = new Vector2(1f / Mathf.Max(1, numberOfIntervals.x), 1f / Mathf.Max(1, numberOfIntervals.y));
            // Compute the minimum inter-camera distance.
            float distanceToClosestCam = Mathf.Min(absScale.x * intervalSize.x, absScale.y * intervalSize.y);

            // Update the camera model of all source cameras.
            for (int j = 0; j < cameraCount.y; j++)
            {
                for (int i = 0; i < cameraCount.x; i++)
                {
                    int         index       = j * cameraCount.x + i;
                    CameraModel cameraModel = cameraModels[index];
                    cameraModel.SetCameraReferenceIndexAndImageName(index + 1, index.ToString("0000") + ".png");
                    Vector2 planePos = (new Vector2(i, j) - 0.5f * numberOfIntervals) * intervalSize;
                    cameraModel.transform.localPosition = planePos.x * Vector3.right + planePos.y * Vector3.up;
                    cameraModel.transform.localRotation = Quaternion.identity;
                    cameraModel.UpdateDistanceToClosestCam(distanceToClosestCam);
                }
            }
            // Set the initial viewing position so that the viewer will initially look at the center of the grid.
            float largestDim = Mathf.Max(absScale.x, absScale.y);

            initialViewingPosition = parentTransform.position - 0.5f * largestDim * parentTransform.forward;
        }
        /// <summary>
        /// Saves additional information related to acquisition, with the given values.
        /// </summary>
        /// <param name="cameraSetup"></param> The camera setup containing the acquisition information.
        public void SaveCOLIBRIVRAdditionalInformation(CameraSetup cameraSetup)
        {
            // Determine the camera model, or initialize a new one if there is none.
            CameraModel cameraParams;

            if (cameraSetup.cameraModels != null)
            {
                cameraParams = cameraSetup.cameraModels[0];
            }
            else
            {
                cameraParams = CameraModel.CreateCameraModel();
            }
            // Get the initial viewing position.
            Vector3 initialViewingPos = cameraSetup.initialViewingPosition;

            // Store this information in the additional information file.
            GeneralToolkit.CreateOrClear(PathType.File, additionalInfoFile);
            StringBuilder stringBuilder = new StringBuilder();

            stringBuilder.AppendLine("# COLIBRI VR additional information:");
            stringBuilder.AppendLine("#   INITIAL_VIEWING_POSITION");
            string line = initialViewingPos.x + " " + initialViewingPos.y + " " + initialViewingPos.z;

            stringBuilder.AppendLine(line);
            File.WriteAllText(additionalInfoFile, stringBuilder.ToString());
            // Delete any temporary camera model.
            if (cameraSetup.cameraModels == null)
            {
                DestroyImmediate(cameraParams.gameObject);
            }
        }
Example #7
0
        /// <summary>
        /// Adds a camera model to the setup.
        /// </summary>
        /// <param name="setupIndex"></param> Index of the newly-created camera in the setup.
        /// <returns></returns> The created camera model.
        public CameraModel AddCameraModel(int setupIndex)
        {
            CameraModel cameraModel = CameraModel.CreateCameraModel(transform);

            cameraModels[setupIndex] = cameraModel;
#if UNITY_EDITOR
            UpdateGizmoColor(setupIndex);
#endif //UNITY_EDITOR
            return(cameraModel);
        }
Example #8
0
 /// <summary>
 /// Updates the preview camera with a given set of camera models.
 /// </summary>
 /// <param name="sourceCameraModel"></param> The camera model with which to update the preview camera.
 public void UpdateCameraModel(CameraModel sourceCameraModel)
 {
     if (previewCamera != null)
     {
         // Store the camera model for further use.
         _cameraModel = sourceCameraModel;
         // Set up the camera's parameters and target texture from the given camera model.
         previewCamera.targetTexture = null;
         _cameraModel.TransferParametersToCamera(ref previewCamera);
         GeneralToolkit.CreateRenderTexture(ref targetTexture, _cameraModel.pixelResolution, targetTexture.depth, targetTexture.format, targetTexture.sRGB == false, targetTexture.filterMode, targetTexture.wrapMode);
         previewCamera.targetTexture = targetTexture;
     }
 }
Example #9
0
        /// <summary>
        /// Computes camera poses on a sphere.
        /// </summary>
        /// <param name="parentTransform"></param> The parent transform.
        /// <param name="cameraCount"></param> The number of cameras on each of the arcs of the sphere.
        /// <param name="setupDirection"></param> The direction of the sphere setup, inward or outward.
        public void ComputeSpherePoses(Transform parentTransform, Vector2Int cameraCount, SetupDirection setupDirection)
        {
            // Compute several preliminary values.
            Vector2 intervalArcDistance = Vector2.one / cameraCount;
            Vector2 degreesPerIteration = new Vector2(360f, 180f) * intervalArcDistance;
            int     facingDirection     = (setupDirection == SetupDirection.Outwards) ? 1 : -1;
            Vector3 absScale            = new Vector3(Mathf.Abs(parentTransform.lossyScale.x), Mathf.Abs(parentTransform.lossyScale.y), Mathf.Abs(parentTransform.lossyScale.z));

            // Update the camera model of all source cameras.
            for (int j = 0; j < cameraCount.y; j++)
            {
                for (int i = 0; i < cameraCount.x; i++)
                {
                    int         index       = j * cameraCount.x + i;
                    CameraModel cameraModel = cameraModels[index];
                    cameraModel.SetCameraReferenceIndexAndImageName(index, index.ToString("0000") + ".png");
                    cameraModel.transform.rotation = Quaternion.AngleAxis(i * degreesPerIteration.x, -parentTransform.up) * Quaternion.AngleAxis(-90f + (j + 0.5f) * degreesPerIteration.y, -parentTransform.right) * parentTransform.rotation;
                    cameraModel.transform.position = parentTransform.position + Vector3.Scale(cameraModels[index].transform.rotation * Vector3.forward, facingDirection * absScale);
                }
            }
            // Set the initial viewing position so that the viewer will look outwards from within, or inwards from without, based on the specified setup direction.
            initialViewingPosition = (facingDirection == 1) ? parentTransform.position : parentTransform.position - 1.5f * parentTransform.localScale.magnitude * parentTransform.forward;
            // Compute the inter-camera distance factor (here: minimum inter-camera distance).
            float interCamDistanceFactor = 1f;
            int   totalCameraCount       = cameraCount.x * cameraCount.y;

            if (totalCameraCount > 1)
            {
                float xDistance = (cameraModels[1].transform.position - cameraModels[0].transform.position).magnitude;
                if (xDistance > 0)
                {
                    interCamDistanceFactor = xDistance;
                }
                int   halfHeightIndexOne = (Mathf.FloorToInt(cameraCount.y / 2) - 1) * cameraCount.x;
                int   halfHeightIndexTwo = (halfHeightIndexOne + cameraCount.x);
                float yDistance          = (cameraModels[halfHeightIndexOne % totalCameraCount].transform.position - cameraModels[halfHeightIndexTwo % totalCameraCount].transform.position).magnitude;
                if (yDistance > 0)
                {
                    interCamDistanceFactor = Mathf.Min(interCamDistanceFactor, yDistance);
                }
            }
#if UNITY_EDITOR
            // Compute the gizmo size.
            gizmoSize = ComputeGizmoSize(cameraModels, interCamDistanceFactor);
            UpdateGizmosSize();
#endif //UNITY_EDITOR
        }
Example #10
0
        /// <summary>
        /// Updates the given camera model's gizmo color.
        /// </summary>
        /// <param name="setupIndex"></param>
        private void UpdateGizmoColor(int setupIndex)
        {
            CameraModel cameraModel = cameraModels[setupIndex];

            cameraModel.gizmoColor = CameraModel.baseColor;
            if (_isColorSourceCamIndices)
            {
                cameraModel.gizmoColor = GeneralToolkit.GetColorForIndex(setupIndex, cameraModels.Length);
            }
            else
            {
                Transform activeTransform = Selection.activeTransform;
                if (activeTransform != null && transform.IsChildOf(activeTransform) && setupIndex == previewIndex)
                {
                    cameraModel.gizmoColor = CameraModel.selectedColor;
                }
            }
        }
        /// <summary>
        /// Updates the "distance to closest camera" attribute for each camera model in the setup, by comparison with the camera at the given index.
        /// </summary>
        /// <param name="indexToCompare"></param> The index of the source camera with which to check relative distance.
        /// <param name="startSourceCamIndex"></param> The source camera index at which to start checking.
        /// <param name="endSourceCamIndex"></param> The source camera index before which to end checking.
        public void CheckCamDistanceWithOthersInSetup(int indexOfCameraToCompare, int startSourceCamIndex, int endSourceCamIndex)
        {
            CameraModel cameraModel = cameraModels[indexOfCameraToCompare];

            for (int sourceCamIndex = startSourceCamIndex; sourceCamIndex < endSourceCamIndex; sourceCamIndex++)
            {
                if (sourceCamIndex != indexOfCameraToCompare)
                {
                    CameraModel otherCameraModel    = cameraModels[sourceCamIndex];
                    float       distanceBetweenCams = (cameraModel.transform.position - otherCameraModel.transform.position).magnitude;
                    if (cameraModel.distanceToClosestCam == 0f || distanceBetweenCams < cameraModel.distanceToClosestCam)
                    {
                        cameraModel.UpdateDistanceToClosestCam(distanceBetweenCams);
                    }
                    if (otherCameraModel.distanceToClosestCam == 0f || distanceBetweenCams < otherCameraModel.distanceToClosestCam)
                    {
                        otherCameraModel.UpdateDistanceToClosestCam(distanceBetweenCams);
                    }
                }
            }
        }
        /// <summary>
        /// Saves additional information related to acquisition, with the given values.
        /// </summary>
        /// <param name="cameraSetup"></param> The camera setup containing the acquisition information.
        public void SaveAdditionalSetupInformation(CameraSetup cameraSetup)
        {
            // Determine the camera model, or initialize a new one if there is none.
            CameraModel cameraParams;

            if (cameraSetup.cameraModels != null && cameraSetup.cameraModels.Length > 0)
            {
                cameraParams = cameraSetup.cameraModels[0];
            }
            else
            {
                cameraParams = CameraModel.CreateCameraModel();
            }
            // Store the initial viewing position.
            Vector3 initialViewingPos = cameraSetup.initialViewingPosition;

            GeneralToolkit.CreateOrClear(PathType.File, additionalInfoFile);
            StringBuilder stringBuilder = new StringBuilder();

            stringBuilder.AppendLine("# Additional setup information:");
            stringBuilder.AppendLine("#   INITIAL_VIEWING_POSITION");
            string line = GeneralToolkit.ToString(initialViewingPos.x) + " " + GeneralToolkit.ToString(initialViewingPos.y) + " " + GeneralToolkit.ToString(initialViewingPos.z);

            stringBuilder.AppendLine(line);
            // Store the minimum/maximum distance range
            stringBuilder.AppendLine("#   Distance ranges with one line of data per camera:");
            stringBuilder.AppendLine("#   CAMERA_ID DISTANCE_RANGE_MIN DISTANCE_RANGE_MAX");
            foreach (CameraModel camera in cameraSetup.cameraModels)
            {
                Vector2 distanceRange = camera.distanceRange;
                stringBuilder.AppendLine(GeneralToolkit.ToString(camera.cameraReferenceIndex) + " " + GeneralToolkit.ToString(distanceRange.x) + " " + GeneralToolkit.ToString(distanceRange.y));
            }
            // Save the file.
            File.WriteAllText(additionalInfoFile, stringBuilder.ToString());
            // Delete any temporary camera model.
            if (cameraSetup.cameraModels == null)
            {
                DestroyImmediate(cameraParams.gameObject);
            }
        }
Example #13
0
 /// <summary>
 /// Copies another camera model's parameters.
 /// </summary>
 /// <param name="cameraModel"></param> The camera model to copy parameters from.
 public void ParametersFromCameraModel(CameraModel cameraModel)
 {
     isOmnidirectional = cameraModel.isOmnidirectional;
     focalDistance     = cameraModel.focalDistance;
     if (isOmnidirectional)
     {
         _omnidirectionalPixelResolution = cameraModel.pixelResolution;
         cameraModel.isOmnidirectional   = false;
         _perspectivePixelResolution     = cameraModel.pixelResolution;
         _perspectiveFOV = cameraModel.fieldOfView;
     }
     else
     {
         _perspectivePixelResolution     = cameraModel.pixelResolution;
         _perspectiveFOV                 = cameraModel.fieldOfView;
         cameraModel.isOmnidirectional   = true;
         _omnidirectionalPixelResolution = cameraModel.pixelResolution;
     }
     cameraModel.isOmnidirectional = isOmnidirectional;
     distanceRange      = cameraModel.distanceRange;
     transform.position = cameraModel.transform.position;
     transform.rotation = cameraModel.transform.rotation;
     SetCameraReferenceIndexAndImageName(cameraModel.cameraReferenceIndex, cameraModel.imageName);
 }
Example #14
0
 /// <summary>
 /// Creates the preview camera given a camera model.
 /// </summary>
 /// <param name="callerGO"></param> The caller gameobject.
 /// <param name="previewCameraTransform"></param> The transform on which to create a preview camera.
 /// <param name="sourceCameraModel"></param> The camera model with which to update the preview camera.
 public void CreatePreviewCamera(GameObject callerGO, Transform previewCameraTransform, CameraModel sourceCameraModel)
 {
     // The preview camera is only created if it is not already so.
     if (previewCamera == null)
     {
         // Set the camera's hide flags.
         previewCameraTransform.gameObject.hideFlags = HideFlags.HideAndDontSave;
         // Indicate that the camera object's parent is the caller object.
         previewCameraTransform.parent = callerGO.transform;
         // Set up the camera component on the given transform object.
         previewCamera           = GeneralToolkit.GetOrAddComponent <Camera>(previewCameraTransform.gameObject);
         previewCamera.hideFlags = previewCameraTransform.gameObject.hideFlags;
         // Indicate that this camera is monoscopic, even in VR mode.
         previewCamera.stereoTargetEye = StereoTargetEyeMask.None;
         // Disable the camera component so that it only renders when necessary.
         previewCamera.enabled = false;
         // Update the camera object from the parameters of the camera model.
         UpdateCameraModel(sourceCameraModel, false);
     }
 }
 /// <summary>
 /// On selection, sets up the target properties.
 /// </summary>
 void OnEnable()
 {
     // Get the target object.
     _targetObject = (CameraModel)serializedObject.targetObject;
 }