[英]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.