OpenGL进阶(五)-物理模拟

http://blog.csdn.net/qp120291570/article/details/8362942

今天要实现的是利用OpenGL模拟三个物理学中常见的运动:自由落体,匀速之间,弹簧振子。

首先要实现一个空间三维向量类,看这篇文章:向量类的实现

然后主要要实现的是质点类,

  1. /* 
  2. Copyright: 2012, ustc All rights reserved. 
  3. contact:k283228391@126.com 
  4. File name: mass.h 
  5. Description:Particle in Physical 
  6. Author:Silang Quan 
  7. Version: 1.0 
  8. Date: 2012.12.21 
  9. */  
  10. #ifndef MASS_H  
  11. #define MASS_H  
  12. #include "vector3d.h"  
  13.   
  14. class Mass  
  15. {  
  16.     public:  
  17.         Mass();  
  18.         Mass(float _m,float _size){m=_m;size=_size;};  
  19.         void init();  
  20.         void simulate(float dt);  
  21.         void checkBnd(float x1,float x2,float y1,float y2);  
  22.         void setForce(Vector3D _force){force=_force;};  
  23.         void setVel(Vector3D _vel){vel=_vel;};  
  24.         virtual ~Mass();  
  25.         inline Vector3D getPos(){return pos;};  
  26.         inline Vector3D getVel(){return vel;};  
  27.         inline Vector3D getForce(){return force;};  
  28.         inline float getSize(){return size;};  
  29.   
  30.   
  31.     protected:  
  32.     private:  
  33.     float size;                         //大小  
  34.     float m;                            // 质量  
  35.     Vector3D pos;                               // 位置  
  36.     Vector3D vel;                               // 速度  
  37.     Vector3D force;                             // 力  
  38. };  
  39.   
  40. #endif // MASS_H  
/*
Copyright: 2012, ustc All rights reserved.
contact:k283228391@126.com
File name: mass.h
Description:Particle in Physical
Author:Silang Quan
Version: 1.0
Date: 2012.12.21
*/
#ifndef MASS_H
#define MASS_H
#include "vector3d.h"

class Mass
{
    public:
        Mass();
        Mass(float _m,float _size){m=_m;size=_size;};
        void init();
        void simulate(float dt);
        void checkBnd(float x1,float x2,float y1,float y2);
        void setForce(Vector3D _force){force=_force;};
        void setVel(Vector3D _vel){vel=_vel;};
        virtual ~Mass();
        inline Vector3D getPos(){return pos;};
        inline Vector3D getVel(){return vel;};
        inline Vector3D getForce(){return force;};
        inline float getSize(){return size;};


    protected:
    private:
    float size;                         //大小
	float m;							// 质量
	Vector3D pos;								// 位置
	Vector3D vel;								// 速度
	Vector3D force;								// 力
};

#endif // MASS_H

简单解释一下:质点主要有大小,质量,速度,受力这四个属性。除了一些getset方法外,最关键的是simulate和checkBnd连个方法,分别是模拟运动和边界检测,实现起来也比较简单。
  1. /* 
  2. Copyright: 2012, ustc All rights reserved. 
  3. contact:k283228391@126.com 
  4. File name: mass.cpp 
  5. Description:Particle in Physical 
  6. Author:Silang Quan 
  7. Version: 1.0 
  8. Date: 2012.12.21 
  9. */  
  10. #include "mass.h"  
  11.   
  12. Mass::Mass()  
  13. {  
  14.     //ctor  
  15. }  
  16. void Mass::init()  
  17. {  
  18.     force=Vector3D::zero();  
  19.     vel=Vector3D::zero();  
  20. }  
  21. void Mass::simulate(float dt)  
  22. {  
  23.     Vector3D acl=force/m;  
  24.     vel=vel+acl*dt;  
  25.     pos=pos+vel*dt;  
  26. }  
  27. Mass::~Mass()  
  28. {  
  29.     //dtor  
  30. }  
  31. void Mass::checkBnd(float x1,float x2,float y1,float y2)  
  32. {  
  33.     if (pos.x - size < x1 || pos.x +size > x2) vel.x = -vel.x;  
  34.     if (pos.y - size < y1 || pos.y + size > y2) vel.y = -vel.y;  
  35. }  
/*
Copyright: 2012, ustc All rights reserved.
contact:k283228391@126.com
File name: mass.cpp
Description:Particle in Physical
Author:Silang Quan
Version: 1.0
Date: 2012.12.21
*/
#include "mass.h"

Mass::Mass()
{
    //ctor
}
void Mass::init()
{
    force=Vector3D::zero();
    vel=Vector3D::zero();
}
void Mass::simulate(float dt)
{
    Vector3D acl=force/m;
    vel=vel+acl*dt;
    pos=pos+vel*dt;
}
Mass::~Mass()
{
    //dtor
}
void Mass::checkBnd(float x1,float x2,float y1,float y2)
{
    if (pos.x - size < x1 || pos.x +size > x2) vel.x = -vel.x;
    if (pos.y - size < y1 || pos.y + size > y2) vel.y = -vel.y;
}

在simulate函数中我们用到了运动学的公式:a=F/m,Vt=Vo+at.deltaS=at^2.

接下来我们就可以来进行模拟了!

首先在main.cpp中声明几个全局变量:

  1. GLUquadricObj *mySphere;  
  2. Mass constVelBall;  
  3. Mass gravityBall;  
  4. Mass springBall;  
GLUquadricObj *mySphere;
Mass constVelBall;
Mass gravityBall;
Mass springBall;

GLUquadricObj是二次曲面对象的声明类,后面三个是声明三个质点。

接下来是对三个质点的初始化:

  1. void initMasses()  
  2. {  
  3.     constVelBall=Mass(5.0,3);  
  4.     constVelBall.init();  
  5.     constVelBall.setVel(Vector3D(3.0,5.0,0.0));  
  6.   
  7.     gravityBall=Mass(5.0,2);  
  8.     gravityBall.init();  
  9.     gravityBall.setVel(Vector3D(-1.0,0.0,0.0));  
  10.     gravityBall.setForce(Vector3D(0.0,-2.0,0.0));  
  11.   
  12.     springBall=Mass(5.0,4);  
  13.     springBall.init();  
  14.     springBall.setVel(Vector3D(2.0,0.0,2.0));  
  15. }  
void initMasses()
{
    constVelBall=Mass(5.0,3);
    constVelBall.init();
    constVelBall.setVel(Vector3D(3.0,5.0,0.0));

    gravityBall=Mass(5.0,2);
    gravityBall.init();
    gravityBall.setVel(Vector3D(-1.0,0.0,0.0));
    gravityBall.setForce(Vector3D(0.0,-2.0,0.0));

    springBall=Mass(5.0,4);
    springBall.init();
    springBall.setVel(Vector3D(2.0,0.0,2.0));
}

然后是模拟检测:
  1. void simulateCheck()  
  2. {  
  3.     Vector3D connectionPos = Vector3D(0.0f, 0.0f, 0.0f);  
  4.     constVelBall.simulate(0.1);  
  5.     constVelBall.checkBnd(-20,20,-20,20);  
  6.     gravityBall.simulate(0.1);  
  7.     gravityBall.checkBnd(-20,20,-20,20);  
  8.   
  9.     springBall.simulate(0.1);  
  10.     Vector3D springVector = springBall.getPos() - connectionPos;  
  11.     springBall.setForce(springVector*(-0.1));  
  12. }  
void simulateCheck()
{
    Vector3D connectionPos = Vector3D(0.0f, 0.0f, 0.0f);
    constVelBall.simulate(0.1);
    constVelBall.checkBnd(-20,20,-20,20);
    gravityBall.simulate(0.1);
    gravityBall.checkBnd(-20,20,-20,20);

    springBall.simulate(0.1);
    Vector3D springVector = springBall.getPos() - connectionPos;
    springBall.setForce(springVector*(-0.1));
}

这两个函数在main中进行调用。

还需要添加一个绘制质点的函数。我们用球体来代表质点,Mass中的size域就用来做半径。

  1. void drawMass(Mass m)  
  2. {  
  3.     Vector3D tmp=m.getPos();  
  4.     glPushMatrix();  
  5.     glTranslatef(tmp.x,tmp.y,tmp.z);  
  6.     gluSphere(mySphere,m.getSize(), 32, 16);  
  7.     glPopMatrix();  
  8. }  
void drawMass(Mass m)
{
    Vector3D tmp=m.getPos();
    glPushMatrix();
    glTranslatef(tmp.x,tmp.y,tmp.z);
    gluSphere(mySphere,m.getSize(), 32, 16);
    glPopMatrix();
}


最后来看渲染函数:

  1. void renderGL()  
  2. {  
  3.     // Clear the color and depth buffers.  
  4.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );  
  5.     // We don't want to modify the projection matrix. */  
  6.     glMatrixMode( GL_MODELVIEW );  
  7.     glLoadIdentity( );  
  8.     // Move down the z-axis.  
  9.     glTranslatef(0.0f,0.0f,-35.0f);  
  10.     glColor3ub(0, 0, 255);                                      // Draw In Blue  
  11.     glBegin(GL_LINES);  
  12.     // Draw The Vertical Lines  
  13.     for (float x = -20; x <= 20; x += 2.0f)                      // x += 1.0f Stands For 1 Meter Of Space In This Example  
  14.     {  
  15.         glVertex3f(x, 20, 0);  
  16.         glVertex3f(x,-20, 0);  
  17.     }  
  18.     // Draw The Horizontal Lines  
  19.     for (float y = -20; y <= 20; y += 2.0f)                      // y += 1.0f Stands For 1 Meter Of Space In This Example  
  20.     {  
  21.         glVertex3f( 20, y, 0);  
  22.         glVertex3f(-20, y, 0);  
  23.     }  
  24.     glEnd();  
  25.     glColor3ub(0,255, 255);  
  26.     drawMass(constVelBall);  
  27.     glColor3ub(255,0, 255);  
  28.     drawMass(gravityBall);  
  29.     glColor3ub(255,255,0);  
  30.     drawMass(springBall);  
  31.     SDL_GL_SwapBuffers( );  
  32. }  
void renderGL()
{
	// Clear the color and depth buffers.
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	// We don't want to modify the projection matrix. */
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity( );
	// Move down the z-axis.
	glTranslatef(0.0f,0.0f,-35.0f);
    glColor3ub(0, 0, 255);										// Draw In Blue
	glBegin(GL_LINES);
	// Draw The Vertical Lines
	for (float x = -20; x <= 20; x += 2.0f)						// x += 1.0f Stands For 1 Meter Of Space In This Example
	{
		glVertex3f(x, 20, 0);
		glVertex3f(x,-20, 0);
	}
	// Draw The Horizontal Lines
	for (float y = -20; y <= 20; y += 2.0f)						// y += 1.0f Stands For 1 Meter Of Space In This Example
	{
		glVertex3f( 20, y, 0);
		glVertex3f(-20, y, 0);
	}
	glEnd();
	glColor3ub(0,255, 255);
	drawMass(constVelBall);
    glColor3ub(255,0, 255);
    drawMass(gravityBall);
    glColor3ub(255,255,0);
    drawMass(springBall);
	SDL_GL_SwapBuffers( );
}

先渲染一些网格,然后对质点进行渲染。

最后的效果就像这样:




源码下载


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值