function varargout = OpenGL_Matlab_Figure(varargin)
% OPENGL_MATLAB_FIGURE M-file for OpenGL_Matlab_Figure.fig
%
% Function is written by D.Kroon University of Twente (April 2009)
% Edit the above text to modify the response to help OpenGL_Matlab_Figure
% Last Modified by GUIDE v2.5 11-Apr-2009 09:23:35
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @OpenGL_Matlab_Figure_OpeningFcn, ...
'gui_OutputFcn', @OpenGL_Matlab_Figure_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% --- Executes just before OpenGL_Matlab_Figure is made visible.
function OpenGL_Matlab_Figure_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to OpenGL_Matlab_Figure (see VARARGIN)
% Choose default command line output for OpenGL_Matlab_Figure
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes OpenGL_Matlab_Figure wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% Set the default options
defaultoptions=struct( ...
'Width', 512, ...
'Height', 512);
% Check the input options
if(~exist('options','var')),
options=defaultoptions;
else
tags = fieldnames(defaultoptions);
for i=1:length(tags)
if(~isfield(options,tags{i})), options.(tags{i})=defaultoptions.(tags{i}); end
end
if(length(tags)~=length(fieldnames(options))),
warning('Render:unknownoption','unknown options found');
end
end
% Set the Paint function
data.paint_function_name=varargin{1};
% The initial (Identity) viewmatrix
viewmatrix=[1 0 0 0;0 1 0 0; 0 0 1 0;0 0 0 1];
% Use a struct as data container
data.viewmatrix=viewmatrix;
data.Width=options.Width;
data.Height=options.Height;
data.LastXY=[0 0];
data.zoom=2;
data.FirstRender=true;
data.mouse_button='';
data.handles=handles;
% Initialize render2texture objects
[data]=initializeRender2Texture(data);
% Store all data for this OpenGL window
setappdata(gcf,'data',data);
% Initialize window view matrix
setOpenGLViewingMatrix(data.viewmatrix,data.zoom,data.Width,data.Height);
% Render to framebuffer
render2framebuffer;
% Draw Polygons
eval([data.paint_function_name]);
% Swap buffers
refresh_screen;
function data=initializeRender2Texture(data)
% Add the needed Windows Assemblies
NET.addAssembly('System');
NET.addAssembly('System.Windows.Forms');
% Make A new Form (.NET window)
Form1=System.Windows.Forms.Form;
Form1.Width=data.Width;
Form1.Height=data.Height;
Form1.Visible=false;
% Make an simple Opengl Control for the .NET window
simpleOpenGlControl1 = Tao.Platform.Windows.SimpleOpenGlControl;
% Set all OpenGL Control parameters
simpleOpenGlControl1.AccumBits = 0;
simpleOpenGlControl1.AutoCheckErrors = false;
simpleOpenGlControl1.AutoFinish = false;
simpleOpenGlControl1.AutoMakeCurrent = false;
simpleOpenGlControl1.AutoSwapBuffers = false;
simpleOpenGlControl1.BackColor = System.Drawing.Color.Black;
simpleOpenGlControl1.ColorBits = 32;
simpleOpenGlControl1.DepthBits = 24;
simpleOpenGlControl1.Location = System.Drawing.Point(1, 1);
simpleOpenGlControl1.Name = 'simpleOpenGlControl1';
simpleOpenGlControl1.Size = System.Drawing.Size(Form1.Width-17, Form1.Height-38);
simpleOpenGlControl1.StencilBits = 0;
simpleOpenGlControl1.TabIndex = 0;
% Initialize the Control
simpleOpenGlControl1.InitializeContexts();
% Add the control to the figure,
Form1.Controls.Add(simpleOpenGlControl1);
% Wait to initialize
pause(1)
% Allow to use GL functions without prefixing with Tao.Opengl.
import Tao.OpenGl.*
% Set texture sizes
TextureWidth = simpleOpenGlControl1.Size.Width;
TextureHeight = simpleOpenGlControl1.Size.Height;
% First Flus the openGL pipeline
Gl.glFlush();
% Generate Extern frame buffer id
FB_fbo=Gl.glGenFramebuffersEXT(1);
% Bind frame buffer id to extern
Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, FB_fbo);
% Create the render buffer for the depth
FB_depthBuffer = Gl.glGenRenderbuffersEXT(1);
Gl.glBindRenderbufferEXT(Gl.GL_RENDERBUFFER_EXT, FB_depthBuffer);
% Reserve memory to store the buffer
Gl.glRenderbufferStorageEXT(Gl.GL_RENDERBUFFER_EXT, Gl.GL_DEPTH_COMPONENT, TextureWidth, TextureHeight);
% Now setup a texture to render to
TextureID = Gl.glGenTextures(1);
Gl.glBindTexture(Gl.GL_TEXTURE_2D, TextureID);
% Set texture parameters
Gl.glTexParameterf(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, Gl.GL_CLAMP_TO_EDGE);
Gl.glTexParameterf(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, Gl.GL_CLAMP_TO_EDGE);
Gl.glTexParameterf(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
Gl.glTexParameterf(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);
% Set type of texture data
Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA8, TextureWidth, TextureHeight, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, []);
% And attach it to the FBO so we can render to it
Gl.glFramebufferTexture2DEXT(Gl.GL_FRAMEBUFFER_EXT, Gl.GL_COLOR_ATTACHMENT0_EXT, Gl.GL_TEXTURE_2D, TextureID, 0);
% Attach the depth render buffer to the FBO as it's depth attachment
Gl.glFramebufferRenderbufferEXT(Gl.GL_FRAMEBUFFER_EXT, Gl.GL_DEPTH_ATTACHMENT_EXT, Gl.GL_RENDERBUFFER_EXT, FB_depthBuffer);
status = Gl.glCheckFramebufferStatusEXT(Gl.GL_FRAMEBUFFER_EXT);
if (status ~= Gl.GL_FRAMEBUFFER_COMPLETE_EXT)
error('The card may not be compatible with Framebuffers. Try another bit depth.');
end
% Unbind the FBO for now
Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, 0);
% (Store also OpenGL control object, otherwise listeners are disposed)
setappdata(gcf,'Control',simpleOpenGlControl1);
setappdata(gcf,'Form',Form1);
% Set data
data.TextureWidth=TextureWidth;
data.TextureHeight=TextureHeight;
data.FB_fbo=FB_fbo;
data.TextureID=TextureID;
function refresh_screen
import Tao.OpenGl.*
data=getappdata(gcf,'data');
% Swap buffer to the new rendered image
simpleOpenGlControl1=getappdata(gcf,'Control');
simpleOpenGlControl1.SwapBuffers();
% Get the texture data
texturedata = NET.createArray('System.Byte',data.TextureWidth * data.TextureHeight* 4);
Gl.glEnable(Gl.GL_TEXTURE_2D);
Gl.glBindTexture(Gl.GL_TEXTURE_2D, data.TextureID);
Gl.glGetTexImage(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, texturedata );
Gl.glDisable(Gl.GL_TEXTURE_2D);
% Convert texture data to Matlab image
I=reshape(double(texturedata),[4 data.TextureWidth data.TextureHeight]);
I=permute(I,[3 2 1]);
I=I(:,:,1:3)/255;
% Show the image
if(data.FirstRender)
data.imshow_handle=imshow(I);
set(get(data.handles.axes1,'Children'),'ButtonDownFcn','OpenGL_Matlab_Figure(''axes1_ButtonDownFcn'',gcbo,[],guidata(gcbo))');
setappdata(gcf,'data',data);
else
set(data.imshow_handle,'Cdata',I);
drawnow('expose')
end
function setOpenGLViewingMatrix(viewmatrix,zoom,Width,Height)
% Allow to use GL functions without prefixing with Tao.Opengl.
import Tao.OpenGl.*
% Set projection matrix
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glLoadIdentity();
% Screen coordinates are set from 0,0 to 1,1
tx=0.5*(2^zoom);
ty=0.5*(2^zoom)*(Height/Width);
Gl.glOrtho(0.5-tx, 0.5+tx, 0.5-ty, 0.5+ty, 0.001,5);
% Align viewmatrix before the viewer screen
viewmatrix=TranslateMatrix([0.5 0.5 -2.5])*viewmatrix;
viewarray=NET.convertArray(viewmatrix(:), 'System.Double',16);
Gl.glMultMatrixd(viewarray);
% The Model matrix (no changes)
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glLoadIdentity();
% Initial Depth buffer value of all pixels
Gl.glClearDepth(1);
% Set to default Depth Testing
Gl.glDepthFunc(Gl.GL_LEQUAL);
% Set viewport to fit opengl window
Gl.glViewport(0, 0, Width, Height);
% --- Outputs from this function are returned to the command line.
function varargout = OpenGL_Matlab_Figure_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure
varargout{1} = handles.output;
% --- Executes on mouse press over axes background.
function axes1_ButtonDownFcn(hObject, eventdata, handles)
% hObject handle to axes1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
data=getappdata(gcf,'data');
data.mouse_button=get(handles.figure1,'SelectionType');
data.LastXY=data.XY;
setappdata(gcf,'data',data);
% --- Executes when user attempts to close figure1.
function figure1_CloseRequestFcn(hObject, eventdata, handles)
% hObject handle to figure1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Delete OpenGL Control
simpleOpenGlControl1=getappdata(gcf,'Control');
simpleOpenGlControl1.Dispose();
% Remove Form and Window data
rmappdata(gcf,'Control');
rmappdata(gcf,'Form');
rmappdata(gcf,'data');
% Hint: delete(hObject) closes the figure
delete(hObject);
% --- Executes on mouse motion over figure - except title and menu.
function figure1_WindowButtonMotionFcn(hObject, eventdata, handles)
% hObject handle to figure1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
data=getappdata(gcf,'data');
data.XY=get(0, 'PointerLocation');
diffXY=data.XY-data.LastXY;
switch(data.mouse_button)
case 'open'
case 'normal'
R=RotationMatrix([diffXY(2) diffXY(1) 0]);
data.viewmatrix(1:3,1:3)=R(1:3,1:3)*data.viewmatrix(1:3,1:3);
case 'extend'
t=[data.zoom*diffXY(1)/data.Width -data.zoom*diffXY(2)/data.Width 0];
T=[0 0 0 t(1);
0 0 0 t(2);
0 0 0 t(3);
0 0 0 0];
data.viewmatrix=data.viewmatrix+T;
case 'alt'
data.zoom=data.zoom+8*diffXY(2)/data.Width;
otherwise
setappdata(gcf,'data',data);
return;
end
data.FirstRender=false;
setappdata(gcf,'data',data);
% Initialize window view matrix
setOpenGLViewingMatrix(data.viewmatrix,data.zoom,data.Width,data.Height);
% Render to framebuffer
render2framebuffer;
% Draw Polygons
eval([data.paint_function_name]);
% Swap buffers
refresh_screen;
function render2framebuffer()
% Render to frame buffer
import Tao.OpenGl.*
data=getappdata(gcf,'data');
Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, data.FB_fbo);
Gl.glPushAttrib(Gl.GL_VIEWPORT_BIT);
Gl.glViewport(0, 0, data.TextureWidth, data.TextureHeight);
% --- Executes on mouse press over figure background, over a disabled or
% --- inactive control, or over an axes background.
function figure1_WindowButtonUpFcn(hObject, eventdata, handles)
% hObject handle to figure1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
data=getappdata(gcf,'data');
data.mouse_button='';
setappdata(gcf,'data',data);
function M=ResizeMatrix(s)
M=[s(1) 0 0 0;
0 s(2) 0 0;
0 0 s(3) 0;
0 0 0 1];
function R=RotationMatrix(r)
% Determine the rotation matrix (View matrix) for rotation angles xyz ...
Rx=[1 0 0 0; 0 cosd(r(1)) -sind(r(1)) 0; 0 sind(r(1)) cosd(r(1)) 0; 0 0 0 1];
Ry=[cosd(r(2)) 0 sind(r(2)) 0; 0 1 0 0; -sind(r(2)) 0 cosd(r(2)) 0; 0 0 0 1];
Rz=[cosd(r(3)) -sind(r(3)) 0 0; sind(r(3)) cosd(r(3)) 0 0; 0 0 1 0; 0 0 0 1];
R=Rx*Ry*Rz;
function M=TranslateMatrix(t)
M=[1 0 0 t(1);
0 1 0 t(2);
0 0 1 t(3);
0 0 0 1];