欢迎光临散文网 会员登陆 & 注册

自学计算机图形学6: 用北太天元辅助理解从世界坐标系到相机坐标系下的坐标变换

2023-05-09 11:19 作者:卢朓  | 我要投稿

%北太天元 帮助理解 计算机图形学的坐标变换

%立方体

%

points = [

   % 下底面的四个点

   -1 -1 -1  ; %第一个点

   -1 1 -1  ; %第二个点

   1 1 -1  ;

   1 -1 -1  ;

      %上底面的四个点

   -1 -1 1  ;

   -1 1 1  ;

   1 1 1  ;

   1 -1 1  ;

      %原点

      0 0 0

   ];


points = points' ; %每个点的坐标改成列向量


%开始的up方向 (0, 0, 1);

% pitch = 45, yaw = 0 方向是 (1,1,0)

up = [0; 1; 0];

pitch = 30; yaw = -45;


ca_axes = camera_axes(up, pitch_yaw(pitch,yaw));


ca_points = ca_axes' *points;


max_p = max(ca_points,[], 2); %获得camera view 坐标系下的所有点坐标的最大值

min_p = min(ca_points,[], 2);%获得camera view 坐标系下的所有点坐标的最小值


%现在camera的方向是direction = -ca_axes(3,:)的转置

% 目前假设的camera的位置在(0,0,0)

% 需要把camera 沿着camera的方向反向移动一段距离 distance,

% 使得整个立方体都在camera的前方,

% 现在 ca_points 在 ca_axes(3,:) 的坐标的范围是

min_d = min(ca_points(3,:));

max_d = max(ca_points(3,:));

%相机需要移动的距离是

distance = max_d + 0.1*(max_d - min_d);

% camera 的位置(在移动前的camera 坐标系下)

camera_p = [ 0; 0; distance ];

%相机的位置在世界坐标系下是

camera_position = ca_axes * camera_p ;


% 经过了先旋转,再平移

% 最终得到的 look_at( up, pitch_yaw(pitch,yaw), position) 下的

% 点的坐标(在平移后camera坐标系下)是

final_points = ca_points - camera_p;




%还有一种方式来计算 camera_view 下的坐标, 使用齐次坐标

qi_points = [points ; ones(size(points(1,:))) ]; %最后一行加上了1


%齐次坐标的从world coordinates变换到

% 相机坐标系下的 transform 矩阵

trans_mat = [  ca_axes' , -camera_p; [ 0, 0, 0, 1] ];

 平移_mat = [ eye(3), -camera_position; [0 0 0 1] ]

 旋转_mat = [ ca_axes', zeros(3,1); [0 0 0 1] ]

% 你可以验证 trans_mat = 平移_mat * 旋转_mat

disp("trans_mat - 平移_mat * 旋转_mat")

 trans_mat - 平移_mat * 旋转_mat %

disp("trans_mat - 旋转_mat * 平移")

 trans_mat - 旋转_mat * 平移_mat

% 这和 https://learnopengl.com/Getting-started/Camera 的 LookAt

% 矩阵是相同的



qi_final_points = trans_mat * qi_points;


%比较两种方式得到的camera_view 下的坐标

final_points - qi_final_points(1:3, :)




%根据 pitch 和 yaw 确定 camer 的方向

% 开始的camera的方向是(1,0,0), 首先绕z轴正向逆时针方向旋转pitch角度

% 然后再绕y轴正向顺时针方向旋转 ywa 角度

% 最后得到的camera的方向

% 例如 pitch_yaw(0,-90) 得到的方向是 (0,0,-1);

% 不过,最后的向量都写成了列向量

function direction = pitch_yaw( pitch, yaw)

   direction = [

         cos( deg2rad(pitch) )*cos( deg2rad(yaw) );

         sin( deg2rad(pitch) );

         cos( deg2rad(pitch) )*sin( deg2rad(yaw) );

      ];

end



%对于开始给定的up方向和 direction方向

% 计算出right 方向 : camera_right = direction x up 再normalize

% 然后根据camera_right方向和direction方向计算出camera_up:

% camera_up = right x direction 再normalize

% 最后得到的camera坐标系的三个轴是

% (right,

% https://learnopengl.com/Getting-started/Camera 这篇文章中的

% direction 不是camera 看向的方向,而是相反的。

% 我们这里和上面的帖子不同,direction 还保持camera 看向的方向

% 也就是 (right, camera_up, -direction) 是一个右手系

% https://learnopengl.com/Getting-started/Camera 这篇文章中的

% 的lookat 的矩阵也是怪怪的,可能也会导致模仿者出错。

function ca_axes = camera_axes(up, direction)

   up = up(:); % 确保得到的up是一个列向量

   direction = direction(:); %确保得到的direction 是一个列向量

   %确保输入的direction是一个单位向量

   norm_d = norm(direction, 2);

   if(norm_d < eps)

      error('输入的direction向量接近于0');

   end

   direction = direction /norm_d;


   camera_right = cross( direction, up ); % drection 叉乘 up

   % 这个地方要检查一下 是不是direction 和 up 贡献

   norm_r = norm(camera_right,2) ; %计算camera_right的2范数

   if(norm_r < eps)

      error("up 和 directin 共线")

   end

   camera_right = camera_right / norm_r; %把camera_right单位化


   camera_up = cross(camera_right, direction); % right 叉乘 direction

   camera_up = camera_up / norm(camera_up, 2);


   ca_axes = [ camera_right, camera_up, -direction ]; 

end



自学计算机图形学6: 用北太天元辅助理解从世界坐标系到相机坐标系下的坐标变换的评论 (共 条)

分享到微博请遵守国家法律