/*这是一个简单的三维引擎程序,模仿三个天体的运动,一个行星绕轴自转,两个卫星分别绕行星的
经线和纬线做公转。(在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%=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 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器