ObjLibrary: Vector2/3 Functions

Overview

Sections:
  1. Overview
  2. Basics
  3. Mathematical Operators
  4. Comparisons
  5. Associated Constants
  6. Norms and Normalization
  7. Planar Norms
  8. Distance Calculations
  9. Component Access
  10. Vector Operations
  11. Rotation
  12. Random Vectors
  13. Bottom of Page
Symbols:

The Vector2 and Vector3 classes were designed to have the same functions with the same names whenever possible. Sometimes they even have idenitical implementations (except for for Vector2/Vector3). In theory, this allows the same algorithms to be used for both. It should also allow complex algoithms to be developed and debugged in 2D and then easily converted to 3D. The downside is that a few of the functions names in 2D sound a bit strange.

This document is intended as a summary of the functions available. For more detailed information, including preconditions, see the function documentation in Vector2.h and Vector3.h.

Last updated October 11, 2017.

Basics

Vector Components:

These member variables can be accessed and changed directly using dot notation. All values that can be implicitly typecast to double (including NaN) are legal.

Constructors:

These create Vector2/3s.

If you are using C++11, the ones that do not take an array are defined as constexpr. If you have glm interaction enabled (OBJ_LIBRARY_GLM_INTERACTION is #defined in ObjSettings.h), there is also a constructor to create a Vector2/3 from a glm::vec2/glm::vec3.

There is also an assignment operator:

There are no constructors to convert directly between Vector2 and Vector3. This allows the Vector2 and Vector3 classes to each be used independantly. A constructor with a single value parameter for all components was also deliberatlely not impleneted so as to cut down on errors.

Setting Multiple Components: Output:

A Vector2 is printed in the format (x, y), with the elements separated by a single space and no line break at the end. The format for a Vector3 is similar: (x, y, z).

Mathematical Operators

Value-Returning:

These functions return the result of the calculation. Neither argument is changed.

In-Place:

These functions modify the left argument to contain the calculated result. A non-const reference to the left argument is returned.

Component-Wise:

These operations are applied between each corresponding pair of components.

Clamping Components:

Clamping variables refers to limiting their values to some range.

Comparisons

Unless otherwise stated, no tolerance is used for any of these functions.

Finiteness:

This function returns false if any component is positive infinity, negative infinity, or NaN, and true if all components are real values.

Zeroness:

The isZero function is used as a precondition for many normalization-related functions.

Equality: Component-Wise (vs. Zero): Component-Wise (vs. Scalars): Component-Wise (vs. Vector2/3s):

Associated Constants

Declared Outside the Class:

There are also similar constants declared for the Vector3 class.

Declared Inside the Class:

Warning: These values are initialized as static constant members. They are initialized when the program starts, just as if they were global variables. This means that, when initializing other global variables, they may not have their values yet. This applies even inside constructors for global variables. The exception is ZERO, which has the correct value even before it is initialized.

The only truly safe thing to do is not initialize global variables using other global variables. This includes not using global variables inside constructors for types that will be used as global variables. This is a general rule for C++, not just for Vector2/3s. Times when a global variables can be used to initialize other global variables safely (e.g. copy = original) include:

Norms and Normalization

The norm of a vector is the distance along it. Most people call this the length of the vector. However, in mathematics, the length of a vector is the number of components it contains (e.g. 2 for a Vector2, 3 for a Vector3). I have chosen to adopt the mathematical convention for these classes.

Determining Norms: Norm Comparisons:

Calculating the norm of a Vector2/3 involves a call to sqrt, and is thus relatively slow. These functions compare the squares of the norms, and thus should be faster than calcuating the norms.

Warning: A tolerance is used for all of these functions. This means that a "less than" comparison is equivilent to a "less than or equals" comparison. It can also lead to incorrect results in some cases. For example, a norm of 1.0e-10 is simulataneously less than, equal to, and greater than a norm of 0.0.

Changing Norms:

All of these functions will generate an assert error if the original vector is zero. If there is a possibility that the original vector is zero, alternate "safe" forms of the functions can be used. These safe forms are slightly slower, but will return a default value instead of crashing if the original vector is zero.

Truncation:

Truncating a vector refers to reducing its norm to a maximum value. If the norm is already less than or equal to that value, there is no effect.

Planar Norms

The planar norm of a Vector3 is what its norm would be if one of its components were excluded. This is equivilent to what the norm would be if the Vector3 was projected onto a coordinate plane. The planes used in the calculations are indicated by the function name.

As a Vector2 is always on the XY plane, there are no planar norm functions for the Vector2 class. The standard functions for norms provide the same functionality.

Determining: Comparisons (vs. Scalars): Comparisons (vs. Vector3s):

Distance Calculations

The Euclidean (ordinary) distance between 2 Vector2/3s is the norm of the difference between them.

Determining Distances: Comparing Distances:

These functions are significantly faster than calculating the distances themselves. A tolerance is used in all cases.

Component Access

All components can be accessed directly using dot notation. These functions allow the components to be conveniantly accessed in different forms.

Vectors With Zeroed Components:

These functions return copies of the Vector2/3s with some components set to 0.0.

Array Access:

This function assumes that the Vector2/3 member fields are layed out sequentially. If the compiler lays them out in some other way, an assert error will be generated at runtime when this function is called.

The function can be used to pass values to OpenGL calls more efficiently. For example,

	glVertex3d(longAndComplexCodeYeildingAVector3().x,
	           longAndComplexCodeYeildingAVector3().y,
	           longAndComplexCodeYeildingAVector3().z);
can become
	glVertex3dv(longAndComplexCodeYeildingAVector3().getAsArray());

In addition, this function can also be used to convert between Vector2s and Vector3s. To do this, pass the array as an argument to an array-based constructor. For example,

	Vector2(my_vec3.getAsArray());  // enough array elements
	Vector3(my_vec2.getAsArray(), 2);  // only 2 of 3 array elements available
Note that the array size is necessary when converting to a "larger" vector. Otherwise the constructor would look beyond the bounds of the array.

Warning: Careless use of this function can result in invalid pointers or array out-of-bounds. This is especially a problem when the code that uses the array is being adapted from handling Vector2s to Vector3s or vice versa.

Converting to glm Vectors:

A Vector2/3 can be typecast to a glm::vec2/glm::vec3.

The typecast must be made explicitly, or the compiler will not be able to resolve it.

	Vector3 obj3(1.0, 2.0, 3.0);
	glm::vec3 glm3 = (glm::vec3)(obj3);

I think this has something to do with how glm uses templates.

Vector Operations

Products: Comparing Directions: Calculating Projections:

Both of these functions will generate an assert error at runtime if project_onto is zero. If there is a possibility that project_onto is zero, alternate "safe" forms of the functions can be used. These safe forms are slightly slower, but will return a default value instead of crashing if project_onto is zero.

Alternately, if project_onto is known to be a normal vector, the faster "normal" forms of the functions can be used. These will generate an assert error if either vector is not normal.

Calculating Reflections:

These functions are for calculating the direction of a Vector2/3 after it has been reflected off a surface with the specified surface normal.

Calculating Angles:

Both of these functions will generate an assert error at runtime if either vector is zero. If there is a possibility that the vectors might be zero, alternate "safe" forms of the functions can be used. These safe forms are slightly slower, but will return a default value instead of crashing if one of the vectors is zero.

Alternately, if the vectors are both known to be normal vectors, the faster "normal" forms of the functions can be used. These will generate an assert error if either vector is not normal.

Matrix Products:

These functions all defines a 3x3 matrix that is multiplied by the Vector3. The vector is always interpreted as a column vector and multiplied on the right of the matrix.

Closest Point on a Line:

Rotation

Determining Rotation: Calculating Rotated Vectors:

It is also possible to rotate a Vector2/3 towards a target direction with a maximum change in angle. This is useful when rotating something smoothly over several frames. The rotation can be "free" or restricted to be around a single axis.

Both of these functions will generate an assert error at runtime if either vector is zero. If there is a possibility that the vectors might be zero, alternate "safe" forms of the functions can be used. These safe forms are slightly slower, but will return a default value instead of crashing if one of the vectors is zero.

Alternately, if the vectors are both known to be normal vectors, the faster "normal" forms of the functions can be used. These will generate an assert error if axis is not normal.

In-Place Vector Rotations:

These functions rotate a Vector2/3 towards a target direction with a maximum change in angle.

Both of these functions will generate an assert error at runtime if either vector is zero. If there is a possibility that the vectors might be zero, alternate "safe" forms of the functions can be used. These safe forms are slightly slower, but will return a default value instead of crashing if one of the vectors is zero.

Alternately, if the vectors are both known to be normal vectors, the faster "normal" forms of the functions can be used. These will generate an assert error if axis is not normal.

Random Vectors

All of these functions return Vector2/3s with a uniform distribution.

Circle/Sphere-Based Distributions:

These functions all call rand() to generate random numbers. There are also versions that allow the "random" number to be specifed as seeds. The seeds should be double values in the range [0.0, 1.0).

Rectangle-Based Distributions:

These functions all call rand() to generate random numbers. There are also versions that allow the "random" number to be specifed as seeds. The seeds should be double values in the range [0.0, 1.0).


Back to ObjLibrary page
Back to resources page
Back to home page