选择显示字体大小

一个简单的三维程序(c语言)

/*这是一个简单的三维引擎程序,模仿三个天体的运动,一个行星绕轴自转,两个卫星分别绕行星的
经线和纬线做公转。(在turboc3.0下编译成功)*/

#include<stdio.h>
#include<dos.h>
#include<conio.h>
#include<graphics.h>
#include<stdlib.h>
#include<alloc.h>
#include<time.h>
#include<bios.h>
#include<string.h>
#include<math.h>
#define esc 27  
#define f 80   //此数表示通常情况下操作者离电脑的距离(80厘米)
#define hight 480  //屏幕纵向分辩率
#define wide 640   //屏幕横向分辨率
#define pai 3.1415926   //圆周率
#define time 0.05   //转动间隔时间(每0.2秒转动5度)

typedef struct
{float x;
float y;
}_2d ;   //二维坐标点

typedef struct
{float x;
float y;
float z;
}_3d;   //三维坐标点

typedef struct
{int anglex;
int angley;
int anglez;
}axle;  //轴向量(angle x,y,z分别表示向量与x,y,z轴的夹角)

typedef struct
{//纬度圈由赤道加上南北半球的各四个纬度圈共9个纬度圈组成,经度等分成10个圈
  //所以用 二维数组g[9][10]来记录经纬度交点
_3d *g[9][10];  
  // temp[9][10]用来记录g[9][10]各点从三维变换到二维时的坐标  
_2d *temp[9][10];
_3d *center;  //自转中心坐标,即球心坐标
_3d *round_center;   //公转中心坐标
float r;   //球体半径
}globe;    //球体


float observe_mat[4][4],world_mat[4][4];  //观察坐标矩阵  与世界坐标矩阵
float sin[360],cos[360];  //存放三角函数值的两个数组,可以减少大量的浮点运算,以提高效率
size_t size2d,size3d,sizeaxle,sizeglobe; //各结构体的尺寸
_3d *observe;  //观察者所在的位置坐标
globe *moon1,*moon2,*earth;  //卫星1,卫星2,地球 三个球体
int zangle=5;  //转动角速度

//建立三角函数表
void create_table()  
{int i;
for(i=0;i<360;i++)
  {sin[i]=sin(i*pai/180);
   cos[i]=cos(i*pai/180);
   }
}

//初始化观察者位置
void init_observe()
{observe=(_3d *)malloc(size3d);
observe->x=160;
observe->y=0;
observe->z=0;
}

//把单位矩阵赋值给目标矩阵
void to_emat(float mat[4][4])
{int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
mat[i][j]=0;
for(i=0;i<4;i++)
mat[i][i]=1;
}

//把三维坐标点1的值赋给点2
void _3d_cpy(_3d *point1,_3d *point2)
{point1->x=point2->x;
point1->y=point2->y;
point1->z=point2->z;
}

//把二维坐标点1的值赋给点2
void _2d_cpy(_2d *point1,_2d *point2)
{point1->x=point2->x;
point1->y=point2->y;
}

//初始化各结构体的尺寸
void init_size()
{size2d=sizeof(_2d);
size3d=sizeof(_3d);
sizeaxle=sizeof(axle);
sizeglobe=sizeof(globe);
}

//初始化观察坐标矩阵与世界坐标矩阵(设定为单位矩阵)
void init_mat()
{int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
  {observe_mat[i][j]=0;
   world_mat[i][j]=0;
   }
for(i=0;i<4;i++)
{observe_mat[i][i]=1;
   world_mat[i][i]=1;
   }
}

//矩阵1乘矩阵2得到矩阵3
void mat_mult(float mat1[4][4],float mat2[4][4],float mat3[4][4])
{int i,j;
for(i=0; i<4; i++)
for(j=0; j<4; j++)
mat3[i][j]=mat1[i][0]*mat2[0][j]+mat1[i][1]*mat2[1][j]+mat1[i][2]*mat2[2][j]+mat1[i][3]*mat2[3][j];
}

//复制矩阵2到矩阵1
void mat_cpy(float mat1[4][4],float mat2[4][4])
{int i,j;
  for(i=0;i<=3;i++)
   for(j=0;j<=3;j++)
     mat1[i][j]=mat2[i][j];
}

//根据观察者位置建立观察坐标矩阵
void create_obmat()
{float _2dr,_3dr;
_2dr=pow((pow(observe->x,2)+pow(observe->y,2)),0.5);
_3dr=pow((pow(observe->x,2)+pow(observe->y,2)+pow(observe->z,2)),0.5);
observe_mat[0][0]=observe->y/_2dr*-1;
observe_mat[0][1]=observe->x*observe->z/_2dr/_3dr*-1;
observe_mat[0][2]=observe->x/_3dr*-1;
observe_mat[1][0]=observe->x/_2dr;
observe_mat[1][1]=observe->y*observe->z/_2dr/_3dr*-1;
observe_mat[1][2]=observe->y/_3dr*-1;
observe_mat[2][1]=_2dr/_3dr;
observe_mat[2][2]=observe->z/_3dr*-1;
observe_mat[3][2]=_3dr;
observe_mat[3][3]=1;
}

//三维坐标点对指定矩阵变换以得到新的三维坐标
void _3d_mult_mat(_3d *source,float mat[4][4])
{_3d *temp;
temp=(_3d *)malloc(size3d);
temp->x=source->x*mat[0][0]+source->y*mat[1][0]+source->z*mat[2][0]+mat[3][0];
temp->y=source->x*mat[0][1]+source->y*mat[1][1]+source->z*mat[2][1]+mat[3][1];
temp->z=source->x*mat[0][2]+source->y*mat[1][2]+source->z*mat[2][2]+mat[3][2];
_3d_cpy(source,temp);
}

//把三维坐标点从世界坐标变换成观察坐标
void world_to_ob(_3d *point1,_3d *point2)
{point2->x=point1->x*observe_mat[0][0]+point1->y*observe_mat[1][0]+
point1->z*observe_mat[2][0]+observe_mat[3][0];
point2->y=point1->x*observe_mat[0][1]+point1->y*observe_mat[1][1]+
point1->z*observe_mat[2][1]+observe_mat[3][1];
point2->z=point1->x*observe_mat[0][2]+point1->y*observe_mat[1][2]+
point1->z*observe_mat[2][2]+observe_mat[3][2];
}

//把三维坐标投影为二维坐标
void _3dto_2d(_3d *_3dpoint,_2d *_2dpoint)
{
_2dpoint->x=wide/2+f*_3dpoint->x/_3dpoint->z;
_2dpoint->y=hight/2-f*_3dpoint->y/_3dpoint->z;
}

//球体绕z轴转动后的坐标变换
void z_round(globe *globe,int angle)
{float z[4][4];
int i,j;
to_emat(z);
z[0][0]=cos[get_angle(angle)];
z[0][1]=sin[get_angle(angle)];
z[1][0]=-z[0][1];
z[1][1]=z[0][0];
for(i=0;i<9;i++)
for(j=0;j<10;j++)
_3d_mult_mat(globe->g[i][j],z);
}

//球体绕y轴转动后的坐标变换
void y_round(globe *globe,int angle)
{float y[4][4];
int i,j;
to_emat(y);
y[0][0]=cos[get_angle(angle)];
y[2][0]=sin[get_angle(angle)];
y[0][2]=-y[2][0];
y[2][2]=y[0][0];
for(i=0;i<9;i++)
for(j=0;j<10;j++)
_3d_mult_mat(globe->g[i][j],y);
}

//球体绕x轴转动后的坐标变换
void x_round(globe *globe,int angle)
{float x[4][4];
int i,j;
to_emat(x);
x[1][1]=cos[get_angle(angle)];
x[1][2]=sin[get_angle(angle)];
x[2][1]=-x[1][2];
x[2][2]=x[1][1];
for(i=0;i<9;i++)
for(j=0;j<10;j++)
_3d_mult_mat(globe->g[i][j],x);
}

//初始化图形模式
void init_gph()
{int gd=detect,gm;
initgraph(&gd,&gm,"d:\\turboc3");
setfillstyle(solid_fill,black);
bar(0,0,640,480);
}

//开辟一个用来存放球体数据的空间,并返回头地址
globe *create_globe()
{globe *p;
int i,j;
p=(globe *)malloc(sizeglobe);
for(i=0;i<9;i++)
for(j=0;j<10;j++)
  {p->g[i][j]=(_3d *)malloc(size3d);
   p->temp[i][j]=(_2d *)malloc(size2d);
  }
  p->center=(_3d *)malloc(size3d);
  p->round_center=(_3d *)malloc(size3d);
  return p;
}

//把一个角化为0-360的角,要求是它的三角函数值不变
int get_angle(int angle)
{angle&#37;=360;
if(angle<0)
  angle=360+angle;
  return angle;
}

//给一个三维坐标赋值
_3d *get_3dpoint(float x0,float y0,float z0)
{_3d *p;
p=(_3d *)malloc(size3d);
p->x=x0;
p->y=y0;
p->z=z0;
return p;
}

//给一个轴向量赋值
axle *get_axle(int qx,int qy,int qz)
{axle *p;
p=(axle *)malloc(sizeaxle);
p->anglex=qx;
p->angley=qy;
p->anglez=qz;
return p;
}

//从世界坐标原点平移球体到指定点(球体初始化时用)
void place_globe(globe *globe)
{float tempf[4][4];
int i,j;
to_emat(tempf);
tempf[3][0]=(globe->center)->x;
tempf[3][1]=(globe->center)->y;
tempf[3][2]=(globe->center)->z;
for(i=0;i<9;i++)
for(j=0;j<10;j++)
_3d_mult_mat(globe->g[i][j],tempf);
}

//球体初始化
void init_globe(globe *globe,float r,_3d *thecenter,_3d *rnd_center)
{int i,j;
  //globe=(globe *)malloc(sizeglobe);
  globe->r=r;
  for(i=-4;i<=4;i++)
  for(j=0;j<=9;j++)
  {(globe->g[i+4][j])->x=r*cos[get_angle(i*18)]*cos[get_angle(j*36)];
   (globe->g[i+4][j])->y=r*cos[get_angle(i*18)]*sin[get_angle(j*36)];
   (globe->g[i+4][j])->z=r*sin[get_angle(i*18)];
  }
  _3d_cpy(globe->center,thecenter);
  _3d_cpy(globe->round_center,rnd_center);
  place_globe(globe);
}

//把球体上的点从世界坐标变成观察坐标,然后再把观察坐标投影为二维坐标
void wglobe_to_2d(globe *globe)
{int i,j;
_3d *point;
point=(_3d *)malloc(size3d);
for(i=0;i<9;i++)
for(j=0;j<10;j++)
{world_to_ob(globe->g[i][j],point);
  _3dto_2d(point,globe->temp[i][j]);
}
}

//用指定颜色绘制球体
void draw_globe(globe *g,int color)
{int i,j,n;
wglobe_to_2d(g);
setcolor(color);
for(i=0;i<9;i++)
  for(j=0;j<10;j++)
  {n=j+1;
   if(n==10)
   n=0;
  line((g->temp[i][j])->x,(g->temp[i][j])->y,(g->temp[i][n])->x,(g->temp[i][n])->y);
  }
for(j=0;j<10;j++)
for(i=0;i<9;i++)
{n=i+1;
  if(n==9)
  n=0;
  line((g->temp[i][j])->x,(g->temp[i][j])->y,(g->temp[n][j])->x,(g->temp[n][j])->y);
}
}


//初始化
void init_start()
{int i;
_3d *p1,*p2,*p3,*p4;
p1=(_3d *)malloc(size3d);
p2=(_3d *)malloc(size3d);
p3=(_3d *)malloc(size3d);
p4=(_3d *)malloc(size3d);
init_gph();
setcolor(red);
circle(320,240,200);
init_size();
create_table();
init_observe();
init_mat();
create_obmat();
moon1=create_globe();
moon2=create_globe();
earth=create_globe();
p1=get_3dpoint(0,100,0);
p2=get_3dpoint(0,-100,0);
p3=get_3dpoint(0,0,0);
p4=get_3dpoint(0,0,0);
init_globe(moon1,20,p1,p4);
init_globe(moon2,20,p2,p4);
init_globe(earth,50,p3,p4);
draw_globe(earth,blue);
draw_globe(moon1,darkgray);
draw_globe(moon2,cyan);
}


//各球体随时间变化而在各自轨道上运行的动画(按任意键退出)
void roll()
{clock_t start,end;
int angle=0;
start=clock();
while(!kbhit())
  { end=clock();
   if((end-start)/clk_tck>time)
     {draw_globe(moon1,black);
     draw_globe(moon2,black);
      draw_globe(earth,black);
       z_round(moon1,zangle);
       x_round(moon2,zangle);
       y_round(earth,zangle);
angle+=5;
if(get_angle(angle)<180)
       {draw_globe(moon1,darkgray);
draw_globe(earth,blue);
draw_globe(moon2,cyan);
}
       else
{draw_globe(moon2,cyan);
  draw_globe(earth,blue);
  draw_globe(moon1,darkgray);
  }
       start=clock();
     }
   }
}

//主函数
void main()
{init_start();
roll();
getch();
closegraph();
}


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons