2
\$\begingroup\$

In pure physics texbooks, I'm seeing this formula to calculate fluid drag force:

It is clearly stated that it should be opposite to the velocity. Now to me that means, in pseudocode:

fd = get_drag(v) // using the above formula
if v < 0: fd = -fd

That is, if the velocity is negative the drag should be positive, so we invert the returned value.

However, in game code, game physics books and tutorials, I see people doing:

drag = -v
drag.normalise()
fd = get_drag(v)
fd *= drag

That is, we multiply the drag force by the (inverted) velocity unit vector.

This to me is logic in regard to the sign, but also it scales down the drag force by a factor between 0 and 1.

Which one is correct, and why?

PS: to be noted, normalisation involves square root, multiplications and divisions, so it's more expensive than a conditional check and subtraction.

\$\endgroup\$
1
\$\begingroup\$

Both ideas are actually correct, but the second code snippet seems wrong to me.

If it is the same get_drag() in both cases, then it should operate on a scalar, and return a negative number. It should be something like:

drag = v                 # No sign inversion here; get_drag() does it
drag.normalise()
fd = get_drag(length(v)) # Operate on a scalar
drag *= fd               # Get a vector

The first formula operates in one dimension, where the “opposite” of the velocity just means choosing a number that has the opposite sign (hence -fd).

The second formula operates in two or three dimensions, where a force “opposite” of the velocity has to be a scalar multiplied by a unit vector that goes in the opposite direction (hence drag.normalize()`).

Your final assumption that the drag force is “scaled down” is erroneous: a normalised vector has size 1, so the drag force is not changed. Getting the length of drag will give you the original drag force fd.

\$\endgroup\$
  • \$\begingroup\$ You are quite right: I had failed to notice the guy stored the speed (magnitude) separately from the velocity vector. In his code, the "get_drag" does actually work with the magnitude, so multiplying back by the normalised velocity makes sense. In my code, it works on vectors (the if case is repeated for every dimension). I still think that my solution (I currently use abs(v)*v inside get_drag instead of v^2, so I don't have to do three if cases) it's faster than normalisation. I wonder if I'm missing something. Anyway, thanks a lot! It was bugging me for no reason apparently :) \$\endgroup\$ – Fabio Jul 18 '15 at 20:24
  • \$\begingroup\$ But you can’t do it component-wise; this is only valid for linear operations, and the in the drag formula makes it non-linear. Just compare the results you get with v = [1 0 0] and with [0.8 0.6 0]. Both these vector have unit length, but your method will give you 30% less drag with the second vector. \$\endgroup\$ – sam hocevar Jul 20 '15 at 7:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.