简体   繁体   English

无法为 2D 点动画创建第 3 维

[英]Failed to create a 3rd dimension to 2D dots animation

I have a code that animates dots moving in random directions in a 2D space (x and y axis).我有一个代码可以为在 2D 空间(x 和 y 轴)中随机方向移动的点设置动画。 I tried to create a 3rd dimension (z axis) using spherical coordinates In order to draw and display the dots in a 3D space, I used the Psychtoolbox function moglDrawDots3D, as it takes 3d coordinates XYZ, but I am still getting a 2D animation, the dots on the z don't appear.我尝试使用球坐标创建第 3 维(z 轴)为了在 3D 空间中绘制和显示点,我使用了 Psychtoolbox 函数 moglDrawDots3D,因为它需要 3d 坐标 XYZ,但我仍然得到 2D 动画, z 上的点没有出现。 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.我对 Matlab 和动画很陌生,如果能得到您的反馈和见解,我将不胜感激。 I tried to explain my code step by step below for the sake of clarity.为了清楚起见,我试图在下面逐步解释我的代码。 Thank you in advance for your help!预先感谢您的帮助!

PS: The use of the Psychtoolbox is not a necessity, if you have any other solution, I'd be happy to try it out. PS:Psychtoolbox 的使用不是必须的,如果您有其他解决方案,我很乐意尝试。

AssertOpenGL;
InitializeMatlabOpenGL;
display = OpenWindow()
dots.nDots = 531;                       % 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 = [50.8,28.5,50.8];   % size of rectangular aperture [w,h,depth] in degrees

First, 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' 和 'dots.y' 将保存每个点的 x 和 y 位置。

[dots.x,dots.y,dots.z] = CreateUniformDotsIn3DFrustum(dots.nDots, 25, 1/screen_ratio, 0.1, 100);  

Then I converted these dot positions from a visual angle into pixel coordinates using a created function 'angle2pix'然后我使用创建的函数“angle2pix”将这些点位置从视角转换为像素坐标

tmp = Screen('Resolution',0);                       % (1) Screen's 'Resolution' function determine the screen resolution.
display.resolution = [tmp.width,tmp.height];
display.width = 50.8;                               % (2) Width of the screen in cm.
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这会生成像素位置,但它们以 [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 = ones(1, dots.nDots) * -1;               

I defined some timing and motion parameters for the animation我为动画定义了一些时间和运动参数

dots.speed = 3;                             % degrees/second
dots.duration = 10;                         % seconds                                                         
dots.theta_deg = randi(360,1,dots.nDots);   % degrees 
dots.phi_deg = 30;                          % 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.我通过使用球坐标确定 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; 

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)我尝试通过计算光圈的左、右顶部、底部和深度(向前和向后)(以度为单位)来拟合光圈内的点

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函数 secs2frames 执行计算

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;

New random starting positions新的随机起始位置

[dots.x,dots.y,dots.z] = CreateUniformDotsIn3DFrustum(dots.nDots, 25, 1/screen_ratio, 0.1, 100);   

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 = ones(1, dots.nDots) * -1;

        moglDrawDots3D(display.windowPtr, [pixpos.x;pixpos.y;pixpos.z],dots.size, dots.color, dots.center,1);

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

You asked for a suggestion on how to do this differently, so here's a demonstration of a simple 3D animation:您询问了有关如何以不同方式执行此操作的建议,因此这是一个简单 3D 动画的演示:

function q56758294
%% Generate some data
N_OBJS = 20;
P = rand(N_OBJS,3) .* ones(1,1,3);

%% Create the figure
figure(); 
hP(1) = plot3(P(:,1,1), P(:,2,1), P(:,3,1), 's', 'Color', [0 0 0]+0.8); hold on;
hP(2) = plot3(P(:,1,2), P(:,2,2), P(:,3,2), 's', 'Color', [0 0 0]+0.6);
hP(3) = plot3(P(:,1,3), P(:,2,3), P(:,3,3), 's', 'Color', [0 0 0]);
AX_LIMS = [-1 1]*3;
drawnow; set(gca, 'XLim', AX_LIMS, 'YLim', AX_LIMS, 'ZLim', AX_LIMS); grid on;

%% Animate:
FPS = 12;
for ind1 = 1:500
  % Update coordinates:
  dP = randn(N_OBJS,3)*0.1;
  P(:,:,1) = P(:,:,2);
  P(:,:,2) = P(:,:,3);
  P(:,:,3) = P(:,:,3) + dP;
  
  % Update plot objects:
  for ind2 = 1:3
    set( hP(ind2), 'XData', P(:,1,ind2), 'YData', P(:,2,ind2), 'ZData', P(:,3,ind2) );
  end
  
  pause(FPS^-1);
end

Which results in:结果是:

在此处输入图片说明


If you want white circles on a black background, replace the figure creation code with the following:如果您想要黑色背景上的白色圆圈,请将图形创建代码替换为以下内容:

figure('Color', 'k'); 
hP(1) = plot3(P(:,1,1), P(:,2,1), P(:,3,1), '.', 'Color', [0 0 0]+0.2, 'MarkerSize', 20); hold on;
hP(2) = plot3(P(:,1,2), P(:,2,2), P(:,3,2), '.', 'Color', [0 0 0]+0.4, 'MarkerSize', 20);
hP(3) = plot3(P(:,1,3), P(:,2,3), P(:,3,3), '.', 'Color', [0 0 0]+1.0, 'MarkerSize', 20);
AX_LIMS = [-1 1]*3;
drawnow; set(gca, 'XLim', AX_LIMS, 'YLim', AX_LIMS, 'ZLim', AX_LIMS, 'Color', 'k',...
  'XColor', 'k', 'YColor', 'k', 'ZColor', 'k');

Which then results in:然后导致:

在此处输入图片说明


To export a plot as a movie file, you would need to use getframe inside the loop, and then use VideoWriter as explained in this example .要将绘图导出为电影文件,您需要在循环内使用getframe ,然后按照本示例中的说明使用VideoWriter

Also, I've added the "trails" for aesthetic purposes, but these are easy to remove if you don't need them.此外,出于审美目的,我添加了“轨迹”,但如果您不需要它们,它们很容易删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM