/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016 Raytrix GmbH. All rights reserved.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// namespace: Example.LFR.CS.BasicA
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Example.LFR.CS.BasicA
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// The application's main form.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public partial class MainForm : Form
{
// The CLUViz Control instance which creates the open gl context.
CLUViz.Net.ViewCtrl m_xCluView;
// The CLUViz Engine instance.
CLUViz.Net.EngineCtrl m_xCluEngine;
// A slider for changing the focus
System.Windows.Forms.TrackBar m_xSliderFocus;
// The CUDA compute instance.
Rx.LFR.Net.CudaCompute m_xCudaCompute;
// The open GL interop instance that holes the open GL context
Rx.LFR.Net.OpenGlInterop m_xOpenGlInterop;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Default constructor.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public MainForm()
{
try
{
InitializeComponent();
// Initialize
m_xSliderFocus = new System.Windows.Forms.TrackBar();
m_xSliderFocus.Enabled = false;
// Set the starting slider value (0.5) and its range [0.0,1.0] scaled by 100.
m_xSliderFocus.Minimum = 0;
m_xSliderFocus.Maximum = 100;
m_xSliderFocus.Value = 50;
m_xSliderFocus.SmallChange = 1;
m_xSliderFocus.Width = 300;
// Add an event handler to the Scroll event, so that we can react to it
m_xSliderFocus.Scroll += new EventHandler(m_xSliderFocus_Scroll);
// Throw the slider control into a flow control panel
panelCtrl.Controls.Add(m_xSliderFocus);
}
catch (Rx.Net.RxException xEx)
{
MessageBox.Show(xEx.ToString());
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Event handler. Called by MainForm for shown events.
///
///
/// Source of the event.
/// Event information.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void MainForm_Shown(object sender, EventArgs e)
{
try
{
// Start the CLU engine
m_xCluEngine = new CLUViz.Net.EngineCtrl();
m_xCluEngine.Start();
// Now create the CLU control and embed it into the "panelClu" control.
// Changes in size and position of panelClu are automatically applied
// to the CLU control.
// Since the CLU control display runs in a separate thread, we must
// create an OpenGL rendering context for the CUDA thread (this thread)
// that shares its texture memory with the OpenGL rendering context in
// the CLU control thread. This is done automatically by setting the second
// parameter to "true".
m_xCluView = new CLUViz.Net.ViewCtrl(true, 0);
// We now have to make this shared rendering context current,
// since otherwise all CUDA commands will fail. That is,
// CUDA is only initialized once this rendering context is made current.
// Note that the shared rendering context for this thread is attached to
// an invisible dummy window that is held internally.
m_xCluView.MakeCurrentSharedRC();
// Initialize the open GL interop instance and store the current context in it.
m_xOpenGlInterop = new Rx.LFR.Net.OpenGlInterop();
m_xOpenGlInterop.StoreCurrentContext();
// Authenticate the light field runtime
Rx.LFR.Net.LightFieldRuntime.Authenticate();
// Enumerate all CUDA devices at the beginning
Rx.LFR.Net.Cuda.EnumerateCudaDevices();
// Assign the CUDA device and the calibration
m_xCudaCompute = new Rx.LFR.Net.CudaCompute();
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.PreProc_DataType, (uint) Rx.InteropNet.Runtime28.EDataType.UByte);
if (Rx.LFR.Net.Cuda.GetDeviceCount() == 0)
{
throw new Exception("No Cuda device found");
}
m_xCudaCompute.SetCudaDevice(Rx.LFR.Net.Cuda.GetDevice((int) 0));
// Add the CluView to the panel
panelClu.Controls.Add(m_xCluView);
m_xCluView.Dock = DockStyle.Fill;
// Now set the visualization CLUScript from the resources.
m_xCluView.SetScript(Example.LFR.CS.BasicA.Properties.Resources.View_Image_01);
}
catch (Rx.Net.RxException xEx)
{
MessageBox.Show(xEx.ToString());
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Event handler. Called by _xSliderFocus for scroll events.
///
///
/// Source of the event.
/// Event information.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void m_xSliderFocus_Scroll(object sender, EventArgs e)
{
try
{
// Refocus from raw image
UpdateFocus();
}
catch (Rx.Net.RxException xEx)
{
MessageBox.Show(xEx.ToString());
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Event handler. Called by loadRayImageToolStripMenuItem for click events.
///
///
/// Source of the event.
/// Event information.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void loadRayImageToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
openFileDialog1.Filter = "Ray Image|*.ray";
DialogResult diagRes = openFileDialog1.ShowDialog();
if (diagRes == DialogResult.OK)
{
Rx.LFR.Net.RayImage xRayImg = new Rx.LFR.Net.RayImage();
// Read the ray file
Rx.LFR.Net.RayFileReader.Read(openFileDialog1.FileName, xRayImg);
// Upload the new image to the compute class and apply the calibration
m_xCudaCompute.ApplyCalibration(xRayImg.GetCalibration(), true);
m_xCudaCompute.UploadRawImage(xRayImg);
// Initialize image view, since new image may have different dimensions.
NewImage();
// Enable the slider
m_xSliderFocus.Enabled = true;
// And finally refocus the image.
UpdateFocus();
}
}
catch (Rx.Net.RxException xEx)
{
MessageBox.Show(xEx.ToString());
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Initialize visualization for new image.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void NewImage()
{
try
{
// Preprocess the image -> must be done before any other image processing can be performened
m_xCudaCompute.Compute_PreProcess();
// Create a refocused image
m_xCudaCompute.Compute_RefocusBasic();
// Get the texture access interface. This interface allows:
// * Updating the texture.
Rx.LFR.Net.ICudaDataTextures xTexture = (m_xCudaCompute.GetInterface(Rx.LFR.Net.Interfaces.ECudaCompute.Textures)) as Rx.LFR.Net.ICudaDataTextures;
// Update texture stored in the open GL interop instance with the given image id.
xTexture.UpdateTexture(Rx.LFR.Net.EImage.RefocusBasic, m_xOpenGlInterop);
// Get the image access interface. This interface allows:
// * Download CUDA image into host memory
// * Upload a host image to CUDA to overwrite a certain CUDA image
// * Access to CUDA device pointer to do own CUDA image processing
Rx.LFR.Net.ICudaDataImages xImages = (m_xCudaCompute.GetInterface(Rx.LFR.Net.Interfaces.ECudaCompute.Images)) as Rx.LFR.Net.ICudaDataImages;
Rx.Net.ImageFormat xImgF = xImages.GetImageFormat(Rx.LFR.Net.EImage.RefocusBasic);
// Initialize the CLUScript variables iWidth and iHeight with
// the dimensions of the refocused image.
m_xCluView.SetVarNumber("iWidth", xImgF.Width);
m_xCluView.SetVarNumber("iHeight", xImgF.Height);
// Check if this is a luminance image
bool bLuminance = ((xImgF.PixelType == Rx.InteropNet.Runtime28.EPixelType.Lum)
|| (xImgF.PixelType == Rx.InteropNet.Runtime28.EPixelType.LumA));
// Execute the script with ToolName == "Image_Create".
// This prepared the image view for an image of the given size.
// The image itself is not copied at this point.
m_xCluView.ExecScript("Image_Create");
// Get the texture id
uint uiTexID = m_xOpenGlInterop.GetTextureID(Rx.LFR.Net.EImage.RefocusBasic);
if (uiTexID > 0)
{
// Set the id to the CluView script
m_xCluView.SetVarNumber("texImage", (int) uiTexID);
// If the refocused image is of luminance type, we need to select
// a different shader for the image display.
if (bLuminance)
{
m_xCluView.ExecScript("Image_Lum_Enable");
}
// Tell the CLU control to redraw the current scene tree.
// This does not re-execute the script itself.
// It needs to be called to ensure that the new content of
// the image texture is displayed.
m_xCluView.Update();
}
}
catch (Rx.Net.RxException xEx)
{
MessageBox.Show(xEx.ToString());
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Update the focus setting.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void UpdateFocus()
{
try
{
// Set the new refocus parameter
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.Focus_RelativeFocusPlane, System.Convert.ToDouble(m_xSliderFocus.Value) / 100.0);
//Refocus image
m_xCudaCompute.Compute_RefocusBasic();
// Redisplay the refocused image
UpdateImage();
}
catch (Rx.Net.RxException xEx)
{
MessageBox.Show(xEx.ToString());
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Redisplay the image.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void UpdateImage()
{
try
{
// Get the texture access interface. This interface allows:
// * Updating the texture.
Rx.LFR.Net.ICudaDataTextures xTexture = (m_xCudaCompute.GetInterface(Rx.LFR.Net.Interfaces.ECudaCompute.Textures)) as Rx.LFR.Net.ICudaDataTextures;
// Update texture stored in the open GL interop instance with the given image id.
xTexture.UpdateTexture(Rx.LFR.Net.EImage.RefocusBasic, m_xOpenGlInterop);
// Get the texture id
uint uiTexID = m_xOpenGlInterop.GetTextureID(Rx.LFR.Net.EImage.RefocusBasic);
if (uiTexID > 0)
{
// Set the id to the CluView script
m_xCluView.SetVarNumber("texImage", (int) uiTexID);
// Tell the CLU control to redraw the current scene tree.
// This does not re-execute the script itself.
// It needs to be called to ensure that the new content of
// the image texture is displayed.
m_xCluView.Update();
}
}
catch (Rx.Net.RxException xEx)
{
MessageBox.Show(xEx.ToString());
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Event handler. Called by MainForm for form closing events.
///
///
/// Source of the event.
/// Form closing event information.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
// End the CLU engine. This closes all CLU controls
m_xCluEngine.End();
// Finalize the Lightfield Runtime. This frees all internal memory also on the CUDA device.
Rx.LFR.Net.LightFieldRuntime.End();
}
catch (Rx.Net.RxException xEx)
{
MessageBox.Show(xEx.ToString());
}
}
}
}