当前位置:   article > 正文

C语言伪3D制作_c语言伪3d房间制作

c语言伪3d房间制作

源码下载地址:文件下载-奶牛快传 Download |CowTransfer

(这个程序只支持EGE图形库,请下载自带EGE的redpandaDEVC++,下载地址:文件下载-奶牛快传 Download |CowTransfer,如果使用的是easyX图形库,请根据以下内容对程序进行修改。)

成品展示:

1.眼睛的成像方式

如下图,用A表示物体,O表示晶状体的光心(因为晶状体的形状可变,所以用符号↕表示),l表示主光轴,眼睛会自动调焦,把点A反射的光线都会聚在A'上。

下面,只留线段AA',再在图上加一个屏幕,屏幕与AA'的交点为A": 

之后把屏幕后面的部分去掉,A"为光源,眼睛就会改变晶状体的形状,重新聚焦,把A"的光线聚集到A",那么可以在屏幕上用点A''表示点A: 

之后,创建一个3维坐标图(为适应屏幕,所以不使用右手空间直角坐标系):

由此可以得出A在屏幕上的x坐标为A.x*眼睛与屏幕z轴的差/(眼睛距屏幕距离+A与屏幕z轴的差),y坐标同理。(但是这样只能在一定的位置实现“3D”,而且眼睛可以很容易的判断屏幕距离)

2.代码(因为成品代码太复杂,所以换另外一个程序简解)

头文件引用:

  1. #include<stdio.h>
  2. #include<windows.h>
  3. #include<graphics.h>
  4. #include<math.h>

初始化:

  1. main()
  2. {
  3. initgraph(450,300);
  4. int l=500;
  5. int ox=(getwidth()+1)/2;
  6. int oy=(getheight()+1)/2;
  7. int oz=70;
  8. typedef struct cd
  9. {
  10. int x=0;
  11. int y=0;
  12. }wdot;
  13. wdot wpoint[8];
  14. VECTOR3D point[8];
  15. int i,j,k;
  16. for(i=0;i<2;i++)
  17. {
  18. for(j=0;j<2;j++)
  19. {
  20. for(k=0;k<2;k++)
  21. {
  22. point[i*4+j*2+k].x=50*pow(-1,i);
  23. point[i*4+j*2+k].y=50*pow(-1,j);
  24. point[i*4+j*2+k].z=50*pow(-1,k);
  25. }
  26. }
  27. }

初始化中l为眼睛距屏幕的距离, ox和oy为屏幕中心位置坐标,oz为屏幕距坐标原点的距离,wdot类用来保存各个点在屏幕上的位置,VECTOR3D类为EGE图形库提供的3d类,用于保存3d点坐标,包含x,y,z三个float变量,如果用的是easyX,请自行定义(最好定义全局),后面三个for循环用于确定point数组中各个变量的位置,组成一个正方体。

绘制:

  1. while(1)
  2. {
  3. for(i=0;i<8;i++)
  4. {
  5. wpoint[i].x=ox+point[i].x*l/(l+oz-point[i].z);
  6. wpoint[i].y=oy+point[i].y*l/(l+oz-point[i].z);
  7. putpixel(wpoint[i].x,wpoint[i].y,RGB(255,255,255));
  8. }
  9. line(wpoint[0].x,wpoint[0].y,wpoint[2].x,wpoint[2].y);
  10. line(wpoint[0].x,wpoint[0].y,wpoint[4].x,wpoint[4].y);
  11. line(wpoint[2].x,wpoint[2].y,wpoint[6].x,wpoint[6].y);
  12. line(wpoint[4].x,wpoint[4].y,wpoint[6].x,wpoint[6].y);
  13. line(wpoint[0].x,wpoint[0].y,wpoint[1].x,wpoint[1].y);
  14. line(wpoint[1].x,wpoint[1].y,wpoint[3].x,wpoint[3].y);
  15. line(wpoint[2].x,wpoint[2].y,wpoint[3].x,wpoint[3].y);
  16. line(wpoint[3].x,wpoint[3].y,wpoint[7].x,wpoint[7].y);
  17. line(wpoint[6].x,wpoint[6].y,wpoint[7].x,wpoint[7].y);
  18. line(wpoint[5].x,wpoint[5].y,wpoint[7].x,wpoint[7].y);
  19. line(wpoint[5].x,wpoint[5].y,wpoint[1].x,wpoint[1].y);
  20. line(wpoint[5].x,wpoint[5].y,wpoint[4].x,wpoint[4].y);

用wpoint储存point对应坐标在屏幕上显示的位置,再用putpixel函数绘制点,后面的12个line函数用来绘制正方体的各个边。

旋转:

这里可以使用EGE自带的rotate_point3d_x(), rotate_point3d_y(),rotate_point3d_z()三个函数,分别为绕x,y,z轴旋转,参数格式:&VECTOR结构体,旋转角度*PI/180(弧度)。

  1. for(i=0;i<8;i++)
  2. {
  3. rotate_point3d_z(&point[i],3);
  4. }
  5. delay_fps(10);
  6. cleardevice();
  7. }
  8. }

easyX中没有 rotate_point3d_x(), rotate_point3d_y(),rotate_point3d_z()这三个函数,所以可以 自制turn3d_x(),turn3d_y(),turn3d_z()三个函数,输入格式:&VECTOR3D x,旋转角度

这里拿turn3d_y()来讲解:

  1. int turn3d_y(VECTOR3D *x,float a)
  2. {
  3. float tx=x->x;
  4. float tz=x->z;
  5. float ta=atan2(tx,tz)/PI*180+a;
  6. float r=sqrt(pow(tx,2)+pow(tz,2));
  7. x->x=sin(ta*PI/180)*r;
  8. x->z=cos(ta*PI/180)*r;
  9. }

 首先,引用VECTOR3D结构体x,旋转角度a两个参数;

然后定义tx,ty分别等于x的想坐标,x的y坐标;

之后用x的x轴,z轴和x与原点的连线构建一个二维三角形:

那么就可以用math库中的三角函数逆推函数atan2()输入角x的邻边和对边,返回弧度,需要把返回值/PI*180得到角度,保存置ta,再用ta加上旋转角度a,算出旋转后的角度(PI为EGE图形库中的定值,如果没有EGE,请自定义PI,atan2()返回后的弧度/PI*180后得到的角度可以大于90度) 

然后用勾股定理a^2+b^2=c^2算出Ox,保存到r中。

再画一个半径为r的圆:

那么x旋转后的位置永远都会在圆上, 所以可以根据三角函数用旋转后的角度ta和半径r求出旋转之后的位置,公式如下:

                                        x->x=sin(ta)*r;

                                        x->z=cos(ta)*r;

因为math库中的sin(),cos(),tan()函数输入的是弧度,所以要把ta*PI/180。

完整函数(最好定义全局,放在VECTOR3D结构体后面):

  1. int turn3d_y(VECTOR3D *x,float a)
  2. {
  3. float tx=x->x;
  4. float tz=x->z;
  5. float ta=atan2(tx,tz)/PI*180+a;
  6. float r=sqrt(pow(tx,2)+pow(tz,2));
  7. x->x=sin(ta*PI/180)*r;
  8. x->z=cos(ta*PI/180)*r;
  9. }
  10. int turn3d_x(VECTOR3D *x,float a)
  11. {
  12. float ty=x->y;
  13. float tz=x->z;
  14. float ta=atan2(tz,ty)/PI*180+a;
  15. float r=sqrt(pow(ty,2)+pow(tz,2));
  16. x->z=sin(ta*PI/180)*r;
  17. x->y=cos(ta*PI/180)*r;
  18. }
  19. int turn3d_z(VECTOR3D *x,float a)
  20. {
  21. float tx=x->x;
  22. float ty=x->y;
  23. float ta=atan2(tx,ty)/PI*180+a;
  24. float r=sqrt(pow(ty,2)+pow(tx,2));
  25. x->x=sin(ta*PI/180)*r;
  26. x->y=cos(ta*PI/180)*r;
  27. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/834690
推荐阅读
相关标签
  

闽ICP备14008679号