对于我这种有代码洁癖的人来说用别人的代码框架,然后补充别人的代码是很痛苦的。
原本的作业要求是在课程提供的代码框架下填写补充完几个函数后实现简单三角形在三维空间中围绕坐标轴旋转的效果,这里我在不适用其框架的情况下,自己造轮子实现了更复杂的可绕任意过原点轴的旋转效果,而且摄像机位置可以任意改变。
当然帮我进行矩阵运算的eigen库,还有帮助我控制屏幕像素点显示的opencv库还是要用的,如果再低层到纯c++我就要谢了。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
cv::Mat bg_image=Mat();
//质点绕任意过原点的旋转轴进行旋转的 *** 作
Eigen::Vector4d rotating(Eigen::Vector4d point_vector, Eigen::Vector3d Rotary_shaft, double angle)
{
double u=Rotary_shaft.x(), v = Rotary_shaft.y(), w = Rotary_shaft.z(),o=angle;
double s = sqrt(u * u + v * v + w * w);
u = u / s;
v = v / s;
w = w / s;
Eigen::Matrix4d rotating;
rotating <<
u * u + (1 - u * u) * cos(o), u* v* (1 - cos(o)) - w * sin(o), u * w * (1 - cos(o)) + v * sin(o), 0,
u * v * (1 - cos(o)) + w * sin(o), v * v + (1 - v * v) * cos(o), v * w * (1 - cos(o)) - u * sin(o), 0,
u * w * (1 - cos(o)) - v * sin(o), v * w * (1 - cos(o)) + u * sin(o), w * w + (1 - w * w) * cos(o), 0,
0, 0, 0, 1;
Eigen::Vector4d ret= rotating * point_vector;
return ret;
}
//计算质点相对于摄像机的位置,以摄像机的焦点为坐标原点新建的坐标系,也可以拿来把任意点作为原点建系,求相对位置
Eigen::Vector3d Relative_position (Eigen::Vector4d point_vector, Eigen::Vector4d camera_positon,Eigen::Vector4d camera_z, Eigen::Vector4d camera_x)
{
Eigen::Vector3d Apart_position;//摄像机位置点到质点的向量
Apart_position <<
point_vector.x() - camera_positon.x(),
point_vector.y() - camera_positon.y(),
point_vector.z() - camera_positon.z();
Eigen::Vector3d camera_x_3d, camera_z_3d;
camera_x_3d <<
camera_x.x(), camera_x.y(), camera_x.z();
camera_z_3d<<
camera_z.x(), camera_z.y(), camera_z.z();
Eigen::Vector3d camera_y_3d = camera_x_3d.cross(camera_z_3d);//向量叉乘得到垂直于它的向量
Eigen::Vector3d Relative_position;
double x = Apart_position.dot(camera_x_3d)/Apart_position.norm();//计算质点在摄像机为原点的坐标系中的x值
double y = Apart_position.dot(camera_y_3d)/Apart_position.norm();
double z = Apart_position.dot(camera_z_3d)/Apart_position.norm();
Relative_position <<
x, y, z;
return Relative_position;
}
//摄像机透视成像 以及光栅化
Eigen::Vector2 perspective(double fov_w,int width,int height, Eigen::Vector3d Relative_position)
{
double focal_length = (width / tan(fov_w/2))/20000;
double x = Relative_position.x()* focal_length/ Relative_position.z();
double y= Relative_position.y() * focal_length / Relative_position.z();
double z = focal_length;
Eigen::Vector2 ret;
ret <<
(int)(x * 10000)+400,
(int)(y * 10000)-100;
return ret;
}
//三个顶点连线绘制三角形
void triangle(Point A,Point B,Point C)
{
Scalar line_color =cv::Scalar(5,5,4);
line(bg_image, A, B, line_color, 2, LINE_8);
line(bg_image, B, C, line_color, 2, LINE_8);
line(bg_image, C, A, line_color, 2, LINE_8);
printf("%d %d\n", A.x,A.y);
}
void tick(Eigen::Vector4d A, Eigen::Vector4d B, Eigen::Vector4d C)//暂时废弃掉的tick刷新函数,以后会有用
{
}
int main(void)
{
namedWindow("GAMES101-homework1-super-plus - SWPU - Li_JinWen", 1);
int weith = 800, height = 400;
double FOV = 3.1415926/4;
Eigen::Vector4d S[3];
S[0] << 3,0, 4, 0;
S[1] << -3, 0, 4, 0;
S[2] << 0, 0, 2, 0;
double rotating_speed = 0.05;
Eigen::Vector3d Rotary_shaft;
Eigen::Vector4d camera_positon, camera_z, camera_x;
Rotary_shaft << 0, 0, 1;
camera_positon << 15, 0, 0, 0;//这里可以修改摄像机焦点摆放的位置
camera_z << -1, 0, 0, 0;//这里可以修改摄像机的朝向
camera_x << 0, 1, 0, 0;//这里可以修改摄像机的水平方向
Point A, B, C;
bg_image = cv::Mat(height, weith, CV_8UC3, Scalar(255, 255, 255, 255));
while (true)
{
for (int i = 0; i < 3; i++)
{
S[i]=rotating(S[i], Rotary_shaft, rotating_speed);
}
A.x = perspective(FOV, weith, height, Relative_position(S[0], camera_positon, camera_z, camera_x)).x();
A.y = perspective(FOV, weith, height, Relative_position(S[0], camera_positon, camera_z, camera_x)).y();
B.x= perspective(FOV, weith, height, Relative_position(S[1], camera_positon, camera_z, camera_x)).x();
B.y= perspective(FOV, weith, height, Relative_position(S[1], camera_positon, camera_z, camera_x)).y();
C.x = perspective(FOV, weith, height, Relative_position(S[2], camera_positon, camera_z, camera_x)).x();
C.y = perspective(FOV, weith, height, Relative_position(S[2], camera_positon, camera_z, camera_x)).y();
triangle(A, B, C);
imshow("GAMES101-homework1-Original - SWPU - Li_JinWen", bg_image);
waitKey(100);
bg_image = cv::Mat(height, weith, CV_8UC3, Scalar(255, 255, 255, 255));
imshow("GAMES101-homework1-Original - SWPU - Li_JinWen", bg_image);
}
}
绕任意过原点的轴的旋转 *** 作 矩阵如下:
执行效果如下:
后续我会继续更新这篇文章,完善这段代码,让它功能更加强大
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)