/// <summary> /// Starts up and selects a device's camera, and finds appropriate picture settings /// based on the provided resolution! /// </summary> /// <param name="preferGPUTexture">Do you prefer GPU textures, or do you prefer a NativeArray of colors? Certain optimizations may be present to take advantage of this preference.</param> /// <param name="resolution">Preferred resolution for taking pictures, note that resolutions are not guaranteed! Refer to CameraResolution for details.</param> /// <param name="onInitialized">When the camera is initialized, this callback is called! Some cameras may return immediately, others may take a while. Can be null.</param> public void Initialize(bool aPreferGPUTexture, CameraResolution aResolution, Action aOnInitialized) { resolution = aResolution; Resolution cameraResolution = resolution.nativeResolution == NativeResolutionMode.Smallest ? PhotoCapture.SupportedResolutions.OrderBy((res) => res.width * res.height).First() : PhotoCapture.SupportedResolutions.OrderBy((res) => - res.width * res.height).First(); cacheTex = new Texture2D(cameraResolution.width, cameraResolution.height); // Create a PhotoCapture object PhotoCapture.CreateAsync(false, delegate(PhotoCapture captureObject) { camera = captureObject; cameraParams = new CameraParameters(); cameraParams.hologramOpacity = 0.0f; cameraParams.cameraResolutionWidth = cameraResolution.width; cameraParams.cameraResolutionHeight = cameraResolution.height; cameraParams.pixelFormat = CapturePixelFormat.BGRA32; IntPtr unknown = camera.GetUnsafePointerToVideoDeviceController(); using (VideoDeviceControllerWrapperUWP wrapper = new VideoDeviceControllerWrapperUWP(unknown)) { wrapper.SetExposure(-7); wrapper.SetWhiteBalance(5000); wrapper.SetISO(80); } if (aOnInitialized != null) { aOnInitialized(); } isReady = true; }); }
/// <summary> /// Internal version of initialize. Should not be called more than once unless Shutdown has been called. /// </summary> /// <param name="preferGPUTexture"> /// Whether GPU textures are preferred over NativeArray of colors. Certain optimizations may be present to take advantage of this preference. /// </param> /// <param name="preferredResolution"> /// Preferred resolution for taking pictures. Note that resolutions are not guaranteed! Refer to CameraResolution for details. /// </param> /// <returns> /// A <see cref="Task"/> that represents the operation. /// </returns> private async Task InnerInitializeAsync(bool preferGPUTexture, CameraResolution preferredResolution) { // Store preferred resolution resolution = preferredResolution; // Find the nearest supported camera resolution to the preferred one Resolution cameraResolution = resolution.nativeResolution == NativeResolutionMode.Smallest ? PhotoCapture.SupportedResolutions.OrderBy((res) => res.width * res.height).First() : PhotoCapture.SupportedResolutions.OrderBy((res) => - res.width * res.height).First(); // Create the texture cache cacheTex = new Texture2D(cameraResolution.width, cameraResolution.height); // Setup parameters for the camera cameraParams = new CameraParameters(); cameraParams.hologramOpacity = 0.0f; cameraParams.cameraResolutionWidth = cameraResolution.width; cameraParams.cameraResolutionHeight = cameraResolution.height; cameraParams.pixelFormat = CapturePixelFormat.BGRA32; // Create the PhotoCapture camera camera = await CameraExtensions.CreateAsync(false); // Create the wrapper IntPtr unknown = camera.GetUnsafePointerToVideoDeviceController(); wrapper = new VideoDeviceControllerWrapperUWP(unknown); }
/// <summary> /// Grab worldToCamera matrix and projection matrix from the Hololens /// camera for correct texture placement, clip and save the texture as /// an image, then properly clean up (dispose of) the PhotoCaptureFrame /// storing relevant image data. /// </summary> /// <param name="result"> /// Information about the success of taking the picture. /// </param> /// <param name="photoCaptureFrame"> /// The information/image associated with the picture taken. /// </param> static void OnPhotoCaptured(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame) { // After the first photo, we want to lock in the current exposure and white balance settings. if (lockCameraSettings && currentPhoto == 0) { //#if WINDOWS_UWP #if WINDOWS_UWP //#if UNITY_WSA_10_0 unsafe { //This is how you access a COM object. VideoDeviceController vdm = (VideoDeviceController)Marshal.GetObjectForIUnknown(photoCaptureObj.GetUnsafePointerToVideoDeviceController()); //Locks current exposure for all future images vdm.ExposureControl.SetAutoAsync(false); //Figureout how to better handle the Async //Locks the current WhiteBalance for all future images vdm.WhiteBalanceControl.SetPresetAsync(ColorTemperaturePreset.Fluorescent); //vdm.WhiteBalanceControl.SetPresetAsync(ColorTemperaturePreset.Manual); } #endif } // Grab appropriate matrices, and write them to the local storage // arrays at the correct index Matrix4x4 worldToCameraMatrix; Matrix4x4 projectionMatrix; bool matricesExtracted = ExtractCameraMatrices(photoCaptureFrame, out worldToCameraMatrix, out projectionMatrix); if (matricesExtracted) { WriteMatricesToArrays(worldToCameraMatrix, projectionMatrix, currentPhoto); // Set up local class texture to save as a picture/texture - Hololens camera requires BGRA32 format m_Texture = new Texture2D(m_CameraParameters.cameraResolutionWidth, m_CameraParameters.cameraResolutionHeight, TextureFormat.BGRA32, false); photoCaptureFrame.UploadImageDataToTexture(m_Texture); m_Texture = ClipTexture(m_Texture); m_Texture.wrapMode = TextureWrapMode.Clamp; SaveTexture(); // Reset displayed message to remind user how to take photos or end texturing process TextManager.SetText(Messages.PhotoPrompt + Messages.AppendNumPhotosTaken()); } else { TextManager.SetText(Messages.MatrixFail); } // Clean up camera memory photoCaptureFrame.Dispose(); // Automatically shut down the operation if the maximum number of // textures is reached. if (currentPhoto >= MaxPhotoNum) { StopTextureCapture(); } }