今天花了一个多小时就写好了代码,做的这个很有趣呢hhh,弹性小球自由落体,在碰到地面时又向上弹起,然后能量产生衰减,速度降低。
先附上我的结果图~~·
切换角度观察
加上纹理~~~草坪上弹起的毛线球!!!
主要思路如下:
首先是球体的绘制~因为没有配置glut库,所以我们不能使用以下两个函数:
void glutWireSphere(GLdouble radius, GLint slices, GLint stacks); 网状球
void glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); 实心球
绘制的过程其实是对球体的参数方程的解析过程,代码如下:
新建Point类
class Point
{
public:
Point();
Point(double a,double b,double c);
public:
double x;
double y;
double z;
};
Point::Point(){}
Point::Point(double a, double b, double c):x(a),y(b),z(c){}在Widget类中添加成员函数:
Point Widget::getPoint(double u,double v)
{
double x = sin(PI*v)*cos(PI*u);
double y = sin(PI*v)*sin(PI*u);
double z = cos(PI*v);
return Point(x,y,z);
}
void Widget::DrawSphere(double x_,double y_,double z_)
//参数用来指定绘制球体的中心位置
{
double ustep = 1/(double)uStepsNum, vstep = 1/(double)vStepNum;
double u = 0,v = 0;
//绘制下端三角形
glTranslatef(x_,y_,z_);//平移到球体的中心位置
for(int i = 0;i<uStepsNum;i++)
{
glBegin(GL_TRIANGLES);
Point a = getPoint(0,0);
glVertex3f(a.x,a.y,a.z);
Point b = getPoint(u,vstep);
glVertex3f(b.x,b.y,b.z);
Point c = getPoint(u+ustep,vstep);
glVertex3f(c.x,c.y,c.z);
u += ustep;
glEnd();
}
//绘制中间四边形组
u = 0, v = vstep;
for(int i=1;i<vStepNum-1;i++)
{
for(int j=0;j<uStepsNum;j++)
{
glBegin(GL_POLYGON);
Point a = getPoint(u,v);
Point b = getPoint(u+ustep,v);
Point c = getPoint(u+ustep,v+vstep);
Point d = getPoint(u,v+vstep);
glVertex3f(a.x,a.y,a.z);
glVertex3f(b.x,b.y,b.z);
glVertex3f(c.x,c.y,c.z);
glVertex3f(d.x,d.y,d.z);
u += ustep;
glEnd();
}
v += vstep;
}
//绘制下端三角形组
u = 0;
for(int i=0;i<uStepsNum;i++)
{
glBegin(GL_TRIANGLES);
Point a = getPoint(0,1);
Point b = getPoint(u,1-vstep);
Point c = getPoint(u+ustep,1-vstep);
glVertex3f(a.x,a.y,a.z);
glVertex3f(b.x,b.y,b.z);
glVertex3f(c.x,c.y,c.z);
glEnd();
}
}
当我们可以在指定位置绘制球体之后,我们就要让球体开始运动,运动需要指定初始位置、初始速度、加速度、衰减系数等等
我们首先建一个Ball类,用来存放球的各种属性:
class Ball
{
public:
Ball();
Ball(float x, float y, float z, float spe, float a_);
QVector3D now_pos;//当前位置坐标
float power;
float speed;//当前速度
float startX,startY,startZ;//起始坐标
float startSpeed;//起始速度
float a;//衰减系数
};
Ball::Ball()
{
power = 0;
speed = 0;
startX = startY = startZ = 0;
startSpeed = 0;
a = 0;
}
Ball::Ball(float x, float y, float z, float spe,float a_)
{
startX = x;
startY = y;
startZ = z;
startSpeed = spe;
speed = startSpeed;
a = a_;
now_pos.setX(x);
now_pos.setY(y);
now_pos.setZ(z);
}
然后我们把我们的OpenGL的相关初始设置工作做完,参考我的另一个博客点击打开链接
接着就到了我们最核心的部分啦~~~
QVector3D Widget::Running()
{
float x = ball->now_pos.x();//获取当前球的x,y坐标
float y = ball->now_pos.y();
if(ball->speed == 0 && y == 0)//如果球速度为0并且高度为0,说明此时球静止了
{
y = 0;
}
if(y>0)//如果高度不为0说明球还没有到达临界值~~~
{
//判断球在此运动状态下的下一时刻会不会砸到地里面
//否则让球的高度减少 y = y - (v0 + v)t 假定时间为1
//速度增加
qDebug() << " 当前速度 " << ball->speed << " 高度 " << y << endl;
}
if(y == 0 && ball->speed != 0)//高度为0但速度不为0说明要反向
{
//速度反向
//衰减
//弹起的初始位置设定为衰减的高度
}
ball->now_pos.setX(x);//更新当前球的x,y坐标
ball->now_pos.setY(y);
updateGL();//更新绘制
}
函数返回一个位置向量,我们再paintGL函数中将球体绘制到这个位置即可,然后通过一个QTimer的计时器来不断调用槽函数Running,不断刷新界面即可啦