Create a 3D space

11 ビュー (過去 30 日間)
Kahina
Kahina 2019 年 6 月 19 日
編集済み: Kahina 2019 年 6 月 19 日
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 件)

カテゴリ

Help Center および File ExchangeTiming and presenting 2D and 3D stimuli についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by