Em[i][j]=Em[i][j]-Em[k][j]*p1;
}
}
coefficient[exp]=Em[exp][exp+1]/Em[exp][exp];
for(int l=exp-1;l>=1;l--) //回代求解
coefficient[l]=(Em[l][exp+1]-F(coefficient,l+1,exp))/Em[l][l]; }
double F(double c[],intl,int m)//供CalEquation函数调用
{
double sum=0;
for(inti=l;i<=m;i++)
sum+=Em[l-1][i]*c[i];
return sum;
}
(3)程序运行界面截图:
(4)调试中出现的问题及解决方法:
通过网上资料查找首先了解什么是最小二乘法的多项式拟合。拟合过程中随着高阶逐渐增加拟合的曲线也会存在病态,所以有时候对比较高的高阶需要压缩后在拟合。这里是没有经过压缩的拟合,我会继续深入研究更高阶的曲线拟合。EMatrix这个函数的ex要加1,就是说如果要求四次就要ex要写5。
二.用OpenGL的图形库设计长方体。
1.长方体的六个面对应六张不同的图像,可以通过键盘进行上下左右旋转。
(1)程序设计流程图:
(2)(部分)源程序:
#include // Windows的头文件
#include // OpenGL32库的头文件
#include
#include
#pragma comment(lib, "glaux.lib") // GLaux连接库
#include // GLaux库的头文件
static GLfloatxRot = 0.0f; //建立x轴的坐标
static GLfloatyRot = 0.0f; //建立y轴的坐标
GLuint texture[6]; //纹理填充
AUX_RGBImageRec *LoadBMP(char *FileName) //加载.bmp图像,返回该图像的指针
{
FILE *File = NULL;
if(!FileName)
return NULL;
File = fopen(FileName,"r");
if (File)
{
fclose(File);
returnauxDIBImageLoad(FileName);
}
return NULL;
}
//载入.bmp格式的贴图纹理
intLoadGLTextures() // 载入位图(调用上面的代码)并转换成纹理
{
int Status = FALSE;
char *bmpFile[6] = {"1.bmp","2.bmp","3.bmp", //创建纹理的存储空间
"4.bmp","5.bmp","6.bmp"};
AUX_RGBImageRec *TextureImage[6] = {NULL,NULL,NULL,NULL,NULL,NULL}; for(inti = 0;i < 6;++i)
{
//memset(TextureImage[i],0,sizeof(void*) * 1);//set the point to NULL
if (TextureImage[i] = LoadBMP(bmpFile[i]))
{
Status = TRUE;
glGenTextures(1,&texture[i]); //命名纹理对象
glBindTexture(GL_TEXTURE_2D,texture[i]); //绑定纹理
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TextureImage[i]->sizeX, TextureImage[i]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,
TextureImage[i]->data); //指定纹理
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //指定过滤模式
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
if (TextureImage[i])
{
if (TextureImage[i]->data)
free(TextureImage[i]->data);
free(TextureImage[i]);
}
}
return Status;
}
voidRenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
if(!LoadGLTextures());
glEnable(GL_TEXTURE_2D);
LoadGLTextures(); //载入纹理贴图
glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glBindTexture(GL_TEXTURE_2D,texture[0]);
glBegin(GL_QUADS);
// glColor3f(1.0,0.0,0.0);//红色
glTexCoord2f(0.0f, 0.0f); glVertex3f( 10.0f, 10.0f,20.0f); //上面glTexCoord2f(1.0f, 0.0f); glVertex3f(-10.0f, 10.0f,20.0f);
glTexCoord2f(1.0f, 1.0f);glVertex3f(-10.0f,-10.0f,20.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 10.0f,-10.0f,20.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[1]);
glBegin(GL_POLYGON);
// glColor3f(0.0,1.0,0.0); //绿色
glTexCoord2f(0.0f, 1.0f); glVertex3f(10.0, 10.0,-10.0); //右面glTexCoord2f(0.0f, 0.0f);glVertex3f(10.0, 10.0, 20.0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(10.0,-10.0, 20.0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(10.0,-10.0,-10.0);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[2]);
glBegin(GL_POLYGON);
// glColor3f(0.0,0.0,1.0);//蓝色
glTexCoord2f(1.0f, 0.0f); glVertex3f( 10.0,-10.0,-10.0); //下
面
glTexCoord2f(1.0f, 1.0f);glVertex3f(-10.0,-10.0,-10.0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-10.0, 10.0,-10.0);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 10.0, 10.0,-10.0);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[3]);
glBegin(GL_POLYGON);
// glColor3f(1.0,1.0,0.0);// 黄色
glTexCoord2f(1.0f, 0.0f); glVertex3f(-10.0, 10.0, 20.0); //左面glTexCoord2f(1.0f, 1.0f); glVertex3f(-10.0, 10.0,-10.0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-10.0,-10.0,-10.0);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-10.0,-10.0, 20.0);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[4]);
glBegin(GL_POLYGON);
//glColor3f(0.0,1.0,1.0);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 10.0,10.0,-10.0); //后面glTexCoord2f(0.0f, 1.0f); glVertex3f(-10.0,10.0,-10.0);
glTexCoord2f(0.0f, 0.0f);glVertex3f(-10.0,10.0, 20.0);
glTexCoord2f(1.0f, 0.0f);glVertex3f( 10.0,10.0, 20.0);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[5]);
glBegin(GL_POLYGON);
// glColor3f(1.0,0.0,1.0);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 10.0,-10.0, 20.0); //前面glTexCoord2f(1.0f, 0.0f); glVertex3f(-10.0,-10.0, 20.0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-10.0,-10.0,-10.0);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 10.0,-10.0,-10.0);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
/*void SetupRC()
{
//glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
glColor3f(0.0f, 1.0f, 0.0f);
glShadeModel(GL_FLAT);
//glFrontFace(GL_CW);
}*/
void SpecialKeys(int key, int x, int y) //设置键盘控制{
if(key == GLUT_KEY_UP)
xRot-= 5.0f;
if(key == GLUT_KEY_DOWN)
xRot += 5.0f;
if(key == GLUT_KEY_LEFT)
yRot -= 5.0f;
if(key == GLUT_KEY_RIGHT)
yRot += 5.0f;
if(key > 356.0f)
xRot = 0.0f;
if(key < -1.0f)
xRot = 355.0f;
if(key > 356.0f)
yRot = 0.0f;
if(key < -1.0f)
yRot = 355.0f;
glutPostRedisplay();
}
voidChangeSize(int w, int h)
{
GLfloatnRange = 25.0f;
if(h == 0)
{
h = 1;
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); //设置下面的操作矩阵为GL_MODELVIEW
glLoadIdentity();
if (w <= h)
{
glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
}
else
{
glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); //空间的视觉范围设置
}
int main(intargc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow("按上下左右键旋转"); //创建窗口
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys); //键盘控制
glutDisplayFunc(RenderScene); //显示绘图
// SetupRC();
glutMainLoop(); //主循环
return 0;
}
(3)程序运行界面截图:
(4)调试中出现的问题及解决方法:
1.长方体开始旋转时没有绕着自身旋转而是绕着原点旋转,经检查后发现glRotatef()函数和glTranslatef()顺序写错,应该先平移,后旋转,而不是先旋转后平移;
2.贴的图片一开始不显示,后发现图片大小设置错误,改成64乘64像素的就可以正常显示了。
2.两个长方体,可以分别对每个长方体进行旋转。
(1)程序设计流程图:
(2)(部分)源程序:
#include
GLfloat vertices[][3] = {{-1.0, -1.0, 1.0}, {-1.0, 1.0, 1.0}, //定义八个点;
{1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {-1.0, -1.0, -1.0},
{-1.0, 1.0, -1.0}, {1.0, 1.0, -1.0}, {1.0, -1.0, -1.0}};
GLfloat colors[][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 1.0}, //定义六种颜色;
{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0},
{0.0, 0.0, 1.0}, {1.0, 0.0, 1.0}};
float xrot[2] = {0.0f}; //定义两组旋转参数;floatyrot[2] = {0.0f};
inti=0; //定义旋转参数的组号
void polygon(int a, int b, int c, int d) //绘制四边形函数;{
glBegin(GL_POLYGON);
glVertex3fv(vertices[a]);
glVertex3fv(vertices[b]);
glVertex3fv(vertices[c]);
glVertex3fv(vertices[d]);
glEnd();
}
void colorcube() //绘制立方体函数;
{
glColor3fv(colors[0]); //设置颜色;
polygon(0, 3, 2, 1); //绘制正方形;
glColor3fv(colors[1]);
polygon(2, 3, 7, 6);
glColor3fv(colors[2]);
polygon(3, 0, 4, 7);
glColor3fv(colors[3]);
polygon(1, 2, 6, 5);
glColor3fv(colors[4]);
polygon(4, 5, 6, 7);
glColor3fv(colors[5]);
polygon(5, 4, 0, 1);
}
void mymenu(int value) //菜单函数;
{
i=value; //根据菜单选项,选定当前的旋转操作组;
}
void init() //初始化函数;
{
glClearColor(0.0, 0.0, 0.0, 0.0); //清屏,屏幕为黑色;
glColor3f(1.0, 1.0, 1.0); //设置初始颜色为白色;
glutCreateMenu(mymenu); //创建菜单,注册菜单处理函数mymenu;
glutAddMenuEntry("left",0); //给菜单加一个名
为left的条目,并设置,当点击此条目传递给mymenu一个值:0(int型)glutAddMenuEntry("right",1); //给菜单加
一个名为right的条目,……
glutAttachMenu(GLUT_RIGHT_BUTTON); //绑定菜单到鼠标右击;
}
void display(void) //绘制函数;
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色和深度缓冲;
glEnable(GL_DEPTH_TEST); //启用深度;
glMatrixMode(GL_MODELVIEW); //设置,以下的操作修改的是GL_MODELVIEW(模型视景矩阵)
/*GL_PROJECTION是对投影矩阵操作,
**GL_MODELVIEW是对模型视景矩阵操作,
**GL_TEXTURE是对纹理矩阵进行随后的操作
*/
glLoadIdentity(); //GL_MODELVIEW矩阵设置为单位矩阵,类似于还原为初始状态;
glTranslatef(-2.0,0,0); //矩阵左移2单位值;
glRotatef(xrot[0], 1.0, 0.0, 0.0); //设置矩阵的旋转值;
glRotatef(yrot[0], 0.0, 1.0, 0.0);
glScalef(1.0,1.5,.5); //设置矩阵拉伸值,也就是将正方体变为长方体;
colorcube(); //按照此矩阵,绘图;
glLoadIdentity(); //还原矩阵GL_MODELVIEW;
glTranslatef(2.0,0,0); //右移2单位值;
glRotatef(xrot[1], 1.0, 0.0, 0.0); //设置旋转值;
glRotatef(yrot[1], 0.0, 1.0, 0.0);
glScalef(1.0,0.5,0.5); //拉伸值;
colorcube(); //绘图;
glFlush(); //立即执行,不进入缓冲;
glutSwapBuffers(); //交换前后台;
}
void reshape(int w, int h) //重绘函数(参数为新窗口的长宽);
{
glViewport(0, 0, w, h); //窗口左下角为(0,0),窗口右上角为(w,h);
glMatrixMode(GL_PROJECTION); //设置下面的操作矩阵为GL_PROJECTION;
glLoadIdentity(); //设置矩阵为单位矩阵;
glOrtho(-4.0, 4.0, -4.0, 4.0, -4.0, 4.0); //空间的视觉范围设置;(left, right, bottom, top, near, far)
}
void keyboard(intkey,intx,int y) //按键响应函数;
{
if(key==GLUT_KEY_UP) //根据按键,设置当前旋转值,每次加5度或减5度(角度);
xrot[i]+=5.0;
if(key==GLUT_KEY_DOWN)
xrot[i]+=355.0;
if(key==GLUT_KEY_LEFT)
yrot[i]+=5.0;
if(key==GLUT_KEY_RIGHT)
yrot[i]+=355.0;
if(xrot[i]>=360) //使旋转值保持在360度以内;
xrot[i]-=360;
if(yrot[i]>=360)
yrot[i]-=360;
glutPostRedisplay(); //当前窗口需要重新绘制;
}
int main(intargc, char **argv)
{
glutInit(&argc, argv); //初始化;glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); //设置显示方式,[颜色,双缓存,深度缓存]
/*使用双缓存是为了把完整图画一次性显示在窗口上,
以避免把计算机作图的过程都表现出来;
**使用深度缓存是为了只看到所画图形的外表**/
glutInitWindowSize(400, 400); //设置窗口大小;
glutInitWindowPosition(200, 200); //设置窗口在屏幕中的位置;
glutCreateWindow("OpenGL"); //创建窗口,并命名标题为OpenGL;
glutDisplayFunc(display); //注册一个绘图函数display,操作系统在必要时刻就会用display对窗体进行重新绘制操作;
glutReshapeFunc(reshape); //注册重绘函数reshape,当窗口被拉动时候(也就是窗口大小改变),调用reshape;
glutSpecialFunc(keyboard); //注册一个特殊键盘按键响应函数keyboard,当用户输入特殊字符时,程序调用keyboard函数;
init(); //初始设置;
glutMainLoop(); //让系统陷入死循环,也就是程序永远运行;
}
(3)程序运行界面截图: