为沿给定方向移动的点创建 3D 空间

为沿给定方向移动的点创建 3D 空间

我编写了一个代码,用于使沿特定方向移动的二维点动起来。我尝试使用球面坐标创建一个三维空间,为此我使用了两次仅接受二维坐标的 psychtoolbox 函数 Screen('DrawDots') - 所以我首先将它用于 X 和 Y,然后用于 X 和 Z,但它没有给出正确的三维感知。因此我改用 moglDrawDots3D,因为它接受三维坐标 XYZ,但点会出现和消失,而不是全部沿给定方向移动。我不知道原因。我对 Matlab 和动画非常陌生,我将非常感激您的反馈和见解。为了清楚起见,我尝试在下面逐步解释我的代码。提前感谢您的帮助!

附言:如果您不了解 Psychtoolbox 但可以使用其他方法提出解决方案,请这样做。

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*

首先,我在光圈内为每个点定义了一个随机位置。“dots.x”和“dots.y”将保存每个点的 x 和 y 位置。

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); 

然后我使用创建的函数“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.

% 这将生成像素位置,但它们的中心是 [0,0],即左上角

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.

我为动画定义了一些时间和运动参数

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

我通过使用球坐标确定 x、y 和 z 位置,然后求它们的导数,计算出点行进的距离。

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);

我尝试通过计算光圈的左、右、上、下和深度(前后)(以度为单位)来将点放入光圈内

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;

新的随机起始位置

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);

让点移动

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)+ 150;   

我评论了我以前使用过的功能屏幕绘制点。

% 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);

我用 moglDrawDots3D 替换了 Screen DrawDots

    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 one aperture
    %width.
    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');

相关内容