%Perspective.m
%This program paints copies of a photo on three
%sides of a cube using a perspective projection.
%It is important to know that this program has
%been designed to emphasize the mathematics we have
%been discussing and it does not use MATLAB's
%built-in tools for rendering three dimensional objects.
%Readers who are knowledgeable about MATLAB or
%another programming language may wish to
%design a more efficient program.
%Although a z-buffer is not needed for this particular
%object, one is included in order to make the
%program more easily adaptable.
%In the first line the photo is read into memory.
%The word 'infile' should be replaced by the
%filename of your image file which must be stored
%in the current directory. Next, we find the
%dimensions of the input photo. We also find the
%edge size to make a square.
inpic = imread('infile');
row = size(inpic,1);
col = size(inpic,2);
s = min(row,col);
%In the following lines we fix the coordinates of the viewer's eye
%and fix the viewing plane. The
%values are somewhat arbitrary and you should experiment to get a good effect.
a = 4*row;
b = 2*col;
c = 2*row; %(a,b,c) is the position of the viewer's eye.
d = row; %x=d is the viewing plane.
%We enter estimated bounds on the computed coordinates,
%initialize the output file by assigning
%the color (255,255,255) to each pixel
%(rescales to (1,1,1) -- white),
%and initialize the z-buffer
%array by entering Inf for infinity.
ymin = 1;
ymax = 2*col; %We guess ymin < y < ymax for all projected points (x,y,z).
zmin = 1;
zmax = 2*row; %We guess zmin < z < zmax for all projected points (x,y,z).
outpic(1:round(1+zmax-zmin),1:round(1+ymax-ymin),1:3) = 255;
zbuffer(1:round(1+zmax-zmin),1:round(1+ymax-ymin)) = Inf;
%Now we loop through the input array and assign the color
%values to the three points of the
%output corresponding to the three faces of the cube
%that are to appear. It is important to note
%that the same block of code is repeated each time the
%values of x0, y0, and z0 are assigned.
for i=1:s %This s is the number of rows of the square image.
for j=1:s %This s is the number of columns of the square image.
%Front face:
x0=s; y0=j; z0=s-i+1;
%Perspective projection routine starts here.
x=d; y=b+((d-a)/(x0-a))*(y0-b); z=c+((d-a)/(x0-a))*(z0-c);
distance=sqrt((x0-a)^2+(y0-b)^2+(z0-c)^2);
if (ymin<=y & y<=ymax & zmin<=z & z<=zmax)
if distance < zbuffer(round(1+zmax-z),round(1+y-ymin))
outpic(round(1+zmax-z),round(1+y-ymin),:)=inpic(i,j,:);
zbuffer(round(1+zmax-z),round(1+y-ymin))=distance;
end
end
%Perspective projection routine ends here.
%Right face:
x0=s-j+1; y0=s; z0=s-i+1;
%Perspective projection routine starts here.
x=d; y=b+((d-a)/(x0-a))*(y0-b); z=c+((d-a)/(x0-a))*(z0-c);
distance=sqrt((x0-a)^2+(y0-b)^2+(z0-c)^2);
if (ymin<=y & y<=ymax & zmin<=z & z<=zmax)
if distance < zbuffer(round(1+zmax-z),round(1+y-ymin))
outpic(round(1+zmax-z),round(1+y-ymin),:)=inpic(i,j,:);
zbuffer(round(1+zmax-z),round(1+y-ymin))=distance;
end
end
%Perspective projection routine ends here.
%Top face:
x0=i; y0=j; z0=s;
%Perspective projection routine starts here.
x=d; y=b+((d-a)/(x0-a))*(y0-b); z=c+((d-a)/(x0-a))*(z0-c);
distance=sqrt((x0-a)^2+(y0-b)^2+(z0-c)^2);
if (ymin<=y & y<=ymax & zmin<=z & z<=zmax)
if distance < zbuffer(round(1+zmax-z),round(1+y-ymin))
outpic(round(1+zmax-z),round(1+y-ymin),:)=inpic(i,j,:);
zbuffer(round(1+zmax-z),round(1+y-ymin))=distance;
end
end
%Perspective projection routine ends here.
end
end
%Finally, the output image is sent to the screen and also saved to a file.
%Runtime is shorter if you
%do not send the image to the screen. Just put a "%" in front of that line
%to disable it. On the other
%hand, you may want to view the image on the screen but not save it to a file.
%In that case disable
%the imwrite line.
image(outpic/255); axis equal
imwrite(outpic/255,'outfile.jpg','jpg')