#include "glwidget.h"
/* #ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE 0x809D
#endif*/
//static float view_rotate[16] = {1,0,0,0, 0,1,0,0, 0,-0.35,1,0, 0,0,0,1 };//用于上下移动设置
static GLubyte* pixeldata;//用于存储位图信息
GLWidget::GLWidget(QWidget *parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
lighting = true;
angle_z= 0;
angle_x= 25;
scale = 1.0;
z= -3.5;
sita = 0.0f;
chartflag = 0;
angle_scan = 135;
angle_elevation = -0.001;
}
GLWidget::~GLWidget()
{
}
/* QSize GLWidget::minimumSizeHint() const
{
return QSize(50, 50);
}
*/
//初始化显示界面(按照加载位图长宽定义)
QSize GLWidget::sizeHint() const
{
return QSize(width, height);
}
//灯光控制按钮槽函数(灯光开)
void GLWidget::setlighton()
{
glEnable(GL_LIGHTING);
updateGL();
}
//灯光控制按钮槽函数(灯光关)
void GLWidget::setlightoff()
{
glDisable(GL_LIGHTING);
updateGL();
}
//画地面槽函数(效果关)
void GLWidget::setchartoff()
{
chartflag = 0;
updateGL();
}
//画电子地图槽函数
void GLWidget::setcharton()
{
chartflag = 1;
updateGL();
}
//画水平地面槽函数
void GLWidget::setground()
{
chartflag = 2;
updateGL();
}
//按钮控制缩放槽函数
void GLWidget::setslider(int value)
{
if (value > (scale-1)*10)
{
scale += 0.1;
}
else if (value<(scale - 1)*10)
{
scale -= 0.1;
}
updateGL();
}
//按钮控制水平旋转槽函数
void GLWidget::setangle(int value)
{
if (value < angle_z /18)
{
angle_z= (angle_z-18) % 360;
}
else if (value > angle_z /18)
{
angle_z= (angle_z+18) % 360;
}
updateGL();
}
//按钮控制旋转槽函数
void GLWidget::setrotate(int value)///%%%%%%%%%%%%%%%%%%%%%%%待。。有问题(需要加按钮么?还是键盘控制就好?)
{
/* if (value <(view_rotate[9]+4.1)*10)
{
view_rotate[9] = view_rotate[9] - 0.1;
view_rotate[10] = view_rotate[10] - 0.1;
view_rotate[0] = view_rotate[0] + 0.1;
z= z - 0.25;
if ( view_rotate[9]< -0.4)
{
glDisable (GL_LIGHTING);
emit lightChanged(0);
}
}
else if (value >(view_rotate[9]+4.1)*10)
{
view_rotate[9] = view_rotate[9] + 0.1;
view_rotate[10] = view_rotate[10] +0.1;
view_rotate[0] = view_rotate[0] - 0.1;
z = z + 0.25;
}*/
if (value >(angle_x -25)/5)
{
if (angle_x <90)
angle_x= (angle_x+ 5) % 360;
}
else if (value <(angle_x -25)/5)
{
if (angle_x >25)
angle_x= (angle_x - 5) % 360;
}
updateGL();
}
//求2的n次幂函数(用于地图加载函数load_texture)
int GLWidget::power_of_two(int n)
{
if( n <= 0 )
return 0;
return (n & (n-1)) == 0;
}
//画扫描面函数
void GLWidget::scanning()
{
int i,n;
n = 5;
glEnable(GL_BLEND);
glDisable(GL_LIGHTING);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0.05f,0.05f, 0.2f, 0.5f);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0,0.0,-0.001);
for(int i=angle_scan;i<=angle_scan+SCOPE;i+=5)
{
float p=(float)(i*pi/180);
glVertex3f((float)sin(p),(float)cos(p),angle_elevation );// 扇形轨迹
}
glEnd();
glEnd();
glEnable(GL_LIGHTING);
glDisable(GL_BLEND);
}
void GLWidget::initializeGL()
{
GLfloat light_ambient[] = {0.0f, 1.0f, 0.0f, 0.0f};
GLfloat light_diffuse[] = {0.0f, 1.0f, 0.0f, 0.0f};
GLfloat light_position[] = {0.0f, 0.0f, 3.0f, 1.0f};
glShadeModel( GL_SMOOTH );
//这一行启用smooth shading(阴影平滑)。阴影平滑通过多边形精细的混合色彩,并对外部光进行平滑。
glClearColor( 0.0, 0.0, 0.0, 0.0 );
//这一行设置清除屏幕时所用的颜色
glClearDepth( 1.0 );
//设置深度缓存。
glEnable( GL_DEPTH_TEST );
//启用深度测试。
glDepthFunc( GL_LEQUAL );
//所作深度测试的类型。
//上面这三行必须做的是关于depth buffer(深度缓存)的。将深度缓存设想为屏幕后面的层。深度缓存不断的对物体进入屏幕内部有多深进行跟踪
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
//真正精细的透视修正
glLightfv(GL_LIGHT1,GL_AMBIENT,light_ambient);
glLightfv(GL_LIGHT1,GL_DIFFUSE,light_diffuse);
glLightfv(GL_LIGHT1,GL_POSITION,light_position);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHTING);
texGround = load_texture(FILENAME);
}
//模拟航迹点函数
void GLWidget::trackdraw()
{
glDisable (GL_LIGHTING);
glPointSize(8.0f);
glColor4f (0.03f, 0.03f, 0.0f, 1.0f);
glBegin(GL_POINTS);
// glVertex3f(0.0f,-0.23f,0.0f);//所有的y都要-0.25f
glVertex3f(R/4*3*cos((sita-6.0)*pi/180),-0.23f+R*sin((sita-6.0)*pi/180),-R/3);
glEnd();
glColor4f (0.1f, 0.1f, 0.0f, 1.0f);
glBegin(GL_POINTS);
// glVertex3f(0.0f,-0.23f,0.0f);//所有的y都要-0.25f
glVertex3f(R/4*3*cos((sita-5.0)*pi/180),-0.23f+R*sin((sita-5.0)*pi/180),-R/3);
glEnd();
glColor4f (0.3f, 0.3f, 0.0f, 1.0f);
glBegin(GL_POINTS);
// glVertex3f(0.0f,-0.23f,0.0f);//所有的y都要-0.25f
glVertex3f(R/4*3*cos((sita-4.0)*pi/180),-0.23f+R*sin((sita-4.0)*pi/180),-R/3);
glEnd();
glColor4f (0.4f, 0.4f, 0.0f, 1.0f);
glBegin(GL_POINTS);
// glVertex3f(0.0f,-0.23f,0.0f);//所有的y都要-0.25f
glVertex3f(R/4*3*cos((sita-3.0)*pi/180),-0.23f+R*sin((sita-3.0)*pi/180),-R/3);
glEnd();
glColor4f(0.5f, 0.5f, 0.0f, 1.0f);
glBegin(GL_POINTS);
glVertex3f(R/4*3*cos((sita-2.0)*pi/180),-0.23f+R*sin((sita-2.0)*pi/180),-R/3);
glEnd();
glColor4f(0.6f, 0.6f, 0.0f, 1.0f);
glBegin(GL_POINTS);
glVertex3f(R/4*3*cos((sita-1.0)*pi/180),-0.23f+R*sin((sita-1.0)*pi/180),-R/3);
glEnd();
glColor4f(0.75f, 0.75f, 0.0f, 1.0f);
glBegin(GL_POINTS);
glVertex3f(R/4*3*cos(sita*pi/180),-0.23f+R*sin(sita*pi/180),-R/3);
glEnd();
/* glBegin(GL_LINES);
glVertex3f(R/3*cos((sita-3.0)*pi/180),-0.23f+R/2*sin((sita-3.0)*pi/180),-R/4);
glVertex3f(R/3*cos(sita*pi/180),-0.23f+R/2*sin(sita*pi/180),-R/4);
// glVertex3f(R/2*cos(sita*pi/180),-0.23f+R/5*4*sin(sita*pi/180),-R/2);
// glVertex3f(R/2*cos(sita*pi/180),R/5*4*sin(sita*pi/180),-R/2);
glEnd();*/
/* glColor4f (0.7f, 0.7f, 0.0f, 1.0f);
glPointSize(5.0f);
glBegin(GL_POINTS);
// glVertex3f(0.0f,-0.23f,0.0f);//所有的y都要-0.25f
glVertex3f(R/2*cos(sita*pi/180),-0.23f+R/5*4*sin(sita*pi/180),-R/2);
glVertex3f(R/2*cos(sita*pi/180),R/5*4*sin(sita*pi/180),-R/2);
glEnd();*/
glEnable(GL_LIGHTING);
}
//加载电子地图位图函数
GLuint GLWidget::load_texture(const char* file_name)
{
GLuint texture_ID;
unsigned long factual_width;
if((pfile=fopen(file_name,"rb"))==NULL) /*打开文件,并且判断文件是否存在*/
{
printf("Can't find .bmp file %s",file_name);
}
fseek(pfile,0,SEEK_SET); //定义初始点
fread(&BmpHead.bfType,2,1,pfile); /*位图文件头*/
fread(&BmpHead.bfSize,4,1,pfile); /*位图文件头*/
fread(&BmpHead.bfReserved1,2,1,pfile); /*位图文件头*/
fread(&BmpHead.bfReserved2,2,1,pfile); /*位图文件头*/
fread(&BmpHead.bfOffBits,4,1,pfile); /*位图文件头*/
if(BmpHead.bfType!=0x4d42)//0x424D
{
printf("\n\r this bmp file is not 24 bmp!");
exit(1);
}
fseek(pfile, 0x0012, SEEK_SET);
fread(&width, 4, 1, pfile);
fread(&height, 4, 1, pfile