Create a 3D space for random moving dots
Mostra commenti meno recenti
I have a code that animates dots moving in random directions in a 2D space (x and y axis). 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. 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!
PS: The use of the Psychtoolbox is not a necessity, if you have any other solution, I'd be happy to try it out.
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,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'
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
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.
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,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');
16 Commenti
Jan
il 26 Giu 2019
You are using the PsychToolbox, which is a 3rd party tool. Please mention such important details.
What does "the z doesn't appear" mean?
Kahina
il 26 Giu 2019
Jan
il 26 Giu 2019
@Kahina Olafsson: It is still not clear, what the problem is. What does "dots move in a 2D space" mean? Is their z value always 0? What does "computed the z axis" mean?
Kahina
il 26 Giu 2019
KALYAN ACHARJYA
il 26 Giu 2019
Sorry @Kahina Olafsson, for me, it's still unclear.
Walter Roberson
il 26 Giu 2019
As you are using psychtoolbox it is not obvious to us that you have a perspective view that would permit you to observe z differences. If you have a situation where a point with a smaller z is on top of a point with a higher z then that would be a psychtoolbox issue.
Kahina
il 26 Giu 2019
Jan
il 26 Giu 2019
@Kahina: I have asked some specific questions already, e.g. what "dots move in a 2D space" mean. Here an example of what might be meant:
t = 1:10
x = sin(t ./ 10);
y = cos(t ./ 10);
z = zeros(size(x));
This describes a situation, in which x and y coordinates are moving, while z is fixed. If I explain, that x,y,z are the 3D coordinates of a dot, the above code can be understood as "dots move in a 2D space".
But perhaps z is not fixed and you do not talk about some code, but you have a visualization already. If the view position is in the Z-direction and you have an orthographic projection, you do have a motion in 3D, but you do not see it due to the projection.
So are you talking about the corrdinates, or about an animation?
Explain, what you observe and not what happens internally. "dots move in a 2D space" is an interpretation of something, you see on the screen, in the code, in the workspace browser. But this can be a misinterpretation, so we need to know, what you observe with which tool.
Walter Roberson
il 26 Giu 2019
psychtoolbox uses its own graphics routines that might default to being a view from above. For a range of distances and relative sizes it can become difficult to tell that there is z difference, and potentially impossible for othographic projections.
MATLAB defaults 3d plots to be viewed from an angle that makes it easier to tell that points are different z.
Kahina
il 26 Giu 2019
Walter Roberson
il 26 Giu 2019
You can use plots and write to videos file if you do not need real-time video generation.
Bjorn Gustavsson
il 26 Giu 2019
Modificato: Bjorn Gustavsson
il 26 Giu 2019
If you want to change the background color of a figure you can use:
whitebg([0 0 0])
That should make the background color black, and you can then use standard plot3 calls, or scatter3 if you want easy controll of the dot colour...
Your problem seems to be made worse with the psyco-toolbox interface, it should be rather simple:
for i1 = 1:n,
plot3(x,y,z,'w.','markersize',23)
view(23,34)
axis([-1 sX+1,-1 sY+1, -1 sZ+1])
grid on
set(gca,'projection','perspective')
% additional decorations
M(i1) = getframe(gca);
% update x y and z
end
...with obvious replacements for you to style it out.
Kahina
il 27 Giu 2019
Bjorn Gustavsson
il 27 Giu 2019
Oh, you want to get a 3-D feeling when looking at your figure. That is another task altogether.
You might get a bit of a feel for 3-D motion if you do change the size depending on distance from your eye. I would still do that with plain matlab-coding, the trick would be to calculate size depending on distance from your eye, the angular diameter of your dots would decrease as
, where l is distance from your eye. The question is how to properly scale the distance from the nearest to the farthes point relative to the distance between the screen and your eye. My guess is that you should try for dimensions close to reality, perhaps 0.4 m from eye to screen, and another .15 m from nearest to farthest corner of your cube. It "seems reasonable" that our visual perception would handle such a setting better than some completely different ratio.
The reason I write eye and not eyes is obviously that since you will only plot the points in one figure at the physical screen surface, and at that distance objects are close enough that we determine 3-D position from paralax. Because of that your eyes might actually be too clever to be fooled by your size-variation technique, they might see the points and determine by stereoscopic triangulation that they are at the screen-surface and simply interpret the size-variation as just that, The 3-D illusion might have a bigger chans if you only look with one eye. The ideal way to go about this would be to use one frame for the left eye and another frame for the right eye and then use VR-techniques to display the sequence - once uppon a time I worked with a SGI Onyx where you could separate frames for the left/right eyes with polarization and it worked really well.
Risposte (0)
Categorie
Scopri di più su Image display and manipulation in Centro assistenza e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!