`

TC 3D模型绘图

 
阅读更多

/*这个程序用于描述一个用户给定方程的3D物体,用户可以通过键盘控制这个3D体的
运动来了解物体的表面细节,程序定义的控制键如下:
a、s、w、d:是3D体左、后、前、右移动(默认)
c:功能切换键,当奇数次按下这个键时,a、s、w、d:得功能为左、下、上、右以用户为中心旋转
小键盘对应的数字键,使得3D体沿自己的体心对应旋转
0:退出该程序
其它任意键:使3D体保持当前状态静止*/

/*下面包含头文件*/
#include <math.h>
#include <stdio.h>
#include <graphics.h>

#define PI 3.1415926
#define MAXROW 32
#define MAXLINE 16

struct _3DPoint
{
float x;
float y;
float z;
};

struct _3DObjPosition
{
//空间位移坐标
struct _3DPoint point;
//观众姿态角
double User_angelY;
double User_angelZ;
//自心姿态角
double angelY;
double angelZ;
};

struct _2DPoint
{
float x;
float y;
};

struct _ProccessBox
{
struct _2DPoint point;
int Longth;
int Higth;
int BackGColor;
int MyColor;
char MyText[13];
};

float GetResult(float r,float angel1,float angel2);
void GraphicsInit(int mode,int driver); /*图像初始化的函数*/
void ProccessBoxInit(struct _ProccessBox *p); /*进度条初始化函数*/
void ProccessBoxSet(int n,struct _ProccessBox *p); /*进度条设置函数*/
float HalfWay(float angel1,float angel2); /*二分法求解方程函数*/
void Init3DObj(struct _3DObjPosition *p); /*初始化物体的姿态数据*/
void Change3DObjPosition(char order,struct _3DObjPosition *p); /*3D物体姿态参数设置函数*/
void Change3dTO2D(struct _3DPoint SousePoint,struct _3DObjPosition P,struct _3DPoint *ArmPoint);/*3D数据转2D的函数*/
void ShowSmallMap(void);

void main(void)
{
int i, j; /*循环变量*/
int l, n, k=0; /*程序中使用的状态标记变量*/
char PressKey='6';
float AngelArpha, AngelThetar; /*角度变量*/
float r,SmallMap[2][2]={0};

struct _ProccessBox Proccess;
struct _3DPoint SourceData[MAXROW][MAXLINE]; /*记录物体空间点阵的原始计算数据*/
struct _3DObjPosition Object;
struct _3DPoint TempPoint;
struct _3DPoint ChangedData[MAXROW][MAXLINE][2]={0}; /*记录经过用户空间变换后的点阵数据*/

ProccessBoxInit(&Proccess);
Init3DObj(&Object);

GraphicsInit(VGAHI,VGA); /*图形模式初始化*/

/*下面这段代码用于计算用户给出的曲面的空间点阵*/
cleardevice(); /*清屏*/
for(i=0; i<MAXROW; i++) /*按角度开始求解方程*/
{
ProccessBoxSet(3*i, &Proccess);
delay(60);

for(j=0; j<MAXLINE; j++)
{
AngelThetar = (PI / (MAXLINE -1)) * (j- (MAXLINE -1)/2.0);
AngelArpha = (PI / (MAXROW -1)) * i * 2;
r=HalfWay(AngelThetar,AngelArpha);
/*计算完成之后将点阵保存进数组*/
SourceData[i][j].x = r * cos(AngelThetar) * cos(AngelArpha);
SourceData[i][j].y = r * cos(AngelThetar) * sin(AngelArpha);
SourceData[i][j].z = r * sin(AngelThetar);
}
}

/*下面开始接受用户的空间在屏幕上显示动态的图像*/
cleardevice();
l = 0;
AngelThetar = 0;

for( ; ; ) /*开始处理用户的控制*/
{
if(kbhit()) PressKey = getch();/*判断用户是否有键入*/
switch(PressKey)
{
case 'c': /*切换成转动或者移动,也就是改变l=0或者=1*/
case 'C': {
l = (l-1) * (l-1);
PressKey = 'q';
break;
}
case '0': {
exit(0);
break;
}/*退出程序*/
default: { if(PressKey < '0' || PressKey > '9')
{//非数字
if(l==1)
{//小写
if(PressKey<'a') PressKey += 'a' -'A';
}else
{//大写
if(PressKey>='a') PressKey -= 'a' -'A';
}
}
Change3DObjPosition(PressKey, &Object);
}
}

/*下面一段为三维向二维转换*/
k = (1 - k) * (1 - k);
for(i=0; i<MAXROW; i++) /*开始3D->2D的转换*/
{
for(j=0; j<MAXLINE; j++)
{
Change3dTO2D(SourceData[i][j], Object,&TempPoint);
ChangedData[i][j][k].x = TempPoint.x + 320; /*计算完后进行3d->2d*/
ChangedData[i][j][k].y = TempPoint.y + 240; /*这里的320和240是将原点放到屏幕中间*/
ChangedData[i][j][k].z = TempPoint.z;
}
}

n=(1-k) * (1-k);
for(i=0; i<MAXROW; i++) /*开始作图*/
{
for(j=0; j<MAXLINE-1; j++)
{
if((ChangedData[i][j + 1][n].z > 0) && (ChangedData[i][j][n].z > 0))
{
setcolor(0);
line(ChangedData[i][j][n].x, ChangedData[i][j][n].y, ChangedData[i][j+1][n].x, ChangedData[i][j + 1][n].y);
}

if((ChangedData[i][j+1][k].z > 0) && (ChangedData[i][j][k].z > 0))
{
setcolor(9);
line(ChangedData[i][j][k].x, ChangedData[i][j][k].y, ChangedData[i][j+1][k].x, ChangedData[i][j + 1][k].y);
}

if(i < (MAXROW-1))
{
if((ChangedData[i+1][j][n].z > 0) && (ChangedData[i][j][n].z > 0))
{
setcolor(0);
line(ChangedData[i][j][n].x, ChangedData[i][j][n].y, ChangedData[i + 1][j][n].x, ChangedData[i + 1][j][n].y);
}
if((ChangedData[i+1][j][k].z > 0) && (ChangedData[i][j][k].z > 0))
{
setcolor(9);
line(ChangedData[i][j][k].x, ChangedData[i][j][k].y, ChangedData[i+1][j][k].x, ChangedData[i+1][j][k].y);
}
}

if(i == MAXROW-1)
{
if((ChangedData[0][j][n].z > 0) && (ChangedData[i][j][n].z > 0))
{
setcolor(0);
line(ChangedData[i][j][n].x, ChangedData[i][j][n].y, ChangedData[0][j][n].x, ChangedData[0][j][n].y);
}
if((ChangedData[0][j][k].z > 0) && (ChangedData[i][j][k].z > 0))
{
setcolor(9);
line(ChangedData[i][j][k].x, ChangedData[i][j][k].y, ChangedData[0][j][k].x, ChangedData[0][j][k].y);
}
}
}
}
/*插入左上角小地图*/
SmallMap[k][0] = Object.point.x * cos(Object.User_angelZ) - Object.point.y * sin(Object.User_angelZ);
SmallMap[k][1] = sin(Object.User_angelZ) * Object.point.x + cos(Object.User_angelZ) * Object.point.y;
SmallMap[k][1] = SmallMap[k][1] * cos(Object.User_angelY);
setcolor(0);
circle (SmallMap[n][0] / 20 + 26 , 26 - SmallMap[n][1] / 20, 5);
setcolor (12);
circle (SmallMap[k][0] / 20 + 26, 26 - SmallMap[k][1] / 20, 5);
ShowSmallMap();
}
}
void ProccessBoxInit(struct _ProccessBox *p)
{
//数据初始化
(*p).point.x =230;
(*p).point.y =240;
(*p).Longth =100;
(*p).Higth =10;
(*p).BackGColor =0;
(*p).MyColor =1;
strcpy((*p).MyText,"complete %");
}

void Init3DObj(struct _3DObjPosition *p)
{
(*p).point.x =0;
(*p).point.y =0;
(*p).point.z =0;
(*p).User_angelY =0;
(*p).User_angelZ =0;
(*p).angelY =0;
(*p).angelZ =0;
}

void ShowSmallMap()
{
setcolor (14);
circle (26, 26, 25);
line (21, 26, 31, 26);
line (26, 21, 26, 31);
line (310,240,330,240);
line (320,230,320,250);
setcolor (2);
line (26, 26, 17, 5);
line (26, 26, 35, 5);
}

void Change3dTO2D(struct _3DPoint SourcePoint,struct _3DObjPosition P,struct _3DPoint *ArmPoint)
{
struct _3DPoint TempPoint[4];
float Deep;
TempPoint[0].x = SourcePoint.x; /*承接求解数据*/
TempPoint[0].y = SourcePoint.y;
TempPoint[0].z = SourcePoint.z;

TempPoint[1].x = TempPoint[0].x * cos(P.angelY) - TempPoint[0].z * sin(P.angelY); /*延y轴的偏转计算*/
TempPoint[1].z = sin(P.angelY) * TempPoint[0].x + cos(P.angelY) * TempPoint[0].z;
TempPoint[1].y = TempPoint[0].y;

TempPoint[2].x = TempPoint[1].x * cos(P.angelZ) - TempPoint[1].y * sin(P.angelZ) + P.point.x; /*延z轴的偏转计算*/
TempPoint[2].y = sin(P.angelZ) * TempPoint[1].x + cos(P.angelZ) * TempPoint[1].y + P.point.y;
TempPoint[2].z = TempPoint[1].z + P.point.z;

TempPoint[3].x = TempPoint[2].x * cos(P.User_angelZ) - TempPoint[2].y * sin(P.User_angelZ); /*实现定点转动*/
TempPoint[1].y = sin(P.User_angelZ) * TempPoint[2].x + cos(P.User_angelZ) * TempPoint[2].y;

TempPoint[3].y = TempPoint[1].y * cos(P.User_angelY) - TempPoint[2].z * sin(P.User_angelY);
TempPoint[2].z = sin(P.User_angelY) * TempPoint[1].y + cos(P.User_angelY) * TempPoint[2].z;

Deep = 1/ (0.1+0.001*pow (TempPoint[3].x*TempPoint[3].x+TempPoint[3].y*TempPoint[3].y+TempPoint[2].z*TempPoint[2].z,0.5)); /*这一行用于远小近大的透视效果计算*/

TempPoint[2].x = TempPoint[3].x * Deep;
TempPoint[2].z = TempPoint[2].z * Deep;

(*ArmPoint).x=TempPoint[2].x;
(*ArmPoint).y=TempPoint[2].z;
(*ArmPoint).z=TempPoint[3].y;
}

void Change3DObjPosition(char order,struct _3DObjPosition *p)
{
switch(order)
{
case 'w': {
(*p).User_angelY -=0.002; /*向下转动*/
break;
}
case 'W': {
if(pow ((*p).point.y-1, 2) + pow ((*p).point.x ,2) < 490000) (*p).point.y -= 1; /*向前平移*/
break;
}
case 'a': {
(*p).User_angelZ -= 0.002; /*向右转动*/
break;
}
case 'A': {
if(pow ((*p).point.y, 2) + pow ((*p).point.x+1 ,2) < 490000) (*p).point.x += 1; /*向左平移*/
break;
}
case 's': {
(*p).User_angelY +=0.002; /*向上转动*/
break;
}
case 'S': {
if(pow ((*p).point.y+1, 2) + pow ((*p).point.x ,2) < 490000) (*p).point.y += 1; /*向后平移*/
break;
}
case 'd': {
(*p).User_angelZ += 0.002; /*向左转动*/
break;
}
case 'D': {
if(pow ((*p).point.y, 2) + pow ((*p).point.x-1 ,2) < 490000) (*p).point.x -= 1; /*向右平移*/
break;
}
case '6': {
(*p).angelZ += 0.01;
break;
}/*左转*/
case '8': {
(*p).angelY += 0.01;
break;
}/*上转*/
case '2': {
(*p).angelY -= 0.01;
break;
}/*下转*/
case '4': {
(*p).angelZ -= 0.01;
break;
}/*右转*/
case '9': {
(*p).angelZ += 0.01;
(*p).angelY += 0.01;
break;
}/*右上*/
case '1': {
(*p).angelZ -= 0.01;
(*p).angelY -= 0.01;
break;
}/*左下*/
case '7': {
(*p).angelZ -= 0.01;
(*p).angelY += 0.01;
break;
}/*左上*/
case '3': {
(*p).angelZ += 0.01;
(*p).angelY -= 0.01;
break;
}/*右下*/
default: ; /*其它按键,为暂停*/
}
}

float HalfWay(float angel1,float angel2)
{//该函数的求解范围为0到150
float HeadData,MilldData,EndData;
float r[3];
r[0] =0;
HeadData = GetResult(r[0],angel1,angel2);
r[1] =150;
EndData = GetResult(r[1],angel1,angel2);
r[2] =150;
if(HeadData * EndData <0)
{
for(;;)
{
r[2] = (r[0] + r[1]) / 2;
MilldData = GetResult(r[2],angel1,angel2);
if(MilldData * MilldData < 0.00001) break;
if(MilldData * HeadData >= 0)
{
HeadData = MilldData;
r[0] = r[2];
}else
{
EndData = MilldData;
r[1] = r[2];
}
}
}
return r[2];
}

void ProccessBoxSet(int n,struct _ProccessBox *p)
{
rectangle((*p).point.x -1, (*p).point.y -1, (*p).point.x + (*p).Longth +1, (*p).point.y +(*p).Higth +1);
setfillstyle(1, (*p).MyColor);
bar((*p).point.x, (*p).point.y, (*p).point.x + (*p).Longth*n /100, (*p).point.y +(*p).Higth);
(*p).MyText[10] = n % 10 +48;
(*p).MyText[9] = n / 10 +48;
setfillstyle(1, (*p).BackGColor);
bar ((*p).point.x + (*p).Longth +10, (*p).point.y, (*p).point.x + (*p).Longth +10+104, (*p).point.y +(*p).Higth);
outtextxy ((*p).point.x + (*p).Longth +10, (*p).point.y, (*p).MyText);
}

void GraphicsInit(int mode,int driver)
{
registerbgidriver(EGAVGA_driver);/*这一行代码是为了包含显示驱动,当程序编译在这一行出错时,请屏蔽这一行代码*/
initgraph(&driver, &mode, "E://tc2//BGI");/* 需要正确的BGI路径*/
}

/*下面的函数用于计算用户给出的曲面方程的三维坐标*/
float GetResult(float r,float angel1,float angel2)
{
float result;
struct _3DPoint point;
point.x = r * cos(angel1) * cos(angel2);
point.y = r * cos(angel1) * sin(angel2);
point.z = r * sin(angel1);
/* result = point.x * point.x + point.y * point.y +
+ point.z * point.z - 10000;*/

result = point.x * point.x + point.y * point.y + 50 * point.x
- 50 * pow(point.x * point.x + point.y * point.y,0.5)
+ point.z * point.z - 1;/*此处输入用户方程*/
return result;
}

 

本文来自CSDN博客:http://blog.csdn.net/xiajia/archive/2005/04/14/347905.aspx

分享到:
评论

相关推荐

    CAD使用说明书-技术部.doc

    4. 数据输入和导出:如`FX`保存文件,`CXX`保存3D模型为ACIS格式。 这些快捷命令和步骤为CAD的基本操作,熟练掌握能大大提高设计效率。在实际操作中,用户应根据具体需求灵活运用,并结合CAD软件的其他功能,如捕捉...

    OpenGL入门学习

    通过学习OpenGL,开发者可以掌握如何使用顶点、颜色、纹理、光照、深度测试等概念,创建复杂的3D模型和交互式场景。随着技术的发展,OpenGL也在不断更新,如OpenGL ES针对嵌入式设备,以及现代的OpenGL 4.x版本引入...

    OPENGL编程入门

    随着深入学习,可以逐步掌握更多高级特性,如顶点数组、纹理映射、光照模型、深度测试、着色器等,从而实现更复杂的3D图形效果。此外,学习OpenGL的过程中,可以参考官方网站和其他在线资源,如教程、示例代码和论坛...

    计算机图形标准.pdf

    而ANSI是一个美国的非营利性组织,负责协调和促进美国的标准化活动,其下属的不同技术委员会(如TC97)负责制定各种标准,包括计算机图形学中的相关标准。 通过上述内容的解读,我们可以看到计算机图形学领域内众多...

    值得参考CAD快捷键

    24. `SZ`:收缩率设置 - 调整收缩率参数,适用于3D打印或其他制造过程。 25. `C`:参照 - 添加参照对象,如导入其他设计或使用现有模型作为基础。 26. `SA`:精度设置 - 设置绘图的精度,影响测量和设计细节。 27. `...

    OpenGL入门教程

    1. **与C语言的深度融合**:OpenGL的命令集最初设计时即采用了C语言函数的形式,这使得熟悉C语言的开发者能够快速上手,相较于传统的图形库,如TC的`#include&lt;graphics.h&gt;`,使用OpenGL绘制图形更为直观且高效。...

    计算机图形学考试要点

    4. **CGI (Computer Graphics Interface)**:由ISO TC97组提出的标准,定义了图形软件与图形输入输出设备之间的接口。 5. **CGM (Computer Graphics Metafile)**:规定了记录图形信息的数据文件格式,以便于图形数据...

Global site tag (gtag.js) - Google Analytics