泡泡是由于水的表面张力而形成的。这种张力是物体受到拉力作用时,存在于其内部而垂直于两相邻 肥皂泡部分接触面上的相互牵引力。
肥皂“打破”了水的表面张力,它把表面张力降低到只有通常状况下的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();
}
效果
这里用了两个质点内部影响泡泡,会有形状变化的动态效果,下面是在泡泡内部贴一张图的效果,加上泡泡变化的效果非常有趣