Clipping Surface Plots When Plotting Large Volumes

I am curious if anyone has experienced something like this before. I know that Matlab has various clipping options and I have played with those with no success. I am trying to create some graphics that include a fairly large plotting volume but want to zoom in on small features within that volume. What I am experiencing is once the objects at the extremes of the volumes are far enough apart from the origin of the plot, the plot starts to clip the graphic at the origin that I am interested in looking at, sometlimes clipping it out entirely. I have created a piece of sample code below that demonstrates this issue on my machine. I hope it isn't machine-specific and can be replicated on yours. Any assistance would be much appreciated.
clc; clear all; close all;
set(gcf,'renderer','opengl')
%generate test points
[theta phi]=meshgrid(-180:10:180,-180:10:180);
[a b]=size(theta);
iter=1;
pts(a*b,3)=0;
for i=1:a
for j=1:b
[x y z]=sph2cart(theta(i,j)*pi/180,phi(i,j)*pi/180,1);
pts(iter,:)=[x y z];
iter=iter+1;
end
end
[x y z]=sphere(30);
%define initial figure properties
figure(1)
set(gcf,'OuterPosition',[100 100 500 500],'Color','Black');
figureh=gcf;
axesh=gca;
set(axesh,'Parent',figureh);
set(gca,'Clipping','off','ClippingStyle','rectangle');
set(gcf,'Clipping','off');
xlim([-inf inf]);
ylim([-inf inf]);
zlim([-inf inf]);
axis off;
shading flat;
hold on;
p2=plot3(pts(:,1),pts(:,2),pts(:,3),'r.','Parent',axesh,'Clipping','off');
p1=surf(x,y,z,'EdgeColor','None','FaceColor',[.5 .5 .5],'Parent',axesh,'Clipping','off');
hold off;
light;
material dull;
cameratoolbar;
camproj perspective;
camva(120);
campos('manual');
campos([0.7997 -1.1424 1.0343]);
camtarget([1 0 .5]);
camup([0 0 1]);
% change the scalaar (50) to higher values to see total clipping of sphere
p2.XData=p2.XData*500;
p2.YData=p2.YData*500;
p2.ZData=p2.ZData*500;
drawnow;

5 Comments

A few fuzzy areas...
1) is your code supposed to generate the image you shared because it doesn't show the gray sphere at all after changing the p2 data.
2) "What I am experiencing is once the objects at the extremes of the volumes are far enough apart from the origin of the plot, the plot starts to clip the graphic at the origin that I am interested in looking at, sometlimes clipping it out entirely." I lose you at the underlined part. The origin is (0,0,0). Even if I restate the sentence as "..the plot starts to clip the graphic at the section that I am interested in...", it still doesn't make sense to me.
3) What exactly is the problem? Is the problem that the gray sphere disappears?
Due to the projection, camera angles, etc, it's difficult to guess what the goal is and what is preventing you from achieving that goal. If the problem is that the gray sphere disappears, that's easy to explain.
My apologies for going so long without responding!
1) Yes. If I change the "500" scalar located near the end to 50. I am able to recreate the exact image seen above. To give you a better sense of what I am seeing, if I change the radius of the spherical coordinates to progressively larger values (5, 25, and 125) without changing the camera settings, the clipping behavior appears and gets worse and worse as r increases. Images below.
R=5
R=25
R=125
2) Sorry for the confusion. Perhaps reworded a little: given a static camera position, view angle etc, as I center the camera at an object at 0,0,0, that object will start being clipped as objects in the background move further and further away (there is a certain threshold where it starts to happen, it isn't a constant thing). So for example, if you wanted to render a scene of the Earth and Moon, the view of the moon from the Earth would look fine until you include a far away object like the sun at which point it would start to clip the moon surface object.
3) That is correct. The sphere getting clipped and disappearing is this issue.
It is almost like the clipping plane is moving in FRONT of the camera as the volume of the renderred region increases.
Ah... I see. The sphere is expanding outside of the frustum. I'm not at my laptop at the moment but I will reply with an answer tomorrow unless someone else beats me to it.
Copy. Thank you for taking the time to look again. It would probably help a lot if I knew enough about renderring to accurately describe the issue! :-)
It may be beneficial to see if there is any way to issue camera settings directly to the opengl via Matlab. I have found a toolbox that claims to be able to do so and am digging through it now.
https://en.wikipedia.org/wiki/Psychtoolbox_for_MATLAB

Sign in to comment.

Answers (1)

TL;DR: When the coordinates for the red-dotted sphere are expanded, the axis limits are updated. The new x-axis limits clip the sphere because the x-coordinate of the camera is within the range of x-coordinates of the sphere.
Solution: Either reset the x-axis limit after exansion or change the camera position.
Furthre reading: Scratchapixel is my go-to site for graphics, projection geometry, etc. This site came in handy for me when I was learning (still am learning) OpenGL.
Illustrating the problem
Generate the base figure before setting camera properties and before expanding the red-dot sphere. I've commented-out irrelevant lines of code and cleaned up some other sections where I've left comments.
% set(gcf,'renderer','opengl')
%generate test points % I REPLACED YOUR FOR-LOOPS
[theta phi]=meshgrid(-180:10:180,-180:10:180);
[x y z]=sph2cart(theta*pi/180,phi*pi/180,1);
pts = [x(:), y(:), z(:)];
[x y z]=sphere(30);
%define initial figure properties
figureh = figure(1); % ADDED FIG HANDLE OUTPUT
set(figureh,'Color','Black'); % REMOVED OUTERPOSITION PROPERTY; USE FIG HANDLE
% figureh=gcf;
% axesh=gca;
% set(axesh,'Parent',figureh);
axesh = axes(figureh); % CLEANER AND SIMPLER THAN ABOVE
set(axesh,'Clipping','off','ClippingStyle','rectangle'); % USE AX HANDLE
set(figureh,'Clipping','off'); % USE FIG HANDLE
% xlim([-inf inf]); % THIS DOES NOTHING
% ylim([-inf inf]); % THIS DOES NOTHING
% zlim([-inf inf]); % THIS DOES NOTHING
axis off;
shading flat;
hold on;
p2=plot3(pts(:,1),pts(:,2),pts(:,3),'r.','Parent',axesh,'Clipping','off');
p1=surf(x,y,z,'EdgeColor','None','FaceColor',[.5 .5 .5],'Parent',axesh,'Clipping','off');
axis equal % ADDED
% hold off;
light;
material dull;
% cameratoolbar;
To illustrate the desired camera position and target, I've added a blue square and yellow cross respectively. I've also added a YZ plane at the camera's x-location to show the camera's position relative to the sphere. This shows the camera's future position and target.
plot3(1, 0, .5, 'y+','LineWidth',2,'MarkerSize', 10)
plot3(0.7997, -1.1424, 1.0343, 'cs','LineWidth',2,'MarkerSize', 10)
patch(0.7997*[1,1,1,1],[-1 -1 1 1], [-1 1, 1 -1], 'w','FaceAlpha', .8)
view(33,33) % to show the other side of the plane
Now move the camera and examine the axis limits before expanding the red sphere.
view(3) % ADDED
camproj perspective;
camva(120);
% campos('manual'); % REDUNDANT
campos([0.7997 -1.1424 1.0343]);
camtarget([1 0 .5]);
camup([0 0 1]);
xl = xlim % = [-1 1]
yl = ylim % = [-1.1424 1]
zl = zlim % = [-1 1.0343]
Now expand the red sphere and examine the axis limits again.
p2.XData=p2.XData*25;
p2.YData=p2.YData*25;
p2.ZData=p2.ZData*25;
% drawnow;
xlim % = [-25 25]
ylim % = [-25 25]
zlim % = [-25 25]
Return the axis limits to their original values before expansion.
xlim(xl)
ylim(yl)
zlim(zl)
Alternatively, move the camera position back a bit,
axesh.CameraPosition(1) = 1;

7 Comments

What happens when you increase the gain by a few orders of magnitude to something like 2500? At that point the entire point cloud disappears and I can't get it to rerender even after increasing the axes limits.
p2.XData=p2.XData*25;
p2.YData=p2.YData*25;
p2.ZData=p2.ZData*25;
Does that happen after you've made any changes to your code based off of my answer?
> What happens when you increase the gain by a few orders of magnitude to something like 2500? At that point the entire point cloud disappears and I can't get it to rerender even after increasing the axes limits.
Think about what the code is doing, line-by-line, section-by-section. Here's the first section before setting camera properties and before expanding the red-dotted sphere. Look at the axis limits. They are all basically [-1,1].
[theta phi]=meshgrid(-180:10:180,-180:10:180);
[x y z]=sph2cart(theta*pi/180,phi*pi/180,1);
pts = [x(:), y(:), z(:)];
[x y z]=sphere(30);
figureh = figure(1);
% set(figureh,'Color','Black'); % LETS LEAVE THE FIG WHITE FOR THIS DEMO
axesh = axes(figureh);
set(axesh,'Clipping','off','ClippingStyle','rectangle');
set(figureh,'Clipping','off');
% axis off; % LET"S LEAVE THE AXES ON FOR THIS DEMO
shading flat;
hold on;
p2=plot3(pts(:,1),pts(:,2),pts(:,3),'r.','Parent',axesh,'Clipping','off');
p1=surf(x,y,z,'EdgeColor','None','FaceColor',[.5 .5 .5],'Parent',axesh,'Clipping','off');
axis equal
light;
material dull;
plot3(1, 0, .5, 'y+','LineWidth',2,'MarkerSize', 10)
plot3(0.7997, -1.1424, 1.0343, 'cs','LineWidth',2,'MarkerSize', 10)
patch(0.7997*[1,1,1,1],[-1 -1 1 1], [-1 1, 1 -1], 'w','FaceAlpha', .8)
view(33,33) % to show the other side of the plane
view(3)
Now, store the original axis limits and expand the red-dot sphere by a factor of 2500. It looks like the gray sphere is gone but look at the updated axis limits. They are all wider than [-2000,2000] while the inside sphere still has a diameter of 2 making it very small, too small to see. But you can still see the camera marker (cyan square) and camera target (yellow cross).
xl = xlim;
yl = ylim;
zl = zlim;
g = 2500;
p2.XData=p2.XData*g;
p2.YData=p2.YData*g;
p2.ZData=p2.ZData*g;
If you return the original axis limits that worked in my previous answer, you'll see the gray sphere but you will no longer see the very-much-larger red sphere because the axis limits are all within the red sphere space.
xlim(xl)
ylim(yl)
zlim(zl)
None of this should be surprising. Furthermore, given your camera angle and target, the bounds of the image are very sensitive to your axis limits (or vise-versa: given you axis limits, the bounds of the image are very sensitive to the camera position & target).
To demonstrate this, I've increased the number of red dots using [theta,phi]=meshgrid(-180:1:180,-180:1:180) and manually zoomed into the center and manually rotated so that the target (blue cross) and camera position (cyan square) are aligned. This was done before setting the camera position & target. This shows the line of sight of the camera. Depending on your final axis limits, you could be staring at an empty space and completely miss both the gray sphere and all of the red dots. Moving forward, it would be helpful to review what a "viewing frustum" is. The link I provided in my answer is a great starting point.
I understand what you are doing with this code but in the example above I think you are able to retain all of the feaures because you are using ortho projection, not perspective.
Perhaps let us try a simpler scenario that is slightly closer to the desired end application. In this example I am plotting the earth and putting the camera just above the earth surface but still experience clipping. In this scenerio, I want the near-field clipping plane of the frustrum to essentially be co-located with the camera so there will be zero clipping but for the life of me I still don't understand why this doesn't work.
Hopefully this is a simpler and more incrimental approach to solving the probelm.
clc; clear all; close all;
g=6350;
[x y z]=sphere(90);
%configure figure and axes propergies
figureh = figure(1);
axesh = axes(figureh);
set(axesh,'Clipping','off','ClippingStyle','rectangle'); % USE AX HANDLE
set(figureh,'Clipping','off');
axis off; hold on; axis equal;
%import texturemap and render
im=imread('https://cdn11.bigcommerce.com/s-5luen2shhj/images/stencil/original/products/151/414/physical_earth_satellite_image_mural_lg__85186.1560352839.jpg?c=2&imbypass=on&imbypass=on');
earth=warp(x*g,y*g,z*g,rot90(rot90(im)));
set(earth,'Clipping','off');
%configure camera
camproj perspective;
campos([g+100 0 0]);
camtarget([0 0 g]);
camva(60);
cameratoolbar;
axis equal; axis off;
axesh.XLim=[-9999 9999];
axesh.YLim=[-9999 9999];
axesh.ZLim=[-9999 9999];
%display axes limits to ensure all are greater than earth radius
xlim
ylim
zlim
norm(campos) %get camera distance from center of earth to make sure it is postioned >6350 km away from center
The position of the camera and target and shown in the plot below along with the line of sight of the camera. The code was copied from your comments above with the exception of lines where I've added comments.
g=6350;
[x y z]=sphere(90);
figureh = figure();
axesh = axes(figureh);
set(axesh,'Clipping','off','ClippingStyle','rectangle');
set(figureh,'Clipping','off');
axis off; hold on; axis equal;
im=imread('https://cdn11.bigcommerce.com/s-5luen2shhj/images/stencil/original/products/151/414/physical_earth_satellite_image_mural_lg__85186.1560352839.jpg?c=2&imbypass=on&imbypass=on');
earth=warp(x*g,y*g,z*g,rot90(rot90(im)));
set(earth,'Clipping','off');
cpos = [g+100 0 0]; % SPECIFY CAMERA POSITION
ctarg = [0 0 g]; % SPECIFY CAMERA TARGET
box on % VIEW AXES BOX
grid on % VIEW GRID
xlabel('x'); ylabel('y'); zlabel('z') % VIEW AXES LABELS
axis on % VIEW AXES
plot3(cpos(1), cpos(2), cpos(3), 'bs',... % SHOW CAM POSITION
'markersize', 12, 'linewidth', 3, ...
'DisplayName', 'CamPos')
plot3(ctarg(1), ctarg(2), ctarg(3), 'm*', ... % SHOW CAM TARGET
'markersize', 12, 'linewidth', 3, ...
'DisplayName', 'CamTarget')
plot3([cpos(1);ctarg(1)],[cpos(2);ctarg(2)], ... % SHOW LINE OF SIGHT
[cpos(3);ctarg(3)], 'y--', 'LineWidth', 3, ...
'DisplayName','LineOfSight')
legend('location','bestoutside') % ADD LEGEND
view(10,35) % VIEW ADDED MARKERS
alpha(.6) % ADD TRANSPARENCY TO SEE LINE OF SIGHT
It appears that you'd like to point the camera down upon earth at a very close distance to earth's surface. Just to see the viewing angle head-on, I've set the viewing angle and zoomed in a bit below. You can see the underlying axes with orthographic projection and since the earth is partially transparent, you can see the other side of the earth.
view(90, -45)
xlim([3624.7 6810.5])
ylim([-1242.9 1269.7])
zlim([-1243.5 1269.2])
However, when you apply your camera and axes properties, the earth is clipped an you see the other side of the earth. The reason why is 1) the near clipping plane cuts into the earth and 2) your axis limits contain the other side of the earth. I don't know enough about how openGL is applied to Matlab graphics to provide a more technical answer but hopefully my rinky dink drawing below will illustrate my explanation. The red outline is the (poorly drawn) frustum laying along the XZ axis (not to scale).
One way to fix this is the restrict the axis limits to elimiate the "other side" of the earth. For example, the camera target x-coordinate is 0 so the lower x-axis-limit can be set to 0 which solves the problem.
Continuing from the first block of code above,
camproj perspective;
campos(cpos);
camtarget(ctarg);
camva(60);
cameratoolbar;
alpha(1) % REMOVE TRANSPARENCY
axesh.XLim(1) = 0; % SPECIFY AXIS LIMS
Okay. I am able to change the xlimits as you show by why does changing the -x side limit help with clipping on the +x side of the sphere? It is nice that it works but that doesn't make any sense to me at all.
Simlarly, if I execute the following at the end of the script, I would think that it would clip much of the globe but it doesn't.
axesh.XLim(1) = 7000; % SPECIFY AXIS LIMS
axesh.XLim(2) = 9999; % SPECIFY AXIS LIMS
What motivated me to change the lower access limit was to eliminate seeing the far side of Earth but I don't know why that changes the near clipping plane.
I've worked with perspective projections in the past but have never thoroughly investigated it's implementation in matlab.
Perhaps these links may be helpful and if you ever get to the bottom of it, I'd love to hear what you find.

Sign in to comment.

Products

Release

R2018b

Asked:

on 17 May 2021

Edited:

on 29 Sep 2021

Community Treasure Hunt

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

Start Hunting!