Create a 3D space
11 views (last 30 days)
Show older comments
I have written a code that animates 2d dots moving in a certain direction. I tried to create a 3rd dimension using spherical coordinates, and for that I used two times the psychtoolbox function Screen(‘DrawDots’)that takes only 2D coordinates - so I used it first for X and Y and then for X and Z, but it does not give a proper 3D perception. Therefore I used moglDrawDots3D instead, as it takes 3d coordinates XYZ, but the dots appear and disappear instead of moving all in a given direction. I have no clue on the cause. I am very new to Matlab and animations, I'd be very grateful to get your feedback and insight. I tried to explain my code step by step below for the sake of clarity. Thank you in advance for your help!
InitializeMatlabOpenGL;
dots.nDots = 100; % number of dots
dots.color = [255,255,255]; % color of the dots
dots.size = 10; % size of dots (pixels)
dots.center = [0,0,0]; % center of the field of dots (x,y,z)
dots.apertureSize = [12,12,60]; % size of rectangular aperture [w,h,depth] in degrees
First, I defined a random position within the aperture for each of the dots. 'dots.x' and 'dots.y' will hold the x and y positions for each dot.
dots.x = (rand(1,dots.nDots))*dots.apertureSize(1) + dots.center(1); %'rand(dots.nDots,1)' generates a vector dots.nDots long of random numbers between 0 and 1.
dots.y = (rand(1,dots.nDots))*dots.apertureSize(2) + dots.center(2); % To change that range to fit the aperture we multiply them by the aperture size, and add the center offset.
dots.z = (rand(1,dots.nDots))*dots.apertureSize(3) + dots.center(3);
Then I converted these dot positions from a visual angle into pixel coordinates using a created function 'angle2pix'
tmp = Screen('Resolution',0); % (1) Screen's 'Resolution' function determine the screen resolution.
display.resolution = [tmp.width,tmp.height];
display.width = 30; % (2) Width of the screen in cm (with a ruler).
display.dist = 50; % (3) Distance of the screen from the observer in cm.
% This generates pixel positions, but they're centered at [0,0], which is the top left corner
pixpos.x = angle2pix(display,dots.x); % Convert the x position of the dots from visual angle to pixel.
pixpos.y = angle2pix(display,dots.y); % Convert the y position of the dots from visual angle to pixel.
pixpos.z = angle2pix(display,dots.z); % Convert the z position of the dots from visual angle to pixel.
I defined some timing and motion parameters for the animation
dots.speed = 3; %degrees/second
dots.duration = 5; %seconds
dots.theta_deg = 30; %degrees
dots.phi_deg = 100; %degrees
dots.theta_rad = dots.theta_deg * pi /180; % direction converted to radians
dots.phi_rad = dots.phi_deg * pi /180; % direction converted to radians
I calculated the distance travelled by the dot, by determining the x,y and z positions using spherical coordinates and then their derivate.
dx = dots.speed* sin(-dots.phi_rad-dots.theta_rad)/display.frameRate;
dy = -dots.speed* cos(dots.phi_rad + dots.theta_rad)/display.frameRate;
dz = -dots.speed*cos(dots.theta_rad)/display.frameRate;
The total number of frames for the animation is determined by the duration (seconds) multiplied by the frame rate (frames/second). The function secs2frames performs the calculation
nFrames = secs2frames(display,dots.duration);
I try to fit the dots within the aperture by calculating the left, right top, bottom and depth(forward and backward) of the aperture (in degrees)
l = dots.center(1)-dots.apertureSize(1)/2;
r = dots.center(1)+dots.apertureSize(1)/2;
b = dots.center(2)-dots.apertureSize(2)/2;
t = dots.center(2)+dots.apertureSize(2)/2;
d_forward = dots.center(3)- dots.apertureSize(3)/2;
d_backward = dots.center(3)+ dots.apertureSize(3)/2;
New random starting positions
dots.x = (rand(1,dots.nDots))*dots.apertureSize(1) + dots.center(1);
dots.y = (rand(1,dots.nDots))*dots.apertureSize(2) + dots.center(2);
dots.z = (rand(1,dots.nDots))*dots.apertureSize(3) + dots.center(3);
Make the dots move
try
for i=1:nFrames
%convert from degrees to screen pixels
pixpos.x = angle2pix(display,dots.x)+ display.resolution(1)/2;
pixpos.y = angle2pix(display,dots.y)+ display.resolution(2)/2;
pixpos.z = angle2pix(display,dots.z)+ display.resolution(2)/2;
I commented the function screen drawdots that I previously used.
% Screen('DrawDots',display.windowPtr,[pixpos.x;pixpos.y], dots.size, dots.color,[0,0],1);
% Screen('DrawDots',display.windowPtr,[pixpos.x;pixpos.z], dots.size, dots.color,[0,0],1);
I replaced Screen DrawDots with moglDrawDots3D
moglDrawDots3D(display.windowPtr, [pixpos.x;pixpos.y;pixpos.z],dots.size, dots.color, dots.center);
%update the dot position
dots.x = dots.x + dx;
dots.y = dots.y + dy;
dots.z = dots.z + dz;
%move the dots that are outside the aperture back on aperture
dots.x(dots.x<l) = dots.x(dots.x<l) + dots.apertureSize(1);
dots.x(dots.x>r) = dots.x(dots.x>r) - dots.apertureSize(1);
dots.y(dots.y<b) = dots.y(dots.y<b) + dots.apertureSize(2);
dots.y(dots.y>t) = dots.y(dots.y>t) - dots.apertureSize(2);
dots.z(dots.z<d_forward) = dots.z(dots.z<d_forward) + dots.apertureSize(3);
dots.z(dots.z>d_backward) = dots.z(dots.z>d_backward) -dots.apertureSize(3);
Screen('Flip',display.windowPtr);
end
catch ME
Screen('CloseAll');
rethrow(ME)
end
Screen('CloseAll');
0 Comments
Answers (0)
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!