Skip to content

Commit

Permalink
规范工程架构、增加更多操控功能
Browse files Browse the repository at this point in the history
  • Loading branch information
gaowanlu committed May 1, 2022
1 parent 093bcf8 commit 20d4cec
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 68 deletions.
39 changes: 19 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
# 3dll
# 3dll 使用C++实现简单的3D渲染

使用C++实现简单的3D渲染
## 代码

## 快速开始

```shell
git clone https://hub.fastgit.xyz/gaowanlu/3dll.git
```
代码请见github代码仓库 [https://github.com/gaowanlu/3dll](https://github.com/gaowanlu/3dll)

## 为什么写了它

Expand All @@ -20,33 +16,36 @@ git clone https://hub.fastgit.xyz/gaowanlu/3dll.git

1、相机坐标系的旋转

![在这里插入图片描述](https://img-blog.csdnimg.cn/5f74decc37d348549c864ae0291ad3c8.png#pic_center)
2、鼠标点击且移动鼠标进行相机的旋转、滚轮滚动为z轴旋转
![在这里插入图片描述](https://img-blog.csdnimg.cn/ec2443792805477ab7bcd7906cf2edca.png#pic_center)

![在这里插入图片描述](https://img-blog.csdnimg.cn/401d1c84a9b444fb9a013f1523e09983.png#pic_center)

3、Ctrl+滚轮 支持缩小放大
2、鼠标点击且移动鼠标进行x与y轴的旋转、Ctrl+滚轮 支持z轴旋转

![在这里插入图片描述](https://img-blog.csdnimg.cn/cdb8b27c00324e93a30b96435d765412.png#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/f951e4aed6c342a596c64cdd4d55d9ff.png#pic_center)

## 环境搭建

或在Github [https://github/gaowanlu/3dll](https://github/gaowanlu/3dll)、获取最新的工程效果
3、滚轮对为相机位置向量进行放缩

请使用Visual Studio 2022 打开项目 ,或者自己使用其他IDE进行构建
![在这里插入图片描述](https://img-blog.csdnimg.cn/957d1133dfbf4405885b0a7e336588aa.png#pic_center)

项目 =》属性 =》C/C++ =》常规添加本项目的include文件夹路径到附加包含目录属性

项目 =》属性 =》链接器 =》将本项目的lib/x64文件夹路径添加附加库目录

注意设置上面步骤时,尽量选择 配置:所有配置 平台:x64 、以免新手怎么弄都跑不起来
## 快速开始

```shell
git clone https://hub.fastgit.xyz/gaowanlu/3dll.git
```

或在Github [https://github/gaowanlu/3dll](https://github/gaowanlu/3dll)、获取最新的工程效果

请使用Visual Studio 2022 打开项目 ,或者自己使用其他IDE进行构建

## 线性代数

课程推荐

* Bilibili MIT线性代数课程 <https://www.bilibili.com/video/BV1ix411f7Yp>
* 线性代数的本质 <https://www.bilibili.com/video/BV1ib411t7YR>
* Bilibili MIT线性代数课程 https://www.bilibili.com/video/BV1ix411f7Yp
* 线性代数的本质 https://www.bilibili.com/video/BV1ib411t7YR

## 路漫漫

Expand Down
86 changes: 40 additions & 46 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ int main(int argc, char** argv) {
window m_window(1000,700,1);
m_window.set_linecolor(0,255,0);
Model model_1({
{2, 3, 0},
{2, 5, 0},
{4, 3, 0},
{4, 5, 0},
{2, 3, 2},
{2, 5, 2},
{4, 3, 2},
{4, 5, 2}},'1');
{2, 13, 0},
{2, 15, 0},
{14, 13, 0},
{14, 15, 0},
{2, 13, 7},
{2, 15, 7},
{14, 13, 7},
{14, 15, 7}},'1');
Model model_2({
{7, -11, 0},
{7, -5, 0},
Expand All @@ -38,22 +38,31 @@ int main(int argc, char** argv) {
{-2, -5, 0},
{-4, -3, 0},
{-4, -5, 0},
{-2, -3, 2},
{-2, -5, 2},
{-4, -3, 2},
{-4, -5, 2} }, '3');
{-2, -3, 20},
{-2, -5, 20},
{-4, -3, 20},
{-4, -5, 20} }, '3');
Model model_z({
{0, 0, 0},
{0, 0, 70} }, 'z');
Model model_x({
{0, 0, 0},
{30, 0, 0} }, 'x');
Model model_y({
{0, 0, 0},
{0, 30, 0} }, 'y');

std::vector<Model>grid;//地的网格
for (int x = -30; x <= 30; x+=5) {
for (int y = -30; y <= 30; y+=5) {
Eigen::Matrix<double, 3, 1> v1(
x,y ,0);
Eigen::Matrix<double, 3, 1> v2(
x+2,y,0 );
x+5,y,0 );
Eigen::Matrix<double, 3, 1> v3(
x+2,y+2,0 );
x+5,y+5,0 );
Eigen::Matrix<double, 3, 1> v4(
x,y+2,0);
x,y+5,0);
std::vector<Eigen::Matrix<double, 3, 1>> ves{v1, v2, v3, v4};
Model block(ves, ' ');
grid.push_back(block);
Expand All @@ -71,16 +80,17 @@ int main(int argc, char** argv) {
Eigen::Matrix<double, 3, 3> camera_realtime=m_camera.trans(0,0,0);

while (1) {
m_window.set_linecolor(255, 0, 0);
m_window.render_model(model_x, last_resize, m_camera, camera_realtime);
m_window.render_model(model_y, last_resize, m_camera, camera_realtime);
m_window.render_model(model_z, last_resize, m_camera, camera_realtime);
//渲染地面
m_window.set_linecolor(155,155,155);
for (size_t j = 0; j < grid.size(); j++) {
std::vector<std::vector<int>> dots;
std::vector<Eigen::Matrix<double, 3, 1>> block = grid[j].resize(last_resize).get_matrix();
/* std::cout << block[0](1) << std::endl;
std::cout << block[0](0) << std::endl;*/
for (int i = 0; i <= block.size(); i++) {
//std::cout << block[i % block.size()](0) << std::endl;
Eigen::Matrix<double, 3, 1> dot_realtime = camera_realtime.inverse() * m_window.get_world_base() * block[i % block.size()];
Eigen::Matrix<double, 3, 1> dot_realtime = m_window.get_world_base() *camera_realtime.inverse() * block[i % block.size()];
Eigen::Matrix<double, 3, 1> window_dot = m_window.to_xy(dot_realtime(0), dot_realtime(1), dot_realtime(2),m_camera);
dots.push_back(std::vector<int>{ (int)window_dot(0), (int)window_dot(1) });
}
Expand All @@ -92,29 +102,11 @@ int main(int argc, char** argv) {
{dots[4][0],dots[4][1]} };
polygon(pts, 5);
}
//Sleep(1000);
//continue;
//取出相机的向量进行基变换

//模型渲染
m_window.set_linecolor(0, 255, 0);
for (std::size_t k = 0; k < models.size();k++) {
auto model = models[k].resize(last_resize).get_matrix();
//渲染物品
for (std::size_t i = 0; i < model.size(); i++) {
Eigen::Matrix<double, 3, 1> dot = model[i];//获得模型的向量1
//变换到相机坐标系内
Eigen::Matrix<double, 3, 1> dot1_realtime = camera_realtime.inverse() * m_window.get_world_base() * dot;
//获取模型向量2
for (std::size_t j = 0; j < model.size(); j++) {
Eigen::Matrix<double, 3, 1> dot = model[j];
//变换到相机坐标系内
Eigen::Matrix<double, 3, 1> dot2_realtime = camera_realtime.inverse() * m_window.get_world_base() * dot;
//将x y投到屏幕上,变换到图像坐标系
Eigen::Matrix<double, 3, 1> window_dot1 = m_window.to_xy(dot1_realtime(0), dot1_realtime(1), dot1_realtime(2),m_camera);
Eigen::Matrix<double, 3, 1> window_dot2 = m_window.to_xy(dot2_realtime(0), dot2_realtime(1), dot2_realtime(2),m_camera);
//画出向量1到向量2的连线
m_window.draw_t_line(window_dot1, window_dot2);
}
}
m_window.render_model(models[k],last_resize,m_camera,camera_realtime);
}

//操控部分
Expand All @@ -141,8 +133,8 @@ int main(int argc, char** argv) {
m_camera.clear_move();//偏移量归零
}
if (message.lbutton) {//鼠标左键按下
int dx = message.x - last_x;//求出鼠标 x y轴偏移量
int dy = message.y - last_y;
int dx = -(message.x - last_x);//求出鼠标 x y轴偏移量
int dy = -(message.y - last_y);
last_x = message.x;
last_y = message.y;
if (fabs(dx) < 10 && fabs(dy) < 10) {
Expand All @@ -152,17 +144,19 @@ int main(int argc, char** argv) {
camera_realtime = m_camera.trans(x_angle, y_angle, z_angle);//调整相机参数
}
if (message.wheel) {
if (message.ctrl) {//调整缩放参数缩放
double dz = message.wheel / 10.;
if (message.ctrl) {//z轴旋转
double dz = message.wheel / 20.;
z_angle = ((int)z_angle + (int)dz) % 360;
}
else {//z轴旋转
double dz = fabs(message.wheel) / 300.;//一次滚轮120
else {//调整缩放参数缩放
double dz = fabs(message.wheel) / 950.;//一次滚轮120
if (message.wheel < 0 && (last_resize - dz)>0.1) {//变小
last_resize = last_resize - dz;
m_camera.dz=last_resize;
}
else if (last_resize + dz < 15) {//变大
last_resize = last_resize + dz;
m_camera.dz = last_resize;
}
}
//相机进行变换
Expand Down
25 changes: 23 additions & 2 deletions src/utils/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ Eigen::Matrix<double, 3, 1> window::to_xy(double x, double y, double z,camera m_
}

void window::draw_t_line(Eigen::Matrix<double, 3, 1> dot1, Eigen::Matrix<double, 3, 1> dot2) {
if (dot1(2) > 0 || dot2(2) > 0) {//向有一个向量在相机前面时才进行显示此连线
//if (dot1(2) > 0 || dot2(2) > 0) {//向有一个向量在相机前面时才进行显示此连线
line(dot1(0), dot1(1), dot2(0), dot2(1));
}
//}
}

void window::clear() {
Expand All @@ -81,4 +81,25 @@ bool window::get_message(ExMessage *message) {
bool result= peekmessage(message);
flushmessage();
return result;
}

void window::render_model(Model m_model,double resize,camera m_camera, Eigen::Matrix<double, 3, 3> camera_realtime) {
auto model = m_model.resize(resize).get_matrix();
//渲染物品
for (std::size_t i = 0; i < model.size(); i++) {
Eigen::Matrix<double, 3, 1> dot = model[i];//获得模型的向量1
//变换到相机坐标系内
Eigen::Matrix<double, 3, 1> dot1_realtime = this->get_world_base() * camera_realtime.inverse() * dot;
//获取模型向量2
for (std::size_t j = 0; j < model.size(); j++) {
Eigen::Matrix<double, 3, 1> dot = model[j];
//变换到相机坐标系内
Eigen::Matrix<double, 3, 1> dot2_realtime = this->get_world_base() * camera_realtime.inverse() * dot;
//将x y投到屏幕上,变换到图像坐标系
Eigen::Matrix<double, 3, 1> window_dot1 = this->to_xy(dot1_realtime(0), dot1_realtime(1), dot1_realtime(2), m_camera);
Eigen::Matrix<double, 3, 1> window_dot2 = this->to_xy(dot2_realtime(0), dot2_realtime(1), dot2_realtime(2), m_camera);
//画出向量1到向量2的连线
this->draw_t_line(window_dot1, window_dot2);
}
}
}
7 changes: 7 additions & 0 deletions src/utils/window.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <graphics.h>
#include <easyx.h>
#include <Eigen/Dense>
#include "../model/model.h"
#include "../camera/camera.h"

/**
Expand Down Expand Up @@ -82,5 +83,11 @@ class window {
* @brief 获得窗口操控信息
*/
bool get_message(ExMessage* message);

/**
* @brief 渲染模型
* @param model
*/
void render_model(Model m_model, double resize, camera m_camera, Eigen::Matrix<double, 3, 3> camera_realtime);
};
#endif // !__WINDOW_H__

0 comments on commit 20d4cec

Please sign in to comment.