It accepts two parameters, the first is an out parameter - a pointer type, so a referenced variable or a pointer to a variable - the second parameter is an in parameter of the same type but const.

This is strange to me, normalizing is a simple calculation, I would expect the function to have one parameter - the vector to be normalised. Why does it have two? could somebody write an example of how I would use it?


Basically it allows you to have an input vector different from an output vector, like so:

D3DXVECTOR3 bulletMovement = /*...*/; // the whole bullet movement
D3DXVECTOR3 bulletDirection = /*...*/; // the DIRECTION of the bullet movement, with a length of 1.
D3DXVec3Normalize(&bulletDirection , &bulletMovement);

This way you keep your whole bullet movement intact and simply modify the direction, because that's the only vector that you want with a length of 1.

It may not be always useful, but if gives you more control over the normalization (although you could do without it being so flexible by making a copy and normalizing it after).

What you generally want is this:

D3DXVECTOR3 mouseDirection = /*...*/;
D3DXVec3Normalize(&mouseDirection, &mouseDirection);

But keep in mind that you have the possibility to have different input/output parameters.


normalizing is a simple calculation, I would expect the function to have one parameter - the vector to be normalised. Why does it have two? could somebody write an example of how I would use it?

Normalizing is, indeed, relatively simple. It's also an operation that is performed often and consequently should be very fast. Performance considerations are especially important when designing math library middleware like D3DX.

The reason there are two parameters is for efficiency, and to some extent robustness. By providing by-reference (via pointer) output and input parameters, the D3DX normalize function can normalize a vector in place or to a new vector without unnecessary by-value copying of the vector object.

By way of contrast, consider the alternatives: If the normalization function took only a single input vector, it would have only two reasonable options to get the result back to the caller:

  1. Return it directly.
  2. Modify the input value.

Option (1) would perforce require a copy of the vector to be returned on the stack (a vector which is much larger than the size of a pointer in real-world scenarios) and so would be somewhat less efficient, even if it is a slightly more natural or convenient API.

Option (2) is cumbersome, would prevent const variables from being normalized without first making a copy, and similarly would require the caller to create a copy if they did not what the input vector modified. So it's both less convenient and in some cases also less efficient.

Update: It's worth noting, as discussed in the comments, that modern C++ compilers can perform a copy elision optimization that would allow them to eliminate the performance overhead of (1) entirely. This optimization was prevalent even back in 2011 when I originally answered this, so I should have pointed it out then.

I can only speculate as to why the designers of the API in question chose to implement it in this fashion; perhaps they were being conservative or had reason to expect that RVO wouldn't or couldn't be performed in some important use cases (by contrast, you can see some API's like Apple's GLKit aggressive expect these sorts of optimizations, even in C, because they return entire objects like matrices on the stack; this may also be informed by knowledge of the underlying platforms calling convention, as well, however).

  • \$\begingroup\$ Regarding (1), doesn't compiler return value optimization (RVO) take care of this in practice? \$\endgroup\$ – Nathan Reed Mar 4 '14 at 0:14
  • \$\begingroup\$ That's a good point. However, copy elision ("RVO") is explicitly permitted as an exception to the "as-if" rule in the C++ standard. It's not described in the C standard (to my knowledge), and this API is a C API. Although since the question is tagged C++ I probably should have mentioned RVO. It must have slipped my mind. \$\endgroup\$ – user1430 Mar 4 '14 at 1:04

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.