I'm attempting to model a simple graphics pipeline - using Matlab at the moment as a modelling tool to get the transformations correct. I appreciate there are software tools that would make this easier - but I'm looking to understand the maths behind it and hence am looking to mostly use simple functions & matrices that I'm learning from a book (very retro!).
I've successfully got through the stages of defining simple objects and converting them into a universal world space - but have come unstuck with the mathematics required to convert an object into view space and the back face culling.
I believe my view space transformation is correct because when I plot the composite vectors they appear correct - but - when I do the back-face culling, it seems to fail to remove the correct triangles. Given that it depends only on two things, the line-of-sight vector and face normals, I can't work out what I'm doing wrong.
When defining the triangles in local definition space, I did it so that all the normals pointed outwards. I've put my results into the image below
My questions are:
- Have I gone wrong, or are my expectations incorrect?
- If so where, and how do I fix?
Progress
I've plotted the normal's of all the shapes when in view space. They have all been inverted and now point inwards. Is this a property of the transformation and could it be responsible - or should this have no effect because all the polygons are affected the same?
(Have changed the code to show this)
clc; clear all; close all; %============Initial verticies & Faces of the shape=========== [s1_vtx,s1_fcs] = Pyramid(); [s2_vtx,s2_fcs] = Cube(); %==============Transform Shape 1 ====================== Tx = 0; Ty = 0; Tz = 0; %Translation vectors for x,y,z axes Sx = 2; Sy = 2; Sz = 2;%Scaling factors in x,y,z dimensions Rx = pi/2; Ry = pi/4; Rz = pi/4; %Rotating factors in x,y,z dimensions transform = scale(Sx,Sy,Sz)*rotate(Rx,0,0)*translate(Tx,Ty,Tz); %Merge transforms together s1_vtx = transform*vertcat(s1_vtx,(ones(1,length(s1_vtx)))); %Add row of ones to end for multiplication s1_vtx = s1_vtx(1:3,:); %And remove afterwards %==============Transform Shape 2 ====================== Tx = 0.5; Ty = 0; Tz = 0.5; transform = scale(1,2,1)*translate(Tx,Ty,Tz); s2_vtx = transform*vertcat(s2_vtx,(ones(1,length(s2_vtx)))); s2_vtx = s2_vtx(1:3,:); %======Create World Space =========== ws_vtx = horzcat(s1_vtx(1:3,:), s2_vtx(1:3,:)); %remove homogenous column for patching ws_fcs = horzcat(s1_fcs,(s2_fcs+(length(s1_vtx)))); %======Plot World Space =========== grid on; hold on; scatter3(ws_vtx(1,:),ws_vtx(2,:),ws_vtx(3,:)) %Plot all the points patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'none'); for i = 1:length(ws_vtx) str = sprintf('%d',i); text(ws_vtx(1,i),ws_vtx(2,i),ws_vtx(3,i), str,'FontSize',16, 'Color','r', 'FontWeight','b'); end points = zeros(3,3); %Contains 1 triangle for i = 1:length(ws_fcs); %For each triangle points(:,1:3) = ws_vtx(:,ws_fcs(1:3,i)); U = points(:,2) - points(:,1); %Get two non-parallel vectors V = points(:,3) - points(:,1); average = [0,0,0]; for j = 1:length(points) average(j) = (points(j,1) + points(j,2) + points(j,3))/3; end N = cross(U,V)/norm(cross(U,V)); %Normal, normalised to mag 1 scatter3(average(1),average(2),average(3)); plot3([average(1), average(1)+N(1)],[average(2), average(2)+N(2)],[average(3), average(3)+N(3)]); end %==================Create view matrix=================== focus = [1.5,0,1.5]; %The point we're looking at Cx = 3; Cy = -3; Cz = 3; %Position of camera Vspec = [0;0;1]; %Specified up direction T = viewMat(focus, [Cx,Cy,Cz],Vspec); %Create viewspace transform matrix p = norm(focus - [Cx,Cy,Cz]); U = T(1,1:3); V = T(2,1:3); N = T(3,1:3); %New Up, Right & View direction vectors %============Plot the camera vectors================= scatter3(Cx,Cy,Cz,'s') %Plot the camera position plot3([Cx, Cx+p*N(1)],[Cy, Cy+p*N(2)],[Cz, Cz+p*N(3)]); plot3([Cx, Cx+V(1)],[Cy, Cy+V(2)],[Cz, Cz+V(3)]); plot3([Cx, Cx+U(1)],[Cy, Cy+U(2)],[Cz, Cz+U(3)]); %==================Transform into View Space=================== ws_vtx = T*vertcat(ws_vtx,(ones(1, length(ws_vtx)))); %Transform matrix ws_vtx = ws_vtx(1:3,:); %Remove homogenous dimension origin = T*[Cx;Cy;Cz;1]; %Transform origin Cx = origin(1); Cy = origin(2); Cz = origin(3); %remove homogenous dimension focus = (T*horzcat(focus,1)')';%Transform focus point focus = focus(:,1:3);%remove homogenous dimension %==================Plot View Space================= figure(); hold on; grid on; patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'none'); scatter3(Cx, Cy, Cz, 's'); scatter3(focus(1), focus(2), focus(3), 's'); plot3([Cx, focus(1)],[Cy, focus(2)],[Cz,focus(3)], 'g'); for i = 1:length(ws_vtx) str = sprintf('%d',i); text(ws_vtx(1,i),ws_vtx(2,i),ws_vtx(3,i), str,'FontSize',16, 'Color','r', 'FontWeight','b'); end %================Plot normals of world space============== for i = 1:length(ws_fcs); %For each triangle points(:,1:3) = ws_vtx(:,ws_fcs(1:3,i)); U = points(:,2) - points(:,1); %Get two non-parallel vectors V = points(:,3) - points(:,1); average = [0,0,0]; for j = 1:length(points) average(j) = (points(j,1) + points(j,2) + points(j,3))/3; end N = cross(U,V)/norm(cross(U,V)); %Normal, normalised to mag 1 scatter3(average(1),average(2),average(3)); plot3([average(1), average(1)+N(1)],[average(2), average(2)+N(2)],[average(3), average(3)+N(3)]); end 
