欢迎光临
我们一直在努力

真3D!(但是侯老师版)

前言

关于3D有关的东西,我十分感兴趣,因为我想自己手搓一个MC,我可是MC资深老玩家

又在一个平常的下午,刷到了编程侯老师的视频,就跟着一起做了

结果也是非常成功,只不过使用scratch做的

所以,我在这里用C++和EasyX把代码写了出来

温馨提示:本人还只是初一,大部分理论知识都不太清楚,所以不要问我为什么,问我就是不知道

网址在此奉上

正文

因为我不清楚原理,准确来说是看不懂,所以全部我都是照着代码抄的(仅限scratch)

但C++和scratch有所不同所以有些地方在scratch里十分复杂,但在C++就十分简单了

并且我还修复了一些我觉得有问题的地方:

1.我把侯老师的 当方块的面的其中一个角超过了z轴裁剪位置,整个面就会被裁剪 的bug;

2.把z轴裁剪位置改为了极小值(不然在方块内部就会看的很别扭,会误删方块的面)

并且我发现,当两个面的 当前面到相机的距离 相同时,会先绘制先加入的面,再绘制后加入的面,就会导致当两个面的颜色不同时,可能会出现渲染排序的问题(方块的一部分会被覆盖)

不过这些都要看我们的侯老师改不改了

完整代码

要记得改成  UTF-8 with BOM  的编码格式哦(不然标题会是乱码)

#include <bits/stdc++.h>
#include <windows.h>
#include <conio.h>
#include <graphics.h>
#define get_key(key) (GetAsyncKeyState(key)&0x8000)
using namespace std;

const int N = 10000005;

bool running = true;

struct x_y_z {
double x, y, z;
};

double x1, y_1, z1;
double x2, y2, z2;
double x3, y3, z3;
double x4, y4, z4;

double camera_x, camera_y, camera_z;//相机x,y,z

double pianyi_x, pianyi_y, pianyi_z;//位置偏移x,y,z
x_y_z pianyi[N];
double suofang_x, suofang_y, suofang_z;//边长缩放x,y,z
x_y_z suofang[N];
string type;//方块类型
string type_[N];
int cnt;

double cos_x, sin_x;
double cos_y, sin_y;

double shuipin_x, chuizhi_y;

int paint_x, paint_y;//画笔位置

int jiaoju;//焦距

double weizhi_z, bili_z;//z轴裁剪位置,z轴裁剪比例

int _i, _j;

int window_h, window_w;//窗口高度,窗口宽度

string vec[10] = {
"",
"_000100110010",
"_001101111011",
"_000001011010",
"_100101111110",
"_010011111110",
"_000001101100"
};

struct color {
int r, g, b;
};

struct node {
double x1, x2, x3;
double y_1, y2, y3;
double z1, z2, z3;
color colors;
double distance;
}vecs[N];
int vecs_cnt;

void set_vec_1(double x, double y, double z) {
x1 = x;
y_1 = y;
z1 = z;
}

void set_vec_2(double x, double y, double z) {
x2 = x;
y2 = y;
z2 = z;
}

void set_vec_3(double x, double y, double z) {
x3 = x;
y3 = y;
z3 = z;
}

void set_vec_4(double x, double y, double z) {
x4 = x;
y4 = y;
z4 = z;
}

void move(double x, double y, double z) {
paint_x = jiaoju * (x / z) + window_w / 2;
paint_y = jiaoju * (y / z) + window_h / 2;
}

void deep_sort() {
for (_i = 1;_i <= 6;_i++) {
set_vec_1(pianyi_x + (vec[_i][1] – '0') * suofang_x, pianyi_y + (vec[_i][2] – '0') * suofang_y, pianyi_z + (vec[_i][3] – '0') * suofang_z);
set_vec_2(pianyi_x + (vec[_i][4] – '0') * suofang_x, pianyi_y + (vec[_i][5] – '0') * suofang_y, pianyi_z + (vec[_i][6] – '0') * suofang_z);
set_vec_3(pianyi_x + (vec[_i][7] – '0') * suofang_x, pianyi_y + (vec[_i][8] – '0') * suofang_y, pianyi_z + (vec[_i][9] – '0') * suofang_z);
set_vec_4(pianyi_x + (vec[_i][10] – '0') * suofang_x, pianyi_y + (vec[_i][11] – '0') * suofang_y, pianyi_z + (vec[_i][12] – '0') * suofang_z);

set_vec_1(x1 – camera_x, y_1 – camera_y, z1 – camera_z);
set_vec_2(x2 – camera_x, y2 – camera_y, z2 – camera_z);
set_vec_3(x3 – camera_x, y3 – camera_y, z3 – camera_z);
set_vec_4(x4 – camera_x, y4 – camera_y, z4 – camera_z);

set_vec_1(x1 * cos_x – z1 * sin_x, y_1, x1 * sin_x + z1 * cos_x);
set_vec_2(x2 * cos_x – z2 * sin_x, y2, x2 * sin_x + z2 * cos_x);
set_vec_3(x3 * cos_x – z3 * sin_x, y3, x3 * sin_x + z3 * cos_x);
set_vec_4(x4 * cos_x – z4 * sin_x, y4, x4 * sin_x + z4 * cos_x);

set_vec_1(x1, y_1 * cos_y – z1 * sin_y, y_1 * sin_y + z1 * cos_y);
set_vec_2(x2, y2 * cos_y – z2 * sin_y, y2 * sin_y + z2 * cos_y);
set_vec_3(x3, y3 * cos_y – z3 * sin_y, y3 * sin_y + z3 * cos_y);
set_vec_4(x4, y4 * cos_y – z4 * sin_y, y4 * sin_y + z4 * cos_y);

if (z1 > weizhi_z || z2 > weizhi_z || z3 > weizhi_z || z4 > weizhi_z) {//侯老师的方法会漏掉一些面……
double distance = sqrt(((x1 + x2 + x3 + x4) / 4) * ((x1 + x2 + x3 + x4) / 4) + ((y_1 + y2 + y3 + y4) / 4) * ((y_1 + y2 + y3 + y4) / 4) + ((z1 + z2 + z3 + z4) / 4) * ((z1 + z2 + z3 + z4) / 4));
vecs[++vecs_cnt] = { x1,x2,x3,y_1,y2,y3,z1,z2,z3,{0,0,191},distance };
vecs[++vecs_cnt] = { x1,x4,x3,y_1,y4,y3,z1,z4,z3,{0,0,191},distance };
}
}
}

void caijian_z() {
bili_z = 0;
if (z1 < weizhi_z) {
bili_z = (weizhi_z – z1) / (z2 – z1);
set_vec_1(x1 + (x2 – x1) * bili_z, y_1 + (y2 – y_1) * bili_z, weizhi_z);
}
if (z2 < weizhi_z) {
bili_z = (weizhi_z – z2) / (z1 – z2);
set_vec_2(x2 + (x1 – x2) * bili_z, y2 + (y_1 – y2) * bili_z, weizhi_z);
}
}

void paint_line(double X1, double Y1, double Z1, double X2, double Y2, double Z2) {
set_vec_1(X1 – camera_x, Y1 – camera_y, Z1 – camera_z);
set_vec_2(X2 – camera_x, Y2 – camera_y, Z2 – camera_z);

set_vec_1(x1 * cos_x – z1 * sin_x, y_1, x1 * sin_x + z1 * cos_x);
set_vec_2(x2 * cos_x – z2 * sin_x, y2, x2 * sin_x + z2 * cos_x);

set_vec_1(x1, y_1 * cos_y – z1 * sin_y, y_1 * sin_y + z1 * cos_y);
set_vec_2(x2, y2 * cos_y – z2 * sin_y, y2 * sin_y + z2 * cos_y);

caijian_z();

if (bili_z < 1) {
double t_x1, t_y1, t_x2, t_y2;
move(x1, y_1, z1);
t_x1 = paint_x;
t_y1 = paint_y;
move(x2, y2, z2);
t_x2 = paint_x;
t_y2 = paint_y;
line(t_x1, t_y1, t_x2, t_y2);
}
}

void paint_triangle(double X1, double Y1, double Z1, double X2, double Y2, double Z2, double X3, double Y3, double Z3) {
move(X1, Y1, Z1);
x1 = paint_x;
y_1 = paint_y;

move(X2, Y2, Z2);
x2 = paint_x;
y2 = paint_y;

move(X3, Y3, Z3);
x3 = paint_x;
y3 = paint_y;

double len_A = sqrt((x3 – x2) * (x3 – x2) + (y3 – y2) * (y3 – y2));
double len_B = sqrt((x1 – x3) * (x1 – x3) + (y_1 – y3) * (y_1 – y3));
double len_C = sqrt((x2 – x1) * (x2 – x1) + (y2 – y_1) * (y2 – y_1));

paint_x = (len_A * x1 + len_B * x2 + len_C * x3) / (len_A + len_B + len_C);
paint_y = (len_A * y_1 + len_B * y2 + len_C * y3) / (len_A + len_B + len_C);

POINT pts[3] = { {x1,y_1},{x2,y2},{x3,y3} };
setfillcolor(RGB(vecs[_i].colors.r, vecs[_i].colors.g, vecs[_i].colors.b));
solidpolygon(pts, 3);

//setlinecolor(RGB(vecs[_i].colors.r, vecs[_i].colors.g, vecs[_i].colors.b));
setlinecolor(RGB(255, 255, 255));
if ((x1 > 0 && x1 < window_w) || (x2 > 0 || x2 < window_h)) {
line(x1, y_1, x2, y2);
}
if ((x3 > 0 && x3 < window_w) || (x2 > 0 || x2 < window_h)) {
line(x2, y2, x3, y3);
}
}

void jisuan() {
sin_x = sin(shuipin_x);
sin_y = sin(chuizhi_y);
cos_x = cos(shuipin_x);
cos_y = cos(chuizhi_y);
}

void control() {
int key_w_down=0, key_s_down=0, key_a_down=0, key_d_down=0;
int key_up_down=0, key_down_down=0, key_left_down=0, key_right_down=0;
int key_space_down = 0, key_shift_down = 0;
if (get_key('w') || get_key('W')) {
key_w_down = 1;
}
if (get_key(38)) {
key_up_down = 1;
}
if (get_key('s') || get_key('S')) {
key_s_down = 1;
}
if (get_key(40)) {
key_down_down = 1;
}
if (get_key('a') || get_key('A')) {
key_a_down = 1;
}
if (get_key(37)) {
key_left_down = 1;
}
if (get_key('d') || get_key('D')) {
key_d_down = 1;
}
if(get_key(32)) {
key_space_down = 1;
}
if (get_key(16)) {
key_shift_down = 1;
}
if (get_key(39)) {
key_right_down = 1;
}

if (get_key(VK_ESCAPE))running = false;

camera_x += (key_d_down – key_a_down) * 0.02 * cos_x;
camera_z += (key_d_down – key_a_down) * 0.02 * (0 – sin_x);
camera_x += (key_w_down – key_s_down) * 0.02 * sin_x;
camera_z += (key_w_down – key_s_down) * 0.02 * cos_x;
camera_y += (key_shift_down – key_space_down) * 0.02;

shuipin_x += (key_right_down – key_left_down) * 0.01;
chuizhi_y += (key_down_down – key_up_down) * 0.01;

if (chuizhi_y > 1.57) chuizhi_y = 1.57;
if (chuizhi_y < -1.57) chuizhi_y = -1.57;
if (shuipin_x > 3.14) shuipin_x = -3.14;
if (shuipin_x < -3.14) shuipin_x = 3.14;
}

void paint_cube(double pianyi_X, double pianyi_Y, double pianyi_Z, double suofang_X, double suofang_Y, double suofang_Z, string Type) {
pianyi_x = pianyi_X;
pianyi_y = pianyi_Y;
pianyi_z = pianyi_Z;
suofang_x = suofang_X;
suofang_y = suofang_Y;
suofang_z = suofang_Z;
type = Type;
}

void init_xuanran() {
weizhi_z = 0.0000000001;
camera_x = 1;
camera_y = 1;
camera_z = -3;
shuipin_x = 0;
chuizhi_y = 0;
jiaoju = 400;

cnt = 1;
pianyi[1] = { 1,1,1 };
suofang[1] = { 1,1,1 };
}

bool cmp(node x, node y) {
return x.distance > y.distance;
}

void xuanran() {
vecs_cnt = 0;
for (_j = 1;_j <= cnt;_j++) {
paint_cube(pianyi[_j].x, pianyi[_j].y, pianyi[_j].z, suofang[_j].x, suofang[_j].y, suofang[_j].z, type_[_j]);
deep_sort();
}
sort(vecs + 1, vecs + vecs_cnt + 1, cmp);
for (_i = 1;_i <= vecs_cnt;_i++) {
paint_triangle(vecs[_i].x1, vecs[_i].y_1, vecs[_i].z1, vecs[_i].x2, vecs[_i].y2, vecs[_i].z2, vecs[_i].x3, vecs[_i].y3, vecs[_i].z3);
}
}

int main() {
window_h = 500;
window_w = 900;

initgraph(900, 500);

SetWindowText(GetHWnd(), L"3D引擎(编程侯老师版)");

init_xuanran();

BeginBatchDraw();

const double PHYSICS_STEP = 1.0 / 90.0;
double accumulator = 0.0;
LARGE_INTEGER freq, prev_time, curr_time;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&prev_time);

while (running) {

cleardevice();

QueryPerformanceCounter(&curr_time);
double delta_time = (curr_time.QuadPart – prev_time.QuadPart) / (double)freq.QuadPart;
prev_time = curr_time;

jisuan();

control();

xuanran();

FlushBatchDraw();
if (delta_time < PHYSICS_STEP) {
Sleep((PHYSICS_STEP – delta_time) * 1000);
}
}
EndBatchDraw();
closegraph();
return 0;
}

结语

明天就要考八级了,能祝我rp++么?

赞(0)
未经允许不得转载:171主机测评 » 真3D!(但是侯老师版)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址