OpenGL物理泡泡

泡泡是由于水的表面张力而形成的。这种张力是物体受到拉力作用时,存在于其内部而垂直于两相邻 肥皂泡部分接触面上的相互牵引力。肥皂“打破”了水的表面张力,它把表面张力降低到只有通常状况下的1/3,而这正是吹泡泡所需的最佳张力。

要点

为了达到模拟泡泡的目的,需要考虑以下两点

1. 水分子之间的张力(相邻分子间的吸引力):约束相邻分子之间的距离

2. 泡泡内部空气对所有泡泡表面水分子的作用力:使得泡泡鼓起来

模拟思路

用一个质点模拟一个水分子,将所有水分子排列在一个圆上,将相邻的水分子用具有弹力的线连接起来模拟水分子之间的张力; 在圆的内部放N个质量较大的质点对所有的水分子产生作用力。

实现

1. 质点类

质点类模拟水分子和泡泡内部空气压力作用质点

class Point
{
public:
    float x, y;//位置
    float fx, fy;//受到的外力合
    float vx, vy;//移动速度

    float mass;//质量
    Point() {
        fx = 0;
        fy = 0;
        vx = vy = 0;
        x = y = 0;
        mass = MASS_DEFAULT;
    }
    Point(float x, float y)
    {
        fx = 0;
        fy = 0;
        vx = vy = 0;
        this->x = x;
        this->y = y;
        mass = MASS_DEFAULT;
    }
    Point(float x, float y, float mass)
    {
        fx = 0;
        fy = 0;
        this->x = x;
        this->y = y;
        vx = vy = 0;
        this->mass = mass*MASS_DEFAULT;
    }
    void Move() {
        fx = fx / mass;//外力除以质量等于加速度
        fy = fy / mass;
        vx += fx;//加速度改变速度
        vy += fy;
        x += vx;//速度改变位置
        y += vy;
        fx = fy = 0;
    }
};

2. 质点间作用力

float Power(const Point *p1, Point *p2)
{
    float x = p1->x - p2->x;//计算距离
    float y = p1->y - p2->y;

    float dist = (x*x + y*y);
    float dist2 = sqrt(dist);

    x /= dist2 * 8;
    y /= dist2 * 8;

    x *= p2->mass*p1->mass / dist;//f=(m1*m2/R^2)
    y *= p2->mass*p1->mass / dist;

    //外力作用于泡泡上的质点
    p2->fx -= x;
    p2->fy -= y;

    return dist;//返回能量值
}

3.用弹力公式模拟张力

float Spring(Point *p1, Point *p2, float best_dist)
{
    float x = p1->x - p2->x;
    float y = p1->y - p2->y;

    float dist = sqrt(x*x + y*y);
    float ch_dist = (dist - best_dist);//形变长度
    if (ch_dist <= 1e-10)
        return 0;

    x /= dist;//力的方向
    y /= dist;

    float p = ch_dist*K_FLOAT;//形变长度*弹力系数==弹力

    x = x*p;
    y = y*p;

    //弹力作用于连接的两个质点
    p1->fx -= x;
    p1->fy -= y;
    p2->fx += x;
    p2->fy += y;

    return dist;
}

4.OpenGL绘制

void display()
{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    static float r=.99, g= .99, b= .99;

    glColor4f(1, 1, 1, 0.5f);
    glLineWidth(2.5f);
    glBindTexture(GL_TEXTURE_2D, TexName);
    glBegin(GL_POLYGON);
    // 绘制多边形   
    for (int i = 0; i < POINT_SIZE; i++)
    {
        glVertex2f(points[i]->x, points[i]->y);
        glTexCoord2fv(TexCoord[i]);
    }
    glVertex2f(points[0]->x, points[0]->y);
    glEnd();

    glColor4f(r, g, b,0.5f);
    glBegin(GL_LINE_STRIP);
    // 绘制框线   
    for (int i = 0; i < POINT_SIZE; i++)
    {
        glVertex2f(points[i]->x, points[i]->y);
    }
    glVertex2f(points[0]->x, points[0]->y);
    glEnd();
    glEnd();
    glFlush();
}

效果

这里用了两个质点内部影响泡泡,会有形状变化的动态效果,下面是在泡泡内部贴一张图的效果,加上泡泡变化的效果非常有趣

你可以去下载源码看看 https://download.csdn.net/download/u012706436/9795811

公告
本博客基于TinyBlog搭建,关注公众号CoderThing