6
$\begingroup$

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

enter image description here

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 
$\endgroup$
4
  • 2
    $\begingroup$ The range of numbers on the axes change between the three diagrams, and the 2nd and 3rd have more vertices labelled. Are these transformed versions of the same cube, or three separate shapes? $\endgroup$ Commented Feb 10, 2016 at 3:43
  • $\begingroup$ There is information about syntax highlighting on Meta Stack Exchange but it appears that Matlab is not supported. $\endgroup$ Commented Feb 10, 2016 at 3:54
  • $\begingroup$ The first shape is an example of one of the composite worldspace shapes in its local coordinates with normals drawn on. The middel and right hand plots is the same worldspace shape transformed $\endgroup$ Commented Feb 10, 2016 at 11:38
  • 3
    $\begingroup$ Just FYI, in a GPU, the back face culling is done (or can be considered to be done) on the post-projection values of the vertices, and thus only needs to consider the X&Y values of the 3 triangle vertices. (There are a few reasons for this: avoiding problems with floating point rounding being one) $\endgroup$ Commented Feb 10, 2016 at 11:53

1 Answer 1

6
$\begingroup$

I (believe) I've solved this (even if it has taken 2 days). My problem was essentially I wanted to take the dot product of the face normal, and line-of-sight vector like below

enter image description here

And determine the angle to see if the face was looking towards or away from the view point.

My erroneous step was that I was doing this AFTER transforming from world-space to view-space - hence the line-of-sight vector I was using was no longer valid.

Hence, to solve this, I simply performed the back-face culling in world-space, prior to the world-view space transformation!

I've included functioning code showing the back face culling, but not the view-space transform.

clear; clc; close all; %======Create World Space (hard-coded values for demo) =========== ws_vtx = [0,2,0,2,1,0.5,1.5,0.5,1.5,0.5,1.5,0.5,1.5; 0,0,0,0,-2,0,0,2,2,0,0,2,2; 0,0,2,2,1,0.5,0.5,0.5,0.5,1.5,1.5,1.5,1.5]; ws_fcs = [1,2,4,3,3,1,6,6,6,6,7,7,9,8,8,8,10,10; 2,4,3,1,4,4,9,8,7,11,9,13,8,12,10,6,11,13; 5,5,5,5,1,2,7,9,11,10,13,11,13,13,12,10,13,12]; %==================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================= grid on; hold on; 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)],'g'); plot3([Cx, Cx+V(1)],[Cy, Cy+V(2)],[Cz, Cz+V(3)],'g'); plot3([Cx, Cx+U(1)],[Cy, Cy+U(2)],[Cz, Cz+U(3)],'g'); %===========Get Face Normals============================ norm_fcs = zeros(3,length(ws_fcs)); for i = 1:length(ws_fcs); %For each triangle points = zeros(3,3); %Contains 1 triangle points(:,1:3) = ws_vtx(:,ws_fcs(1:3,i)); %Get points for triangle U = points(:,2) - points(:,1); %Get two non-parallel vectors V = points(:,3) - points(:,1); norm_fcs(:,i) = cross(U,V); %Normal, normalised to mag 1 end %=================Back Face Culling====================== null_vals = 0; for i = 1:length(ws_fcs) %Take each triangle & calculate normal if dot(norm_fcs(:,i), N) > 0 %Dot product line of sight & normal of faces ws_fcs(:,i) = [0;0;0]; %If > 0, not visible & remove null_vals = null_vals + 1; %And increment counter end end ws_fcs_cat = zeros(3, length(ws_fcs) - null_vals); %Create new array null_vals = 0; for i = 1:length(ws_fcs) if norm(ws_fcs(:,i)) == 0 null_vals = null_vals + 1; else ws_fcs_cat(:,i - null_vals) = ws_fcs(:,i); end end ws_fcs = ws_fcs_cat; %======Plot World Space =========== scatter3(ws_vtx(1,:),ws_vtx(2,:),ws_vtx(3,:)) %Plot all the points patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'r', 'FaceAlpha', 0.5); 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 xlabel('x'); ylabel('y'); zlabel('z'); 
$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.