123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- classdef CDisplay < handle
- % a display class, manage the most common display functions, such as
- % display text, fixation, flip, degree of visual angle. It also stores
- % display informations, such as resolution, center x,y, ifi ...
- % methods:
- % 1. constructor
- % obj=CDisplay('monitorSize',size,'viewDistance',viewDistance,'bgColor',bgColor,'Color',color,'fontSize',fz,'skipSync',bSync);
- % 2. display text
- % dispText(txt[,flip,clearBackground]);
- % 3. close screen
- % close();
- % 4. calculate visual angle (deg) to pixels
- % deg2pix(degree)
- % 5. display fixation
- % dispFixation(size [,type, flip, clearBackground]);
- % 6. flip: bring back buffer to front (display)
- % flip(obj [, clearBackground])
- % Screen class of PTB
- % Last modify: 7.7.2011
- % Created by: Z. Shi, shi@lmu.de
-
- % 14.07.2011 add createShape function to create simple shapes
- % 07.07.2014 add debug option - fullWindow,
- properties
- wnd = -1; %window handle
- bSkipSync = 0;
- fullWindow = 1; % full screen
- ifi = -1; %inter-frame interval (refresh rate)
- cx = -1; % center x
- cy = -1; % center y
- pdeg; % pixels per degree
- bgColor = 0; % background color
- color = 255; % front color
- fontSize = 14;
- lineWidth = 60;
- lineSpace = 1.5;
- inch = 20;
- viewDistance = 57;
- nItem = 0;
- items;
- end
-
- methods
- function obj = CDisplay(varargin)
- % constructure
- % inch,viewDistance, bgColor, color, fontsize
- p = inputParser;
- p.addParamValue('monitorSize',20,@isnumeric);
- p.addParamValue('viewDistance',57,@isnumeric);
- p.addParamValue('bgColor',[0 0 0],@isnumeric);
- p.addParamValue('Color',[255 255 255],@isnumeric);
- p.addParamValue('fontSize',14,@isnumeric);
- p.addParamValue('lineWidth',60,@isnumeric);
- p.addParamValue('lineSpace',1.5,@isnumeric);
- p.addParamValue('skipSync',0,@isnumeric);
- p.addParamValue('fullWindow',1,@isnumeric);
- p.parse(varargin{:});
-
- %init screens
- obj.inch = p.Results.monitorSize;
- obj.viewDistance = p.Results.viewDistance;
- obj.bgColor = p.Results.bgColor;
- obj.color = p.Results.Color;
- obj.fontSize = p.Results.fontSize;
- obj.lineWidth = p.Results.lineWidth;
- obj.lineSpace = p.Results.lineSpace;
- obj.bSkipSync = p.Results.skipSync;
- obj.fullWindow = p.Results.fullWindow;
- try
- InitializeMatlabOpenGL;
- AssertOpenGL;
- priority = MaxPriority('KbCheck');
- Priority(priority);
- HideCursor;
- if obj.bSkipSync
- Screen('Preference','SkipSyncTests',1);
- else
- Screen('Preference','SkipSyncTests',0);
- end
- screens=Screen('Screens');
- screenNumber=max(screens);
- if obj.fullWindow
- [obj.wnd wsize] = Screen('OpenWindow',screenNumber); % Open On Screen window, mainWnd
- else
- [obj.wnd wsize] = Screen('OpenWindow',screenNumber,[],[0 0 600 400]);
- end
- obj.ifi=Screen('GetFlipInterval', obj.wnd);
-
- obj.cx = wsize(3)/2; %center x
- obj.cy = wsize(4)/2; %center y
- pix = obj.inch*2.54/sqrt(1+9/16)/wsize(3); % calculate one pixel in cm
- obj.pdeg = round(2*tan((1/2)*pi/180) * obj.viewDistance / pix);
- catch ME
- Screen('CloseAll');
- Priority(0);
- disp(ME.message);
- disp('error in initial display');
- end
- end % end of constructor
- function nframes = sec2frames(obj,secs)
- %convert seconds to number of frames
- nframes = round(secs/obj.ifi);
- end
-
- function dispText(obj,txt, flip,clearBackground)
- % dispText
- try
- if nargin < 3
- flip = 1;
- clearBackground = 1;
- end
- if nargin == 3
- clearBackground = 1;
- end
- if clearBackground
- Screen('FillRect',obj.wnd,obj.bgColor);
- end
- Screen('TextSize',obj.wnd,obj.fontSize);
- DrawFormattedText(obj.wnd,txt,'center','center',obj.color,obj.lineWidth,[],[],obj.lineSpace);
- if flip
- Screen('Flip', obj.wnd);
- end
- catch ME
- Screen('CloseAll');
- Priority(0);
- disp(ME.message);
- end
- end % end of dispText method
-
- function itemIndex = createItem(obj,itemData)
- %create items (texture, image, etc.)
- itemIndex= Screen('MakeTexture', obj.wnd, itemData);
- obj.nItem = obj.nItem + 1;
- obj.items(obj.nItem) = itemIndex;
- end
-
- function itemIndex = createShape(obj,name,x,y,varargin)
- %create simple shape
- %be sure to do this before the trial starts
- p = inputParser;
- p.addRequired('name', @(x) any(strcmpi(x,{'rectangle','circle'})));
- p.addRequired('x',@(x) x>0);
- p.addRequired('y',@(x) x>0);
- p.addParamValue('fill',1,@isnumeric);
- p.addParamValue('border',0.1,@(x) x>0);
- p.addParamValue('bgColor',obj.bgColor,@isnumeric);
- p.addParamValue('color',obj.color,@isnumeric);
- p.parse(name,x,y,varargin{:});
-
- xp = round(p.Results.x * obj.pdeg)/2;
- yp = round(p.Results.y * obj.pdeg)/2; %convert to pixels
- bp = round(p.Results.border * obj.pdeg);
- bc = p.Results.bgColor;
- fc = p.Results.color;
- if length(bc) == 1
- bc = repmat(bc,3,1);
- end
- if length(fc) == 1
- fc = repmat(fc,3,1);
- end
- data = zeros(xp*2,yp*2,3); %store in rgb format
- switch p.Results.name
- case {'circle'}
- if p.Results.fill == 1 %fill
- for ix = 1:xp*2
- for iy = 1:yp*2
- if (ix-xp)*(ix-xp)/xp/xp + (iy-yp)*(iy-yp)/yp/yp < 1
- data(ix,iy,:) = fc;
- else
- data(ix,iy,:) = bc;
- end
- end
- end
- else % frame
- for ix = 1:xp*2
- for iy = 1:yp*2
- if (ix-xp)*(ix-xp)/xp/xp + (iy-yp)*(iy-yp)/yp/yp < 1 && ...
- (ix-xp)*(ix-xp)/(xp-bp)/(xp-bp) + (iy-yp)*(iy-yp)/(yp-bp)/(yp-bp) >= 1
- data(ix,iy,:) = fc;
- else
- data(ix,iy,:) = bc;
- end
- end
- end
- end
- case {'rectangle'}
- if p.Results.fill == 1 %fill
- for ix = 1:xp*2
- for iy = 1:yp*2
- data(ix,iy,:) = fc;
- end
- end
- else %frame
- for ix = 1:xp*2
- for iy = 1:yp*2
- if abs(ix-xp)>xp-bp || abs(iy-yp)>yp-bp
- data(ix,iy,:) = fc;
- else
- data(ix,iy,:) = bc;
- end
- end
- end
- end
- end %end of switch
- %create texture
- itemIndex= Screen('MakeTexture', obj.wnd, data);
- obj.nItem = obj.nItem + 1;
- obj.items(obj.nItem) = itemIndex;
-
- end
- function dispItems(obj, xys, itemIndex, itemSizes,rotations, flip)
- %disp items at xys (in visual angle, center 0,0)
- if nargin < 6
- flip = 1;
- end
- if nargin < 5
- rotations = [];
- end
- if nargin < 4
- itemSizes = [obj.cx / obj.pdeg, obj.cy/obj.pdeg]*2;
- end
- destRects = zeros(4, length(itemIndex));
- for iObj = 1: length(itemIndex)
- if size(itemSizes,1) == 1
- itemRect = [0 0 itemSizes*obj.pdeg];
- else
- itemRect = [0 0 itemSizes(iObj,:)*obj.pdeg];
- end
- rect = CenterRectOnPoint(itemRect,obj.pdeg*xys(iObj,1)+obj.cx, obj.pdeg*xys(iObj,2)+obj.cy);
- destRects(:,iObj) = rect';
- end
- Screen('DrawTextures',obj.wnd,itemIndex,[],destRects,rotations);
- if flip
- Screen('Flip', obj.wnd);
- end
- end
-
- function close(obj)
- %% dispClose: close display
- %close display and delete Screen
- Screen('CloseAll');
- ShowCursor;
- Priority(0);
- obj.wnd = -1;
- end % end of closeDisp
-
- function pixs=deg2pix(obj, degree)
- %% deg2pix: calculate degree to pixels
- screenWidth = obj.inch*2.54/sqrt(1+9/16); % calculate screen width in cm
- pix=screenWidth/obj.cx/2; %calculates the size of a pixel in cm
- pixs = round(2*tan((degree/2)*pi/180) * obj.viewDistance / pix);
- end %end of deg2pix
-
- function deg = pix2deg(obj, pixels)
- deg = 1/obj.pdeg*pixels;
- end
-
- function dispFixation(obj,sz,type,flip,clearBackground)
- %% dispCrossFix: display cross fixation
- if nargin < 3
- type = 1;
- flip = 1;
- clearBackground = 1;
- end
- if nargin == 3
- flip = 1;
- clearBackground = 1;
- end
- if nargin == 4
- clearBackground = 1;
- end
- if clearBackground
- Screen('FillRect',obj.wnd, obj.bgColor);
- end
- if type == 1
- rect = CenterRectOnPoint([0 0 2 sz],obj.cx,obj.cy);
- Screen('FillRect',obj.wnd,obj.color,rect);
- rect = CenterRectOnPoint([0 0 sz 2],obj.cx,obj.cy);
- Screen('FillRect',obj.wnd,obj.color, rect);
- else
- rect = CenterRectOnPoint([0 0 sz sz],obj.cx,obj.cy);
- Screen('FillOval',obj.wnd,obj.color,rect);
- end
- if flip
- Screen('Flip',obj.wnd);
- end
- end %end of dispCrossFix
-
- function [vbl visonset] = flip(obj,clearBackground, when)
- %% flip: put back buffer to screen
- if nargin < 3
- when = 0;
- end
- if nargin < 2
- clearBackground = 0;
- end
- if clearBackground
- Screen('FillRect',obj.wnd,obj.bgColor);
- end
- [vbl visonset] = Screen('Flip',obj.wnd, when);
- end
-
- end
- end
|