我(相信)我已经解决了这个问题(即使花了两天时间)。我的问题本质上是我想取面部法线和视线矢量的点积,如下所示
并确定角度,以查看面部是否朝向或远离视点。
我的错误步骤是,我是在从世界空间转换到视图空间之后才这样做的,因此我使用的视线矢量不再有效。
因此,为了解决这个问题,我只是在世界视图空间转换之前,在世界空间中执行了背面剔除!
我包含了显示背面剔除的功能代码,但没有显示视图空间转换。
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');