Plotting many spheres in 3D real time

8 views (last 30 days)
Dan Fitzgerald
Dan Fitzgerald on 4 May 2014
Commented: Dan Fitzgerald on 4 May 2014
I am simulating particles in 3D and want to visualize them in real time with a GUI. Right now I'm using a scatter3 to visualize them, but I want a more accurate representation of their sizes and scatter only has markers in pixels. I want to plot each particle as a sphere, but I can't find a way to quickly plot many spheres in different positions. For N particles I have a 3xn matrix, handles.particles , for the 3D positions of the spheres. I want to plot them on the axis handles.simDisplay (there are other axis on the GUI that should not be changed.)
Right now the relevant code in my update timer is
[handles.SphereX,handles.SphereY,handles.SphereZ] = sphere;
subplot(handles.simDisplay); %plot on the correct axis
set(gcf, 'CurrentAxes', handles.simDisplay);%set the axis (does this even do anything?)
for i=1:handles.nParticles
surf(handles.SphereX+handles.particles(i,1),...
handles.SphereY+handles.particles(i,2),...
handles.SphereZ+handles.particles(i,3));
end
This is easy but very slow. It also does not clear previously drawn spheres. Any suggestions?

Answers (1)

Jan
Jan on 4 May 2014
Replace
subplot(handles.simDisplay); %plot on the correct axis
set(gcf, 'CurrentAxes', handles.simDisplay);
by
axes(handles.simDisplay);
Reduce the number of patches:
[X, Y, Z] = sphere(16);
If you mention "clear previously drawn spheres", it would be faster, not to clear them, but to adjust their position:
axes('NextPlot', 'add');
[X, Y, Z] = sphere(16);
tic
OldH = [];
for k = 1:100
H = surf(X + rand, Y + rand, Z + rand);
if ~isempty(OldH)
delete(OldH);
end
drawnow;
OldH = H;
end
toc
tic
H = surf(X, Y, Z);
for k = 1:100
set(H, 'XData', X + rand, 'YData', Y + rand, 'ZData', Z + rand);
drawnow;
end
toc
Elapsed time is 2.662571 seconds.
Elapsed time is 0.780100 seconds.
  2 Comments
Dan Fitzgerald
Dan Fitzgerald on 4 May 2014
Edited: Dan Fitzgerald on 4 May 2014
By "clear previously drawn spheres" I mean that spheres from the last render update remain when the current update starts drawing. Updated spheres are drawn with all previous versions already there, resulting in particle "steaks" since all the positions every particle ever occupied is still shown.
I tried the setting approach, but the problem is that draw now will clear the sphere that was just drawn in the previous loop, so only one will be shown at a time, and the performance hit from draw now on every loop is huge. With my original method I could get about a frame every four seconds with 1000 spheres/particles. With the above method I can watch it flash all 100 spheres one at a time over about 20-30 seconds.
Dan Fitzgerald
Dan Fitzgerald on 4 May 2014
I tried using the setting approach, but with an array of graphics objects (surf handles), one for for each sphere. It has about the same performance as drawing new spheres each frame, but I feel like it might be vectorizable.
for i=1:handles.nParticles
set(handles.sphereSurfHandles(i),...
'XData',handles.SphereX+handles.particles(i,1),...
'YData',handles.SphereY+handles.particles(i,2),...
'ZData',handles.SphereZ+handles.particles(i,3));
end
Any potential optimizations?

Sign in to comment.

Categories

Find more on Graphics Performance in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!