OpenGL模拟弹性小球自由落体

今天花了一个多小时就写好了代码,做的这个很有趣呢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,不断刷新界面即可啦


  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值