#include "qglproject.h"
//初始化ode中的静态变量/
dWorldID qGlproject::world = dWorldCreate();
dSpaceID qGlproject::space = dSimpleSpaceCreate(0);
dJointGroupID qGlproject::contactgroup = dJointGroupCreate(0);
dGeomID qGlproject::ground = dCreatePlane(space,0,1,0,0);
//初始化房屋盒子
dGeomID qGlproject::ground_box[5] = {
dCreateBox(space,1,500,500),
dCreateBox(space,1,500,500),
dCreateBox(space,500,500,1),
dCreateBox(space,500,500,1),
dCreateBox(space,500,2,500)};
//初始化桌子
dGeomID qGlproject::table[5] = {
dCreateBox(space,30,0.5,60),
dCreateBox(space,2,10,2),
dCreateBox(space,2,10,2),
dCreateBox(space,2,10,2),
dCreateBox(space,2,10,2)
};
//桌面和腿的大小
float sides[2][3] = {{30,0.5,60},{2,10,2}};
const float piover180 = 0.0174532925f;//1°= π/180 = 0.01745329
float heading;//水平转过的角度
float zeading;//竖直转过的角度
float xpos = 0;
float zpos = -60;
float ypos = 0;
//灯光
bool light0 = true;
bool light1 = false;
bool light2 = false;
bool light3 = false;
bool tempNewbody = true;
int tbn = 0;
//产生影子的参数
float l[] = { 4.0f, 24.0f, -100.0f }; //产生影子的灯光坐标
float n[] = { 0.0, -1.0, 0.0 }; // Normal vector for the plane
float e[] = { 0.0, 0.02, 0.0 }; //地平面坐标
GLuint
texture[4];
// 使用四个纹理
小球坐标
GLdouble fBallx;
GLdouble fBally;
GLdouble fBallz;
GLdouble fBallxc;
GLdouble fBallyc;
GLdouble fBallzc;
ode开关参数
bool isOde = false;
bool isAble = true;
//关闭单个物体
选择参数
int numBody = 0; //物体个数
int tempNumBody = 0;
GLfloat
yrot;
GLfloat zrot;
GLfloat walkbias = 0;
GLfloat lookupdown = 0.0f;
GLfloat tempRadius;
GLfloat tempWidth;
GLfloat tempLength;
GLfloat tempHeight;
GLfloat tempDensity;
GLfloat tempSize;
qGlproject::qGlproject(QWidget *parent)
: QGLWidget(parent)
{
startTimer( 10 );
///初始化ode///
dWorldSetGravity(world,0.1,-2.0,0.0);//设置世界的重力加速度
dWorldSetAutoDisableFlag(world,1);
dWorldSetContactMaxCorrectingVel(world,0.1);
dWorldSetContactSurfaceLayer(world,0.001);//这些不用
//testCar.equCreate(world,space,contactgroup);
//testCar.setCarSize(3);
dAllocateODEDataForThread(dAllocateMaskAll);
num_ball = 0;
num_car = 0;
num_box = 0;
//使物体无法穿出屋子
dMass boxMass;
dMassSetBox(&boxMass,1,2,500,500);
dGeomSetPosition(ground_box[0],80.5,-20,5);//测试world.drealx.'+'
dGeomSetPosition(ground_box[1],-120.5,-20,25);//测试world.drealx.'-'
dGeomSetPosition(ground_box[2],20,-20,-100.5);//测试world.drealz.'-'
dGeomSetPosition(ground_box[3],20,-20,100.5);//测试world.drealz.'+'
dGeomSetPosition(ground_box[4],60,101,50);//房顶
//设置桌子的位置
dGeomSetPosition(table[0],0,10,0);//桌面
//桌腿顺时针
dGeomSetPosition(table[1],-13,11/2,-13);
dGeomSetPosition(table[2],-13,11/2,13);
dGeomSetPosition(table[3],13,11/2,13);
dGeomSetPosition(table[4],13,11/2,-13);
frist.creatLab(world,space);
}
//画出桌子
void qGlproject::drawTable()
{
drawGeom(table[0],0,0,sides[0]);//桌面
drawGeom(table[1],0,0,sides[1]);
drawGeom(table[2],0,0,sides[1]);
drawGeom(table[3],0,0,sides[1]);
drawGeom(table[4],0,0,sides[1]);
}
//画桌子的geom
void qGlproject::drawGeom(dGeomID g, const dReal *pos, const dReal *R, float *sides)
{
if(!g) return;
if(!pos) pos = dGeomGetPosition(g);
if(!R) R = dGeomGetRotation(g);
GLfloat matrix[16];
matrix[0]=R[0];
matrix[1]=R[4];
matrix[2]=R[8];
matrix[3]=0;
matrix[4]=R[1];
matrix[5]=R[5];
matrix[6]=R[9];
matrix[7]=0;
matrix[8]=R[2];
matrix[9]=R[6];
matrix[10]=R[10];
matrix[11]=0;
matrix[12]=pos[0];
matrix[13]=pos[1];
matrix[14]=pos[2];
matrix[15]=1;
glPushMatrix();
glMultMatrixf (matrix);
drawBox(sides);
glPopMatrix();
}
//画长方体
void qGlproject::drawBox(float *sides)
{
float lx = sides[0]*0.5f;
float ly = sides[1]*0.5f;
float lz = sides[2]*0.5f;
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, texture[3]);
//逆时针
glBegin (GL_QUADS);
//左面
glNormal3f (-1,0,0);
glTexCoord2f(0.0,0.0);glVertex3f (-lx,-ly,-lz);
glTexCoord2f(1.0,0.0);glVertex3f (-lx,-ly,lz);
glTexCoord2f(1.0,1.0);glVertex3f (-lx,ly,lz);
glTexCoord2f(0.0,1.0);glVertex3f (-lx,ly,-lz);
//右面
glNormal3f (1,0,0);
glTexCoord2f(1.0,0.0);glVertex3f (lx,-ly,-lz);
glTexCoord2f(1.0,1.0);glVertex3f (lx,ly,-lz);
glTexCoord2f(0.0,1.0);glVertex3f (lx,ly,lz);
glTexCoord2f(0.0,0.0);glVertex3f (lx,-ly,lz);
//底面
glNormal3f (0,-1,0);
glTexCoord2f(1.0,1.0);glVertex3f (-lx,-ly,-lz);
glTexCoord2f(0.0,1.0);glVertex3f (lx,-ly,-lz);
glTexCoord2f(0.0,0.0);glVertex3f (lx,-ly,lz);
glTexCoord2f(1.0,0.0);glVertex3f (-lx,-ly,lz);
//顶面
glNormal3f (0,10,0);
glTexCoord2f(0.0,1.0);glVertex3f (-lx,ly,-lz);
glTexCoord2f(0.0,0.0);glVertex3f (-lx,ly,lz);
glTexCoord2f(1.0,0.0);glVertex3f (lx,ly,lz);
glTexCoord2f(1.0,1.0);glVertex3f (lx,ly,-lz);
// 背面
glNormal3f (0,0,-1);
glTexCoord2f(1.0,0.0);glVertex3f (-lx,-ly,-lz);
glTexCoord2f(1.0,1.0);glVertex3f (-lx,ly,-lz);
glTexCoord2f(0.0,1.0);glVertex3f (lx,ly,-lz);
glTexCoord2f(0.0,0.0);glVertex3f (lx,-ly,-lz);
// 前面
glNormal3f (0,0,1);
glTexCoord2f(0.0,0.0);glVertex3f (-lx,-ly,lz);
glTexCoord2f(1.0,0.0);glVertex3f (lx,-ly,lz);
glTexCoord2f(1.0,1.0);glVertex3f (lx,ly,lz);
glTexCoord2f(0.0,1.0);glVertex3f (-lx,ly,lz);
glEnd();
glPopMatrix();
}
qGlproject::~qGlproject()
{
dJointGroupDestroy(contactgroup);
dSpaceDestroy(space);
dWorldDestroy(world);
dCloseODE();
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
}
void qGlproject::initializeGL()
{
LoadGLTextures();
glEnable( GL_TEXTURE_2D );
glShadeModel( GL_SMOOTH );
//启用smooth shading(阴影平滑)。阴影平滑通过多边形精细的混合色彩,并对外部光进行平滑。
glClearColor( 0.2f, 0.5f, 1.0f, 1.0f);
//设置清除屏幕时所用的颜色。
glClearDepth( 1.0 );
//设置深度缓存。
glEnable( GL_DEPTH_TEST );
//启用深度测试。
glDepthFunc( GL_LEQUAL );
//所作深度测试的类型。
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
//真正精细的透视修正。这一行告诉OpenGL我们希望进行最好的透视修正。这会十分轻微的影响性能。但使得透视图看起来好一点。
}
void qGlproject::timerEvent( QTimerEvent * )
{
updateGL();
}
//************转换字符串************
QString qGlproject::GLfQstr(GLfloat f)
{
char str[10];
_gcvt((float)f,4,str);
string str1=str ;
return QString(QString::fromLocal8Bit(str1.c_str()));
}
void qGlproject::LoadGLTextures()
{
QImage tex, buf[4];
//buf.load("./Resource Files/EnvWall.bmp");
buf[0].load( "./Resources/ground.bmp" );
buf[1].load("./Resources/wall4.bmp");
buf[2].load("./Resources/wall4.bmp");
buf[3].load("./Resoures/table.bmp");
if ( !buf[0].load( "./Resources/ground.bmp" ) )//载入纹理图片。这里使用了QImage 类。
{
qWarning( "Could not read image file, using single-colorinstead." );
QImage dummy( 1280, 800, 32 );
dummy.setColorCount(7);
buf[0] = dummy;
}
if ( !buf[1].load("./Resources/wall4.bmp"))//载入纹理图片。这里使用了QImage 类。
{
qWarning( "Could not read image file, using single-colorinstead." );
QImage dummy( 1280, 800, 32 );
dummy.setColorCount(7);
buf[1] = dummy;
}
if (!buf[2].load("./Resources/roof.bmp"))//载入纹理图片。这里使用了QImage 类。
{
qWarning( "Could not read image file, using single-colorinstead." );
QImage dummy( 1280, 800, 32 );
dummy.setColorCount(7);
buf[2] = dummy;
}
if (!buf[3].load("./Resources/table.bmp"))//载入纹理图片。这里使用了QImage 类。
{
qWarning( "Could not read image file, using single-colorinstead." );
QImage dummy( 1280, 800, 32 );
dummy.setColorCount(7);
buf[3] = dummy;
}
glGenTextures( 4, &texture[0] );
for (int i = 0;i < 4; i++)
{
tex= QGLWidget::convertToGLFormat( buf[i] );
glBindTexture( GL_TEXTURE_2D, texture[i] );
glTexImage2D( GL_TEXTURE_2D, 0, 4, tex.width(),tex.height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
}
//绘制阴影
void qGlproject::glShadowProjection(float * l, float * e, float * n)
{
float d, c;
float mat[16];
d = n[0]*l[0] + n[1]*l[1] + n[2]*l[2];
c = e[0]*n[0] + e[1]*n[1] + e[2]*n[2] - d;
// 创建矩阵.
mat[0] = l[0]*n[0]+c;
mat[4] = n[1]*l[0];
mat[8] = n[2]*l[0];
mat[12] = -l[0]*c-l[0]*d;
mat[1] = n[0]*l[1];
mat[5] = l[1]*n[1]+c;
mat[9] = n[2]*l[1];
mat[13] = -l[1]*c-l[1]*d;
mat[2] = n[0]*l[2];
mat[6] = n[1]*l[2];
mat[10] = l[2]*n[2]+c;
mat[14] = -l[2]*c-l[2]*d;
mat[3] = n[0];
mat[7] = n[1];
mat[11] = n[2];
mat[15] = -d;
// 使用矩阵投影变换
glMultMatrixf(mat);
}
void qGlproject::paintGL()
{
QString Coordinate;
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//清楚屏幕和深度缓存。
glLoadIdentity ();
//重置当前的模型观察矩阵。
GLfloat xtrans = -xpos;
GLfloat ztrans = -(zpos + 5.0);
GLfloat ytrans = -ypos-0.25f;
GLfloat sceneroty = 180.0f - yrot;
glRotatef(lookupdown,1.0f,0,0);
glRotatef(sceneroty,0,1.0f,0);
glTranslatef(xtrans,ytrans-2,ztrans-15);
//光照设置
GLfloat
LightAmb[] = {1.0f, 1.0f, 1.0f, 1.0f};
// 环境光颜色
GLfloat
LightDif[] = {0.8f, 0.8f, 0.8f, 1.0f};
//漫反射光强度值,用他改变颜色
GLfloat
LightPos[] = {4.0f, 24.0f, -100.0f, 1.0f};
// 灯光的位置(x,y,z,w),w = 0表示光不是方向光
GLfloat light_specular0[] = {1.0f, 0.0f, 0.0f, 1.0f}; // 定义镜面反射光的颜色
//初始化光源GL_LIGHT0的颜色属性
glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb);
//光的环境强度
glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDif);
//光的散射度
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular0);// 创建镜面反射光
glLightfv(GL_LIGHT0, GL_POSITION, LightPos);//光源位置(x.y.z.w)
//glEnable(GL_LIGHT0);//允许GL_LIGHT0光源
if ( light0 ) glEnable(GL_LIGHT0);
else glDisable(GL_LIGHT0);
glEnable(GL_LIGHTING);//允许光照
//小球代表灯
glPushMatrix();
glDisable(GL_LIGHTING);
glColor3f(0.0,1.0,0.0);
glTranslatef(2.0, 10.0, -5.0);
auxSolidSphere(0.2);
glEnable(GL_LIGHTING);
glPopMatrix();
GLfloat light1_ambient[] = {0.0, 1.0, 0.0, 1.0};
GLfloat light1_siffuse[] = {0.0, 1.0, 0.0, 1.0};
GLfloat light1_specula[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light1_positio[] = {2.0, 10.0, 0.0, 0.0};
GLfloat spot_direction[] = {-1.0, -1.0, 0.0};//聚光方向
GLfloat spot_cu[] = {45.0};
GLfloat spot_di[] = {2.0};
GLfloat spot_con[] = {1.5};
GLfloat spot_lin[] = {0.5};
GLfloat spot_qu[] = {0.2};
glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);//光的环境强度
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_siffuse);//光的散射度
glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specula);//光的镜面强度
glLightfv(GL_LIGHT1, GL_POSITION, light1_positio);//光源位置(x.y.z.w)
glLightfv(GL_LIGHT1, GL_CONSTANT_ATTENUATION, spot_con);//常量衰减因子
glLightfv(GL_LIGHT1, GL_LINEAR_ATTENUATION, spot_lin);//线性衰减因子
glLightfv(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, spot_qu);//二次衰减因子
glLightfv(GL_LIGHT1, GL_SPOT_CUTOFF,spot_cu);
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_direction);
glLightfv(GL_LIGHT1, GL_SPOT_EXPONENT, spot_di);
//glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);//启用双面光源
//if ( light1 )
//{
//
glEnable(GL_LIGHT1);
//}
//glEnable(GL_LIGHTING);//允许光照
//光照3设置
glPushMatrix();
glDisable(GL_LIGHTING);
glTranslatef(4.0f, 24.0f, +100.0f);
glColor3f(1.0f,1.0f,1.0f);
auxSolidSphere(1);
glEnable(GL_LIGHTING);
glPopMatrix();
GLfloat
LightAmb3[] = {1.0f, 1.0f, 1.0f, 1.0f};// 环境光
GLfloat
LightDif3[] = {1.0f, 1.0f, 1.0f, 1.0f};// 漫射光
GLfloat
LightPos3[] = {4.0f, 18.0f, 6.0f, 1.0f};// 灯光的位置
glLightfv(GL_LIGHT2, GL_AMBIENT, LightAmb3);
glLightfv(GL_LIGHT2, GL_DIFFUSE, LightDif3);
glLightfv(GL_LIGHT2, GL_POSITION, LightPos3);
/*glEnable(GL_LIGHT2);
*/
//光照4设置
glPushMatrix();
glDisable(GL_LIGHTING);
glTranslatef(4.0f, 4.0f, 6.0f);
glColor3f(1.0,0.0,0.0);
auxSolidSphere(0.2);
glEnable(GL_LIGHTING);
glPopMatrix();
GLfloat
LightAmb4[] = {1.0f, 0.0f, 0.0f, 1.0f};
// 环境光
GLfloat
LightDif4[] = {1.0f, 0.0f, 0.0f, 1.0f};
// 漫射光
GLfloat
LightPos4[] = {4.0f, 4.0f, 6.0f, 1.0f};
// 灯光的位置
glLightfv(GL_LIGHT3, GL_AMBIENT, LightAmb4);
glLightfv(GL_LIGHT3, GL_DIFFUSE, LightDif4);
glLightfv(GL_LIGHT3, GL_POSITION, LightPos4);
/*glEnable(GL_LIGHT3)*/;
混合透明
//glColor4f(1.0f, 1.0f, 1.0f, 0.0);//全亮度, 50% Alpha 混合
//glBlendFunc(GL_SRC_ALPHA,GL_ONE);// 基于源象素alpha通道值的半透明混合函数
//glEnable(GL_BLEND);
// 打开混合
//glDisable(GL_DEPTH_TEST);
// 关闭深度测试
//地面、墙
glPushMatrix();
glTranslatef(-100,0,100);
glBindTexture(GL_TEXTURE_2D, texture[0]);
for(int i = 0;i < 20;i++)
{
for(int j = 0; j < 20;j++)
{
glBegin(GL_QUADS);
glColor3f(1,1,1);
glTexCoord2f( 1.0, 1.0 );glVertex3f(-20 + 10*i,0,-10*j);
glTexCoord2f( 0.0, 1.0 );glVertex3f(-20+10*(i+1),0,0 -10*j);
glTexCoord2f( 0.0, 0.0 );glVertex3f(-20+10*(i+1),0,-10*(j+1));
glTexCoord2f( 1.0, 0.0 );glVertex3f(-20+10*i,0,-10*(j+1));
glEnd();
}
}
glBindTexture(GL_TEXTURE_2D, texture[1]);
//左墙面
glBegin(GL_QUADS);
glTexCoord2f(1.0,1.0);glVertex3f(-20,100,0);
glTexCoord2f(0.0,1.0);glVertex3f(-20,0,0);
glTexCoord2f(0.0,0.0);glVertex3f(-20,0,-200);
glTexCoord2f(1.0,0.0);glVertex3f(-20,100,-200);
//后墙面
glTexCoord2f(1.0,1.0);glVertex3f(-20,100,-200);
glTexCoord2f(0.0,1.0);glVertex3f(-20,0,-200);
glTexCoord2f(0.0,0.0);glVertex3f(180,0,-200);
glTexCoord2f(1.0,0.0);glVertex3f(180,100,-200);
//右墙面
glTexCoord2f(1.0,1.0);glVertex3f(180,100,-200);
glTexCoord2f(0.0,1.0);glVertex3f(180,0,-200);
glTexCoord2f(0.0,0.0);glVertex3f(180,0,0);
glTexCoord2f(1.0,0.0);glVertex3f(180,100,0);
//前墙面
glTexCoord2f(1.0,1.0);glVertex3f(-20,100,0);
glTexCoord2f(0.0,1.0);glVertex3f(-20,0,0);
glTexCoord2f(0.0,0.0);glVertex3f(180,0,0);
glTexCoord2f(1.0,0.0);glVertex3f(180,100,0);
//房顶
glBindTexture(GL_TEXTURE_2D, texture[2]);
glBegin(GL_QUADS);
glTexCoord2f(1.0,1.0);glVertex3f(-20,100,0);
glTexCoord2f(0.0,1.0);glVertex3f(180,100,0);
glTexCoord2f(0.0,0.0);glVertex3f(180,100,-200);
glTexCoord2f(1.0,0.0);glVertex3f(-20,100,-200);
glEnd();
glPopMatrix();
//关闭混合
// glDisable(GL_BLEND);
//glEnable(GL_DEPTH_TEST);
显示小球坐标
//QTextCodec::setCodecForTr(QTextCodec::codecForName("gbk"));
//Coordinate = "视角:"+GLfQstr(xtrans)+","+GLfQstr(ytrans)+","+GLfQstr(ztrans)+"球:"+GLfQstr(fBallx)+","+GLfQstr(fBallx)+","+GLfQstr(fBallx)
//
+"鼠标:"+GLfQstr((GLfloat)fBallxc)+","+GLfQstr((GLfloat)fBallyc)+","+GLfQstr((GLfloat)fBallzc);
renderText(0,5,-10, tr(GLfQstr(xtrans)));
//setWindowTitle(tr(Coordinate));
//桌子
drawTable();
///在物理世界里描述具有物理性质的物体///
dSpaceCollide (space,0,&nearCallback); //调用碰撞检测函数
if(isOde) dWorldQuickStep(world,0.05);
//ode开关:Space键
dJointGroupEmpty (contactgroup); //清空jointgroup 防止stack flow
for(int i=0;i<v.size();i++)
{
//glPushMatrix();
//
glShadowProjection(l,e,n);
//v[i]->equDraw();
//glPopMatrix();
v[i]->equDraw();
if(isAble)
v[tempNumBody]->equGetPosition(fBallx,fBally,fBallz);
glPushMatrix();
glShadowProjection(l,e,n);
glDisable(GL_LIGHTING);
glColor3f(0.0,0.0,0.0);
v[i]->equDraw();
glEnable(GL_LIGHTING);
glPopMatrix();
}
if(!isAble)
{
glPushMatrix();
glTranslatef(fBallx,fBally,fBallz);
v[tempNumBody]->equDrawD();
glPopMatrix();
}
frist.drawEnv();
}
void qGlproject::resizeGL(int width, int height)
{
if ( height == 0 )
{
height = 1;
}
//防止height为0。
glViewport( 0, 0, (GLint)width, (GLint)height );
//重置当前的视口(Viewport)。
glMatrixMode( GL_PROJECTION );
//选择投影矩阵。
glLoadIdentity();
//重置投影矩阵。
gluPerspective(45.0,(GLfloat)width/(GLfloat)height,0.1,300.0);
//建立透视投影矩阵。
glMatrixMode( GL_MODELVIEW );
//选择模型观察矩阵。
glLoadIdentity();
//重置模型观察矩阵。
}
//********键盘事件处理
void qGlproject::keyPressEvent(QKeyEvent *k)
{
if (k->key() == Qt::Key_Q)
{
ypos += 0.5;
if (ypos > 80)
{
ypos = 80;
}
}
if (k->key() == Qt::Key_E)
{
ypos -= 0.5;
//if(ypos < 0 )
//{
//
ypos = 0;
//}
}
if(k->key() == Qt::Key_W)
{
xpos += (float)sin(heading*piover180) * 1.5f;
zpos += (float)cos(heading*piover180) * 1.5f;
//if (xpos > 75 ) { xpos = 75; }
//if (xpos < -115) { xpos = -115; }
//if (zpos > 75) { zpos = 75; }
//if (zpos < -115) { zpos = -115; }
}
if(k->key() == Qt::Key_S)
{
xpos -= (float)sin(heading*piover180) * 1.5f;
zpos -= (float)cos(heading*piover180) * 1.5f;
if (xpos > 75 ) { xpos = 75; }
if (xpos < -115) { xpos = -115; }
if (zpos > 75) { zpos = 75; }
if (zpos < -115) { zpos = -115; }
}
if(k->key() == Qt::Key_A)
{
xpos += (float)cos(heading*piover180) * 1.0f;
zpos -= (float)sin(heading*piover180) * 1.0f;
if (xpos > 75 ) { xpos = 75; }
if (xpos < -115) { xpos = -115; }
if (zpos > 75) { zpos = 75; }
if (zpos < -115) { zpos = -115; }
}
if(k->key() == Qt::Key_D)
{
xpos -= (float)cos(heading*piover180) * 1.0f;
zpos += (float)sin(heading*piover180) * 1.0f;
if (xpos > 75 ) { xpos = 75; }
if (xpos < -115) { xpos = -115; }
if (zpos > 75) { zpos = 75; }
if (zpos < -115) { zpos = -115; }
}
if(k->key() == Qt::Key_PageUp)
{
lookupdown -= 1.0f;
}
if(k->key() == Qt::Key_PageDown)
{
lookupdown += 1.0f;
}
控制小球
if(k->key() == Qt::Key_Up) Up
{
fBallx += (float)sin(heading*piover180) * 1.5f;
fBallz += (float)cos(heading*piover180) * 1.5f;
}
if(k->key() == Qt::Key_Down) Down
{
fBallx -= (float)sin(heading*piover180) * 1.5f;
fBallz -= (float)cos(heading*piover180) * 1.5f;
}
if(k->key() == Qt::Key_Left) Left
{
fBallx += (float)cos(heading*piover180) * 1.0f;
fBallz -= (float)sin(heading*piover180) * 1.0f;
}
if(k->key() == Qt::Key_Right) Right
{
fBallx -= (float)cos(heading*piover180) * 1.0f;
fBallz += (float)sin(heading*piover180) * 1.0f;
}
//灯光控制
if(k->key() == Qt::Key_F1)
{
light1 = !light1;
if ( light1 ) glEnable(GL_LIGHT1);
else glDisable(GL_LIGHT1);
}
if (k->key() == Qt::Key_F2)
{
light2 = !light2;
if( light2 ) glEnable(GL_LIGHT2);
else glDisable(GL_LIGHT2);
}
if (k->key() == Qt::Key_F3)
{
light3 = !light3;
if ( light3 ) glEnable(GL_LIGHT3);
else glDisable(GL_LIGHT3);
}
if (k->key() == Qt::Key_F4)
{
light0 = !light0;
}
ode开关
if(k->key() == Qt::Key_Space)
{
if(isOde) isOde = false;
else
{
isOde = true;
}
}
if(k->key() == Qt::Key_C)//创建小球
{
if(num_ball < NUM)
{
ball[num_ball].equSetParameter(0.5,0,0,0,1,0);
ball[num_ball].equCreate(world,space,contactgroup);
v.push_back(&ball[num_ball]);
num_ball++;
}
}
if(k->key() == Qt::Key_X)//创建小车
{
if(num_car < NUM)
{
car[num_car].equSetParameter(0,0,0,0,1,1);
car[num_car].equCreate(world,space,contactgroup);
v.push_back(&car[num_car]);
num_car++;
}
}
if(k->key() == Qt::Key_Z)//创建箱子
{
if(num_box < NUM)
{
box[num_box].equSetParameter(0,0.5,0.5,0.5,1,0);
box[num_box].equCreate(world,space,contactgroup);
v.push_back(&box[num_box]);
num_box++;
}
}
if(k->key() == Qt::Key_B)
{
if(v.size()>0)
{
if(isAble)
{
isAble = false;
//摧毁物体前先将物体的属性记录下来以供重新创建时使用
v[tempNumBody]->equGetParameter(tempRadius,tempLength,tempWidth,tempHeight,tempDensity,tempSize);
v[tempNumBody]->equDestroy();
}
else
{
isAble = true;
v[tempNumBody]->equSetPosition(fBallx,fBally,fBallz);
v[tempNumBody]->equSetParameter(tempRadius,tempLength,tempWidth,tempHeight,tempDensity,tempSize);
v[tempNumBody]->equCreate(world,space,contactgroup);
}
}
}
}
bool qGlproject::chooseObject()
{
bool choosed = false;
GLdouble a[3];
for (int i = 0; i < v.size() ; i++)
{
v[i]->equGetPosition(a[0],a[1],a[2]);
GLfloat selRad = v[i]->equGetSelRad();
if(abs(fBallxc - a[0]) < selRad && abs(fBallyc - a[1]) < selRad && (fBallzc - a[2]) < selRad )
{
choosed = true;
tempNumBody = i;
break;
}
}
QTextCodec::setCodecForTr(QTextCodec::codecForName("gbk"));
QString Coordinate = "鼠标:"+GLfQstr((GLfloat)a[0])+","+GLfQstr((GLfloat)a[1])+","+GLfQstr((GLfloat)a[2])
+"指针:"+GLfQstr((GLfloat)fBallxc)+","+GLfQstr((GLfloat)fBallyc)+","+GLfQstr((GLfloat)fBallzc)
+ "tempNumBody:"+GLfQstr((GLfloat)tempNumBody) + " numBody:" +GLfQstr((GLfloat)numBody);
setWindowTitle(tr(Coordinate));
return choosed;
}
//***********鼠标事件处理*********
void qGlproject::mousePressEvent(QMouseEvent *event)
{
lastPos = event->pos();
int dxc = event->x();
int dyc = event->y();
if (event->buttons() & Qt::LeftButton)
{
SelectObject(dxc,dyc);
if(isAble)
{
bool tempChoose = chooseObject();
if ( !tempChoose )
tempNumBody = 0;
for(int i=0;i<v.size();i++)
v[i]->equSelectN();
if(v.size() > 0)
{
v[tempNumBody]->equSelectY();
v[tempNumBody]->equGetPosition(fBallx,fBally,fBallz);
}
}
}
}
void qGlproject::mouseMoveEvent(QMouseEvent *event)
{
int dx = event->x() - lastPos.x();
int dy = event->y() - lastPos.y();
if (event->buttons() & Qt::RightButton)
{
heading -= dx;
yrot = heading;
lookupdown += dy;
}
lastPos = event->pos();
if (event->buttons() & Qt::LeftButton)
{
//zeading -= dy;
//zrot = zeading;
fBallx -= ((float)sin(zeading*piover180) * 1.5f/10);
if (dx < 0)
{
fBallx += (float)cos(heading*piover180) * 1.0f/5;
fBallz -= (float)sin(heading*piover180) * 1.0f/5;
}
else
{
fBallx -= (float)cos(heading*piover180) * 1.0f/5;
fBallz += (float)sin(heading*piover180) * 1.0f/5;
}
if (dy < 0 )
{
fBallx += (float)sin(heading*piover180) * 1.0f/5;
fBallz += (float)cos(heading*piover180) * 1.0f/5;
}
else
{
fBallx -= (float)sin(heading*piover180) * 1.0f/5;
fBallz -= (float)cos(heading*piover180) * 1.0f/5;
}
}
}
void qGlproject::wheelEvent(QWheelEvent *event)
{
double numDegrees = -event->delta() / 8.0;
double numSteps = numDegrees / 200.0;
if (fBally < 0.5)
{
fBally = 0.5;
}
else
fBally -= numSteps;
}
void qGlproject::SelectObject(int x,int y)
{
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX, winY, winZ;
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
winX = (float)x;
winY = (float)viewport[3] - (float)y;
glReadPixels(x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
gluUnProject(winX, winY, winZ, modelview, projection, viewport, &fBallxc, &fBallyc, &fBallzc);
}
碰撞检测的nearCallback函数
void qGlproject::nearCallback(void *data, dGeomID o1, dGeomID o2)
{
dBodyID b1 = dGeomGetBody(o1);
dBodyID b2 = dGeomGetBody(o2);
if(b1 && b2 && dAreConnectedExcluding(b1,b2,dJointTypeContact)) return;
dContact contact[4];
for(int i=0; i<4; i++)
{
contact[i].surface.mode = dContactBounce | dContactSoftCFM |
dContactSlip1 | dContactSlip2 | dContactApprox1 | dContactSoftERP;
contact[i].surface.mu = dInfinity;
contact[i].surface.mu2 = 2;//摩擦
contact[i].surface.slip1 = 0.1;
contact[i].surface.slip2 = 0.1;//滑动
contact[i].surface.bounce = 0.5;//弹力0~1
contact[i].surface.bounce_vel = 0.1;//小于该速度就不弹
contact[i].surface.soft_erp = 0.5;
contact[i].surface.soft_cfm = 0;
}
if(int numc = dCollide(o1,o2,4,&contact[0].geom,sizeof(dContact)))
{
for(int i=0; i < numc; i++)
{
dJointID c = dJointCreateContact(world,contactgroup,contact+i);
dJointAttach(c,b1,b2);
}
}
}