%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')