/* WIN-TC BGI 图形编程模板 */
#include "Conio.h"
#include "graphics.h"
#include "math.h"
#include "bios.h"
#define closegr closegraph
#define PI 3.1415926
#define ESC 0x11b
#define UP 0x4800
#define DOWN 0x5000
#define RIGHT 0x4d00
#define LEFT 0x4b00
/*视点在用户坐标系中的球坐标变量,Rol为用户坐标系的原点与视点的距离,DE为视距(视点与屏幕中心)*/
/*int Theta,Phi,Rol,DE; */
/*#define Theta 30
#define Phi 35
#define Rol 500
#define DE 100
#define DeltaTheta 5
#define DeltaPhi 5 */
int Theta=45 ;
int Phi=30;
int Rol=500;
int DE= 100;
int DeltaTheta= 5;
int DeltaPhi=5;
int xcenter,ycenter;
/*存储计算用户坐标系点到观察坐标系的坐标值公式中的正余弦值
公式如下:
T(变换)= -sin(Theta) -cos(Theta)sin(Phi) -cos(Theta)cos(Phi) 0
-cos(Theta) -sin(Theta)sin(Phi) -sin(Theta)cos(Phi) 0
0 cos(Phi) -sin(Theta) 0
0 0 Rol 1
a1= sin(Theta);
a2= sin(Phi);
a3= cos(Theta);
a4= cos(Phi);
a5=sin(Phi)*cos(Theta)=a2*a3;
a6=sin(Theta)*sin(Phi)=a1*a2;
a7=cos(Theta)*cos(Phi)=a3*a4;
a8=sin(Theta)*cos(Phi)=a1*a4;
=====================================
x0,y0,z0为变换后观察坐标系下的坐标,x,y,z为变换前用户坐标系下的坐标,xProj,yProj,zProj为投影屏幕上的坐标值
x0=-a1*x+a3*y;
y0=-a5*x-a6*y+a4*z;
z0=-a7*x-a6*y-a2*z+Rol;
*/
float a1,a2,a3,a4,a5,a6,a7,a8;
int M,N,P;/*视点在用户坐标系中的坐标(M,N,P)*/
/*长方体的数据结构*/
struct point3d
{
int x;
int y;
int z;
}Vertics[9];
int Faces[7][5];
/*屏幕坐标系需要4个点PMZB[0]为原点,1,2,3分别为x,y,z轴*/
struct point3d PMZB[4];
int flag=0;/*标记坐标是否已求出*/
void initgr(void) /* BGI初始化 */
{
int gd = DETECT, gm = 0; /* 和gd = VGA,gm = VGAHI是同样效果 */
registerbgidriver(EGAVGA_driver);/* 注册BGI驱动后可以不需要.BGI文件的支持运行 */
initgraph(&gd, &gm, "");
xcenter=getmaxx()/2;
ycenter=getmaxy()/2;
}
/*初始化长方体*/
void initCuboid(void)
{ /*定点坐标初始化*/
Vertics[1].x=200;Vertics[1].y=0;Vertics[1].z=0;
Vertics[2].x=200;Vertics[2].y=200;Vertics[2].z=0;
Vertics[3].x=200;Vertics[3].y=200;Vertics[3].z=200;
Vertics[4].x=200;Vertics[4].y=0;Vertics[4].z=200;
Vertics[5].x=0;Vertics[5].y=0;Vertics[5].z=0;
Vertics[6].x=0;Vertics[6].y=200;Vertics[6].z=0;
Vertics[7].x=0;Vertics[7].y=200;Vertics[7].z=200;
Vertics[8].x=0;Vertics[8].y=0;Vertics[8].z=200;
Faces[1][1]=1;Faces[1][2]=2;Faces[1][3]=3;Faces[1][4]=4;
Faces[2][1]=2;Faces[2][2]=6;Faces[2][3]=7;Faces[2][4]=3;
Faces[3][1]=5;Faces[3][2]=8;Faces[3][3]=7;Faces[3][4]=6;
Faces[4][1]=1;Faces[4][2]=4;Faces[4][3]=8;Faces[4][4]=5;
Faces[5][1]=3;Faces[5][2]=7;Faces[5][3]=8;Faces[5][4]=4;
Faces[6][1]=1;Faces[6][2]=5;Faces[6][3]=6;Faces[6][4]=2;
}
void initProject()
{
float th,ph;
th=PI*Theta/180.0;
ph=PI*Phi/180.0;
a1= sin(th);
a2= sin(ph);
a3= cos(th);
a4= cos(ph);
a5=a2*a3;
a6=a1*a2;
a7=a3*a4;
a8=a1*a4;
M=Rol*a7;
N=Rol*a8;
P=Rol*a2;
}
/*求函数点的投影坐标值*/
void project(int x,int y,int z,float * xProj,float * yProj)
{ float x0,y0,z0;
x0=-a1*x+a3*y;
y0=-a5*x-a6*y+a4*z;
z0=-a7*x-a6*y-a2*z+Rol;
/* *xProj=x0*DE/z0;
*yProj=DE*y0/z0;
*/
*xProj=1.35*x0;
*yProj=1.35*y0;
}
void projectPMZB(int x,int y,int z,int th,int phi,int r,float * xProj,float *yProj,float * zProj)
{
float b1,b2,b3,b4,b5,b6,b7,b8;
float x0,y0,z0;
float t,p;
t=PI*th/180.0;
p=PI*phi/180.0;
b1= sin(t);
b2= sin(p);
b3= cos(t);
b4= cos(p);
b5=b2*b3;
b6=b1*b2;
b7=b3*b4;
b8=b1*b4;
x0=-b1*x+b3*y;
y0=-b5*x-b6*y+b4*z;
z0=-b7*x-b6*y-b2*z+r;
*xProj=1.35*x0;
*yProj=1.35*y0;
*zProj=z0;
}
void myLineto(int x,int y,int z)
{
float xProj,yProj;
int xScreen,yScreen;
project(x,y,z,&xProj,&yProj);
xScreen=floor(0.5+xProj+xcenter);
yScreen=floor(0.5+ycenter-yProj);
/* printf("%f %f\n",xProj,yProj);
printf("%d %d\n",xScreen,yScreen); */
putpixel(xScreen,yScreen,4);
lineto(xScreen,yScreen);
}
void myMoveto(int x,int y,int z)
{
float xProj,yProj;
int xScreen,yScreen;
project(x,y,z,&xProj,&yProj);
xScreen=floor(0.5+xProj+xcenter);
yScreen=floor(0.5+ycenter-yProj);
/*printf("%f %f\n",xProj,yProj);
printf("%d %d\n",xScreen,yScreen); */
putpixel(xScreen,yScreen,4);
moveto(xScreen,yScreen);
}
/*画长方体上的第f个面*/
void drawFace(int f)
{
int i;
int num;/*顶点序号*/
int x,y,z,x0,y0,z0;
for(i=1;i<=4;i++)
{
num=Faces[f][i];
x=Vertics[num].x;
y=Vertics[num].y;
z=Vertics[num].z;
if(i==1)
{myMoveto(x,y,z);
x0=x;
y0=y;
z0=z;
}
else myLineto(x,y,z);
}
myLineto(x0,y0,z0);
}
/*计算观察方向矢量与长方体表面矢量的数量积*/
long scaleProduct(int f)
{ /*求出平面f的法矢量*/
long px,py,pz,qx,qy,qz;
long pqx,pqy,pqz;
long product;
int dot1,dot2,dot3;
dot1=Faces[f][1];
dot2=Faces[f][2];
dot3=Faces[f][3];
/*一个向量*/
px=Vertics[dot2].x-Vertics[dot1].x;
py=Vertics[dot2].y-Vertics[dot1].y;
pz=Vertics[dot2].z-Vertics[dot1].z;
/*另一个向量*/
qx=Vertics[dot3].x-Vertics[dot1].x;
qy=Vertics[dot3].y-Vertics[dot1].y;
qz=Vertics[dot3].z-Vertics[dot1].z;
/*计算法矢
=======================
向量p*向量q=i j k
px py pz
qx qy qz
===========================
*/
pqx=(long)py*qz-(long)pz*qy;
pqy=-(long)px*qz+(long)pz*qx;
pqz=(long)px*qy-(long)py*qx;
product=M*pqx+N*pqy+P*pqz;
/*printf("(%ld %ld %ld)*\n(%ld %ld %ld)\n=(%ld %ld %ld)\n",px,py,pz,qx,qy,qz,pqx,pqy,pqz);
printf("product=%ld",M*pqx+N*pqy+P*pqz); */
return product;
}
/*画用户坐标*/
void drawCoordinateOfUser()
{
float xProj,yProj,zProj;
if(flag==0)
{
projectPMZB(0,0,0,45,30,Rol,&xProj,&yProj,&zProj);
PMZB[0].x=floor(0.5+xProj+xcenter);
PMZB[0].y=floor(0.5+ycenter-yProj);
PMZB[0].z=floor(zProj+0.5);
projectPMZB(600,0,0,45,30,Rol,&xProj,&yProj,&zProj);
PMZB[1].x=floor(0.5+xProj+xcenter);
PMZB[1].y=floor(0.5+ycenter-yProj);
PMZB[1].z=floor(zProj+0.5);
projectPMZB(0,600,0,45,30,Rol,&xProj,&yProj,&zProj);
PMZB[2].x=floor(0.5+xProj+xcenter);
PMZB[2].y=floor(0.5+ycenter-yProj);
PMZB[2].z=floor(zProj+0.5);
projectPMZB(0,0,480,45,30,Rol,&xProj,&yProj,&zProj);
PMZB[3].x=floor(0.5+xProj+xcenter);
PMZB[3].y=floor(0.5+ycenter-yProj);
PMZB[3].z=floor(zProj+0.5);
flag=1;
}
/* printf("%d %d %d\n",PMZB[0].x,PMZB[0].y,PMZB[0].z);
printf("%d %d %d\n",PMZB[1].x,PMZB[1].y,PMZB[1].z);
printf("%d %d %d\n",PMZB[2].x,PMZB[2].y,PMZB[2].z);
printf("%d %d %d\n",PMZB[3].x,PMZB[3].y,PMZB[3].z); */
setlinestyle(SOLID_LINE,0,NORM_WIDTH);
moveto(PMZB[0].x,PMZB[0].y);
lineto(PMZB[1].x,PMZB[1].y);
moveto(PMZB[0].x,PMZB[0].y);
lineto(PMZB[2].x,PMZB[2].y);
moveto(PMZB[0].x,PMZB[0].y);
lineto(PMZB[3].x,PMZB[3].y);
/*myMoveto(0,0,0);
myLineto(600,0,0);
myMoveto(0,0,0);
myLineto(0,600,0);
myMoveto(0,0,0);
myLineto(0,0,480); */
}
/*在屏幕上画消隐长方体*/
void drawCuboid()
{
int f;
/* drawFace(2);
scaleProduct(2);*/
for(f=1;f<=6;f++)
{
if(scaleProduct(f)>0)
{
setlinestyle(SOLID_LINE,0,NORM_WIDTH);
drawFace(f);
}
else
{
setlinestyle(DOTTED_LINE,0,NORM_WIDTH);
drawFace(f);
}
}
}
int main(void)
{ int i;
int key;
initgr(); /* BGI初始化 */
initCuboid();/*初始化长方体*/
do
{ if(key==LEFT)
{
Theta+=DeltaTheta;
}else if(key==RIGHT)
{
Theta-=DeltaTheta;
}
cleardevice();
initProject();/*初始化映射变量*/
setcolor(RED);
drawCoordinateOfUser();/*画用户坐标系*/
setcolor(WHITE);
drawCuboid();/*画长方体*/
while(bioskey(1)==0);
}while((key=bioskey(0))!=ESC);
/*
评论1
最新资源