1.Rotating Squares Demo:使用OpenGL命令,使三个不同颜色的矩形旋转
注:这里的旋转方式比较繁琐。如果是为了简便,可以参考之后的纹理操作(将矩形绘制在纹理上,然后让纹理旋转)
(1)Screen(‘glPushMatrix‘, window) 将当前的OpenGL状态信息压入堆栈,由于堆栈空间不超过27,所以要及时利用glPopMatrix函数将堆栈信息弹出堆栈 ,以免堆栈溢出
(2)Screen(‘glTranslate‘, window, tX,tY,tZ) 在X Y Z 维度上平移tX tY tZ tX tY tZ是在X Y Z 维度上的平移量
(3)Screen(‘glRotate‘, window, angle, rX,rY,rZ) 沿由rx、ry、rz空间向量旋转一定角度
(4)Screen(‘glPopMatrix‘, window) 将堆栈中保存的OpenGL状态信息出栈,以恢复原先状态。与glPushMatrix配对使用
对这种方式不理解。个人猜测是先位移动至矩形中心,设置旋转角度,然后再位移回去,再恢复OpenGL的最初状态。
挺麻烦的,以后直接操作纹理旋转即可。
% Our sqaures will have sides 150 pixels in length, as we are going to be 矩形的边长为150pixel,因为要绕着原点旋转,因此对X与Y坐标设置为±75 % rotating these around the origin using OpenGL commands we use -75 to +75 % for the X and Y coordinates dim = 150 / 2; baseRect = [-dim -dim dim dim]; % For this Demo we will draw 3 squares 矩形数量 numRects = 3; % We will randomise the intial rotation angles of the squares. OpenGL uses 随机化旋转的初始角度(OpenGL使用的是角度而非弧度) % Degrees (not Radians) in these commands, so our angles are in degrees angles = rand(1, numRects) .* 360; % We will set the rotations angles to increase by 1 degree on every frame 每帧旋转度数的变化为1 degPerFrame = 1; % We position the squares in the middle of the screen in Y, spaced equally 设置3个矩形的中心的坐标 % scross the screen in X posXs = [screenXpixels * 0.25 screenXpixels * 0.5 screenXpixels * 0.75]; posYs = ones(1, numRects) .* (screenYpixels / 2); % Finally, we will set the colors of the sqaures to red, green and blue 设置3个矩形的颜色 colors = [1 0 0; 0 1 0; 0 0 1]; % Sync us and get a time stamp 获取时间戳 vbl = Screen(‘Flip‘, window); waitframes = 1; % Animation loop while ~KbCheck % With this basic way of drawing we have to translate each square from 这里展示的是一种基本的绘制方式。先将矩形从其屏幕位置变为[0 0],然后旋转,然后 % its screen position, to the coordinate [0 0], then rotate it, then 回到其屏幕位置 % move it back to its screen position. 以高刷新率绘制多个矩形时,这种方式并不高效。但是绘制简单任务的话,能正常工作 % This is rather inefficient when drawing many rectangles at high 更有效的办法看纹理绘制 % refresh rates. But will work just fine for simple drawing tasks. % For a much more efficient way of drawing rotated squares and rectangles % have a look at the texture tutorials for i = 1:numRects % Get the current squares position ans rotation angle 获取当前的位置与旋转角度 posX = posXs(i); posY = posYs(i); angle = angles(i); % Translate, rotate, re-tranlate and then draw our square Screen(‘glPushMatrix‘, window) Screen(‘glTranslate‘, window, posX, posY) Screen(‘glRotate‘, window, angle, 0, 0); Screen(‘glTranslate‘, window, -posX, -posY) Screen(‘FillRect‘, window, colors(i,:),... CenterRectOnPoint(baseRect, posX, posY)); Screen(‘glPopMatrix‘, window) end % Flip to the screen vbl = Screen(‘Flip‘, window, vbl + (waitframes - 0.5) * ifi); % Increment the rotation angles of the sqaures now that we have drawn 每一帧旋转角度的增值 % to the screen angles = angles + degPerFrame; end
2.Mouse In Square Demo: 根据鼠标光标是否在正方形内改变正方形的颜色
思路:首先设置矩形基本属性。然后判断鼠标光标是否在矩形内,根据判断结果,采用不同颜色绘制矩形。这个判断是逐帧进行的
(1) inside=IsInRect(x,y,rect) 判断某位置(x,y)是否在矩形内,返回值为1和0,分别表示在内与在外
% Make a base Rect of 200 by 200 pixels baseRect = [0 0 200 200]; % Define red and blue red = [1 0 0]; blue = [0 0 1]; % Here we set the initial position of the mouse to be in the centre of the 设置光标的初始位置为屏幕中央 % screen SetMouse(xCenter, yCenter, window); % Sync us and get a time stamp vbl = Screen(‘Flip‘, window); waitframes = 1; % Maximum priority level topPriorityLevel = MaxPriority(window); Priority(topPriorityLevel); % Loop the animation until a key is pressed while ~KbCheck % Get the current position of the mouse 获取鼠标状态信息 [x, y, buttons] = GetMouse(window); % Center the rectangle on the centre of the screen centeredRect = CenterRectOnPointd(baseRect, xCenter, yCenter); % See if the mouse cursor is inside the square 判断光标是否在矩形内 inside = IsInRect(x, y, centeredRect); % Set the color of the square to be red if the mouse is inside it or 根据判断结果决定要绘制的颜色 % blue if the mouse is outside it if inside == 1 rectColor = red; elseif inside == 0 rectColor = blue; end % Draw the rect to the screen 绘制矩形 Screen(‘FillRect‘, window, rectColor, centeredRect); % Draw a white dot where the mouse is 绘制点 Screen(‘DrawDots‘, window, [x y], 10, white, [], 2); % Flip to the screen vbl = Screen(‘Flip‘, window, vbl + (waitframes - 0.5) * ifi); end
3.Keyboard Contingent Square Demo: 通过按键盘上的键(在本例中为四个箭头键),以交互式地在屏幕上移动正方形
思路:首先定义四个按键。然后确定一些基本属性,如基本矩形,中心点,每次按键的位移量等。然后判断是否按了箭头(若按了,则计算位移后的矩形中心点坐标,并进行绘制)
或esc键(若按了便退出)
(1) KbNameResult=KbName(arg) 根据参数arg的类型决定返回结果,若为字符,则返回对应的扫描码;若为数值型扫描码,则返回对应的键名,若不提供参数,则1s后调用KbCheck函数。若参数为“UnifyKeyNames”,则命名方法转化为MacOX-X的方案,建议每个程序开头加入这行命令以提高效率。若参数为"KeyNames",会列出扫描码→键名的映射表
% The avaliable keys to press 定义按键 escapeKey = KbName(‘ESCAPE‘); upKey = KbName(‘UpArrow‘); downKey = KbName(‘DownArrow‘); leftKey = KbName(‘LeftArrow‘); rightKey = KbName(‘RightArrow‘); % Get the centre coordinate of the window 获取屏幕中心点坐标 [xCenter, yCenter] = RectCenter(windowRect); % Make a base Rect of 200 by 200 pixels 制作基本矩形 baseRect = [0 0 200 200]; % Set the color of the rect to red 设置颜色 rectColor = [1 0 0]; % Set the intial position of the square to be in the centre of the screen 设置矩形初始的中心点位置 squareX = xCenter; squareY = yCenter; % Set the amount we want our square to move on each button press 设置每次按键后矩形的位移量 pixelsPerPress = 10; % Sync us and get a time stamp 获取时间戳 vbl = Screen(‘Flip‘, window); waitframes = 1; % Maximum priority level 设置优先级 topPriorityLevel = MaxPriority(window); Priority(topPriorityLevel); % This is the cue which determines whether we exit the demo 用以判断是否退出的cue exitDemo = false; % Loop the animation until the escape key is pressed 循环动画,直至按了esc键 while exitDemo == false % Check the keyboard to see if a button has been pressed 检测是否按键 [keyIsDown,secs, keyCode] = KbCheck; % Depending on the button press, either move ths position of the square or exit the demo 依据按键,决定是否移动矩形或者退出 if keyCode(escapeKey) exitDemo = true; elseif keyCode(leftKey) squareX = squareX - pixelsPerPress; elseif keyCode(rightKey) squareX = squareX + pixelsPerPress; elseif keyCode(upKey) squareY = squareY - pixelsPerPress; elseif keyCode(downKey) squareY = squareY + pixelsPerPress; end % We set bounds to make sure our square doesn‘t go completely off of 设置界限,以确保矩形不会完全移动到屏幕外 % the screen if squareX < 0 squareX = 0; elseif squareX > screenXpixels squareX = screenXpixels; end if squareY < 0 squareY = 0; elseif squareY > screenYpixels squareY = screenYpixels; end % Center the rectangle on the centre of the screen 将矩形移动到新的中心点 centeredRect = CenterRectOnPointd(baseRect, squareX, squareY); % Draw the rect to the screen 绘制 Screen(‘FillRect‘, window, rectColor, centeredRect); % Flip to the screen vbl = Screen(‘Flip‘, window, vbl + (waitframes - 0.5) * ifi); end
4.Rectangle Coordinates Demo: 展示屏幕矩形是如何由其左上角和右下角坐标定义的。用键盘(箭头键)移动矩形,看看坐标是如何变化的。还显示了矩形的中心坐标以供参考
思路:与示例3基本一致,只是多了一个文本来报告点的位置
(1) DrawFormattedText(window,string, x, y,color) 绘制标准化文本 ,参数依次为 窗口指针,字符串,坐标,文本颜色
% We will be drawing some text so here we set the size we want the text to 设置字体大小 % be Screen(‘TextSize‘, window, 30); % The avaliable keys to press 设置按键 escapeKey = KbName(‘ESCAPE‘); upKey = KbName(‘UpArrow‘); downKey = KbName(‘DownArrow‘); leftKey = KbName(‘LeftArrow‘); rightKey = KbName(‘RightArrow‘); % Get the centre coordinate of the window 获取中心点 [xCenter, yCenter] = RectCenter(windowRect); % Make a base Rect of 200 by 300 pixels 设置基础矩形 baseRect = [0 0 200 300]; % Set the color of the rect to red 设置颜色 rectColor = [0.5 0.5 0.5]; % Set the intial position of the square to be in the centre of the screen 设置矩形的初始中心为屏幕中心 squareX = xCenter; squareY = yCenter; % Colors of the dots we will be drawing 设置要绘制的点的颜色 dotColors = [0 1 0; 1 0 0; 0 0 1]; % Set the amount we want our square to move on each button press 设置每次按键的位移量 pixelsPerPress = 10; % Sync us and get a time stamp 时间戳 vbl = Screen(‘Flip‘, window); waitframes = 1; % Maximum priority level 优先级 topPriorityLevel = MaxPriority(window); Priority(topPriorityLevel); % This is the cue which determines whether we exit the demo 判断是否退出demo的cue exitDemo = false; % Loop the animation until the escape key is pressed while exitDemo == false % Check the keyboard to see if a button has been pressed 检测按键 [keyIsDown,secs, keyCode] = KbCheck; % Depending on the button press, either move ths position of the square 判断是否退出或移动矩形 % or exit the demo if keyCode(escapeKey) exitDemo = true; elseif keyCode(leftKey) squareX = squareX - pixelsPerPress; elseif keyCode(rightKey) squareX = squareX + pixelsPerPress; elseif keyCode(upKey) squareY = squareY - pixelsPerPress; elseif keyCode(downKey) squareY = squareY + pixelsPerPress; end % We set bounds to make sure our square doesn‘t go completely off of 设置边界判断,使矩形一点都不会超出屏幕外 % the screen. Here when the srectangles edges hit the screen then it % will not move off the screen at all if squareX < baseRect(3) / 2 squareX = baseRect(3) / 2; elseif squareX > screenXpixels - baseRect(3) / 2 squareX = screenXpixels - baseRect(3) / 2; end if squareY < baseRect(4) / 2 squareY = baseRect(4) / 2; elseif squareY > screenYpixels - baseRect(4) / 2 squareY = screenYpixels - baseRect(4) / 2; end % Center the rectangle on the centre of the screen 调整矩形位置 centeredRect = CenterRectOnPointd(baseRect, squareX, squareY); % Draw the rect to the screen 绘制 Screen(‘FillRect‘, window, rectColor, centeredRect); % Draw dots that show the rects coordinates 画点 dotPositionMatrix = [squareX centeredRect(1) centeredRect(3);... squareY centeredRect(2) centeredRect(4)]; Screen(‘DrawDots‘, window, dotPositionMatrix, 10, dotColors, [], 2); % Draw text in the upper portion of the screen with the default font in 绘制文本 % white line1 = [‘\n Top left corner (red dot): x = ‘ num2str(centeredRect(1))... ‘ y = ‘ num2str(centeredRect(2))]; line2 = [‘\n Bottom Right corner (blue dot): x = ‘ num2str(centeredRect(3))... ‘ y = ‘ num2str(centeredRect(4))]; line3 = [‘\n Rect Centre (green dot): x = ‘ num2str(squareX) ‘ y = ‘ num2str(squareY)]; DrawFormattedText(window, [line1 line2 line3], ‘center‘, 100, [1 1 1]); % Flip to the screen vbl = Screen(‘Flip‘, window, vbl + (waitframes - 0.5) * ifi); end
5.Mouse Contingent Square Demo: 将正方形的位置与鼠标的位置相关联,在矩形内部长按鼠标键以拖动矩形
思路:首先设置基本属性。重点在于鼠标的位置变动量。把“按住键并拖动”(第二帧)与“按住键但还未拖动”(第一帧)这两个状态进行比较,以确定鼠标偏移量,从而确定矩形中心
% Make a base Rect of 200 by 200 pixels baseRect = [0 0 200 200]; % Define red red = [1 0 0]; % Here we set the initial position of the mouse to be in the centre of the 设置鼠标初始位置为屏幕中央 % screen SetMouse(xCenter, yCenter, window); % We now set the squares initial position to the centre of the screen 设置矩形的初始位置 sx = xCenter; sy = yCenter; centeredRect = CenterRectOnPointd(baseRect, sx, sy); % Offset toggle. This determines if the offset between the mouse and centre 便宜切换。这决定了是否设置鼠标与屏幕中心的偏移。用这个来移动方形的位置, % of the square has been set. We use this so that we can move the position 而不必将中心转换到鼠标的位置 % of the square around the screen without it "snapping" its centre to the % position of the mouse offsetSet = 0; % Sync us and get a time stamp vbl = Screen(‘Flip‘, window); waitframes = 1; % Maximum priority level topPriorityLevel = MaxPriority(window); Priority(topPriorityLevel); % Loop the animation until a key is pressed while ~KbCheck % Get the current position of the mouse 获取鼠标位置 [mx, my, buttons] = GetMouse(window); % Find the central position of the square 找到矩形中心点坐标 [cx, cy] = RectCenter(centeredRect); % See if the mouse cursor is inside the square 判断鼠标是够在矩形内 inside = IsInRect(mx, my, centeredRect); % If the mouse cursor is inside the square and a mouse button is being 如果鼠标在矩形内且按了鼠标键且还未设置偏移,这设置偏移量与偏移信号 % pressed and the offset has not been set, set the offset and signal % that it has been set if inside == 1 && sum(buttons) > 0 && offsetSet == 0 dx = mx - cx; dy = my - cy; offsetSet = 1; end % If we are clicking on the square allow its position to be modified by 如果我们点击方形,则通过移动鼠标来调整方形的位置,校正方形中心与鼠标位置的偏移 % moving the mouse, correcting for the offset between the centre of the % square and the mouse position if inside == 1 && sum(buttons) > 0 sx = mx - dx; sy = my - dy; end % Center the rectangle on its new screen position 获取新矩形位置 centeredRect = CenterRectOnPointd(baseRect, sx, sy); % Draw the rect to the screen 绘制矩形 Screen(‘FillRect‘, window, red, centeredRect); % Draw a white dot where the mouse cursor is 绘制鼠标所在位置的白色点 Screen(‘DrawDots‘, window, [mx my], 10, white, [], 2); % Flip to the screen vbl = Screen(‘Flip‘, window, vbl + (waitframes - 0.5) * ifi); % Check to see if the mouse button has been released and if so reset 判断鼠标键是否被放开,并重置偏移信号 % the offset cue if sum(buttons) <= 0 offsetSet = 0; end end
PTBtutorials—Animating basic shapes and dots(2)
原文:https://www.cnblogs.com/zxpsyneuroscience/p/12622897.html