Following code snippet resides in the buoyancy
force generator.
1 void ParticleBuoyancy::updateForce(Particle* particle, real duration) 2 { 3 // Calculate the submersion depth. 4 real depth = particle->getPosition().y; 5 // Check if we’re out of the water. 6 if (depth >= waterHeight + maxDepth) return; 7 Vector3 force(0,0,0); 8 // Check if we’re at maximum depth. 9 if (depth <= waterHeight - maxDepth) 10 { 11 force.y = liquidDensity * volume; 12 particle->addForce(force); 13 return; 14 } 15 // Otherwise we are partly submerged. 16 force.y = liquidDensity * volume * 17 (depth - maxDepth - waterHeight) / 2 * maxDepth; 18 particle->addForce(force); 19 }
The formula of ‘d‘ is computed in the below manner:
where yo is the y coordinate of the object and yw is the y coordinate of the liquid plane (assuming it is parallel to the XZ plane).
Why we compute ‘d‘ in such a manner?
The author only leaves the formula to the reader without any further explanation, which once frustrates me for quite a long time.
if you have some experience of 3D programming, especially doing some so-called post-effect or mapping texture coordinates from normal device coordinate to screen space. Then this will be familar to you because it also works this way.
Now let‘s take a look into deeper mechanism of this formula. Trust me, it quite simple:P
We see that:
when
y0 =
yw + s,
we have d =
0;
(1)
when y0 =
yw
, we have
d=-1/2;
(2)
and when
y0 = yw -
s, we have d=-1;
(3)
in fact
‘d‘ is a linear function of y0.
Then d = f(y0) = ky0+b.
So all we
need to do is to find k and b. We choose (1) and (3) to perform the
processing.
The point
(yw
+ s, 0)
and point(yw
- s,-1)
are located on the line. So k =
(-1 - 0)/[(yw - s) - (yw + s)] =
1/2s;
Plug k into (1),
0 = 1/2s*(yw
+ s) + b, sovel this equation we have b
= -(yw +
s)/2s;
Now all the
puzzle are fixed.
d = 1/2s*y0-(yw + s)/2s
d = (y0 - yw - s)/2s