Fast and efficient way to store orientation in 3D space? - math

I originally stored an objects origin and orientation in 3D space using 3 vectors representing the objects origin, forward and up directions.
To apply to correct transformation to the modelview matrix stack I compose the affine transformation matrix using these three vectors.
Translation is trivial, however for rotation is applied by constructing the correct rotation matrix (depending on the angle and axis of rotation) and applying it to these 3 vectors.
I'm using this method for a very large number of objects and the rotation/ affine matrix composing is causing a performance bottleneck.
I'm wondering if there is a more sensible/efficient way to store the orientation?

I originally stored an objects origin and orientation in 3D space using 3 vectors representing the objects origin, forward and up directions.
Or in other words: You're storing a 3×3 matrix. The matrices OpenGL use are just the same, though they're 4×4, but the only difference to your is, that the element 4,4 is always 1, the elements 0...3,4 are all 0, and the first column 0,0...3 is the cross product of forward and up, usually called right.
This is actually the most concise and directly accessible way to represent an objects placement in 3D space. You can apply any kind of transformation, by performing a single matrix multiplication then.
Another method is using a quaternion together with an offset vector. But quaternions must be turned into a matrix if you want your objects to be translatable (or you could chain up a lot of translation/rotation pairings for a transformation hierachy, but using a matrix actually causes less overhead).

Other than memory, what's stopping you from storing the whole 4x4 affine matrix?
Better yet, ISTR that if the array is normalised the bottom row is usually [0, 0, 0, 1] so you only need to store the top three rows.

A quaternion is probably the most natural/efficient way to store an orientation (it should be better in all respects than forward/up vectors). A quaternion will take 4 values to store, and takes 10 multiplications and 15 additions to convert to a 3x3 rotation matrix -- no divisions or transcendental functions are required.
If you are especially pressed for space, you can probably get by with only 3 values, as you can generate the first element of a unit quaternion robustly from the remaining three. This will take an additional 3 multiplications, 3 additions, and a square root (it is also slightly tricky, since you need to make sure this first element is nonnegative...)

Quaternions transformations may be faster then Matrix on current GPGPUs where the access for global memory is much slower then to local memory.
According to this tables you compute twice much but need to fetch less then half of memory.
Rendering have the vertex shader uniforms stored as local memory, the only reasonable here is the use of matrices.

Related

How to convert points between two coordinate systems with different rotations

Imagine two coordinate systems layed on top of each other, with a rotation and scale difference between the two:
The problem is to convert a point from the non-rotated system to the other. What we do have, are four corner points forming a rectangle, with coordinates known for both systems at each point. We also know the rotation difference, and I think I at least should know the scale difference too. How do I convert a point from the non-rotated system to the rotated system? I have Unity3D at use.
Extra points for clarity in math :)
PS: I'm writing this really late, going to edit later for more clarity.
Some linear algebra does the trick:
Express each operation as a matrix and matrix multiply those to combine them into a single resulting matrix (for efficiency).
If translation is involved you need to add a dimension to your matrices, see homogenous coordinates.
The reason is that the mappings are affine ones then, not linear ones. You can ignore the extra dimension in the end result. It is just a nice way to embed affine mappings into linear ones, so the algebra is easier.
Example
M = M_trans * M_rot * M_scale
x' = M x
The order here is right to left: vector x is first scaled, then rotated, then translated into vector x'. (Using column vectors).
Hints on the matrices: Rotation Matrix, Scaling Matrix
For deriving 2D formulas when given 3D ones: either keep z = 0 or delete the 3rd row and 3rd column from each matrix.

Generate random point on a 2D disk in 3D space given normal vector

Is there a simple and efficient method to generate a random (uniformly distributed) point on a disk "hanging" in 3-dimensional space? The disk is defined by its normal.
Ideally, I would like to avoid rotation matrices, as I do not fully understand them, and I know they have issues.
So far, I've tried generating a 3D unit vector and projecting it onto the plane of the disk, which does ensure that the point is within the disk, but not that it's uniformly distributed.
I also tried scaling the generated vector according to some function of its length, but I couldn't get a uniform distribution back regardless.
I had an idea that involved creating 2 vectors perpendicular to each other and the normal, to define a local coordinate system. Then I could generate a point on the unit disk as in 2D and convert the result back to the global coordinate system. This seems like it would be quite efficient, as it involves some precomputation (which I'm completely fine with) and only simple calculations afterwards (this is for a raytracer, so it'll happen a lot). The problem is, I don't know how to reliably calculate the local coordinate system's basis vectors while avoiding possible issues like collinearity.
Any help is much appreciated.
A easy way to calculate orthogonal basis vectors u, v for a plane with normal n = (a,b,c) is finding the component with least absolute value, and making u orthogonal to that component; the rest pretty much follows. For example, if the first component is the one with minimal absolute value, you can pick these basis vectors:
u = (0, -c, b) // n·u = -bc+cb = 0
v = (b²+c², -ab, -ac) // n·v = ab²+ac²-ab²-ac² = 0, u·v = abc-abc = 0

Linear Algebra in Games in a 2D space

I am currently teaching myself linear algebra in games and I almost feel ready to use my new-found knowledge in a simple 2D space. I plan on using a math library, with vectors/matrices etc. to represent positions and direction unlike my last game, which was simple enough not to need it.
I just want some clarification on this issue. First, is it valid to express a position in 2D space in 4x4 homogeneous coordinates, like this:
[400, 300, 0, 1]
Here, I am assuming, for simplicity that we are working in a fixed resolution (and in screen space) of 800 x 600, so this should be a point in the middle of the screen.
Is this valid?
Suppose that this position represents the position of the player, if I used a vector, I could represent the direction the player is facing:
[400, 400, 0, 0]
So this vector would represent that the player is facing the bottom of the screen (if we are working in screen space.
Is this valid?
Lastly, if I wanted to rotate the player by 90 degrees, I know I would multiply the vector by a matrix/quarternion, but this is where I get confused. I know that quarternions are more efficient, but I'm not exactly sure how I would go about rotating the direction my player is facing.
Could someone explain the math behind constructing a quarternion and multiplying it by my face vector?
I also heard that OpenGL and D3D represent vectors in a different manner, how does that work? I don't exactly understand it.
I am trying to start getting a handle on basic linear algebra in games before I step into a 3D space in several months.
You can represent your position as a 4D coordinate, however, I would recommend using only the dimensions that are needed (i.e. a 2D vector).
The direction is mostly expressed as a vector that starts at the player's position and points in the according direction. So a direction vector of (0,1) would be much easier to handle.
Given that vector you can use a rotation matrix. Quaternions are not really necessary in that case because you don't want to rotate about arbitrary axes. You just want to rotate about the z-axis. You helper library should provide methods to create such matrix and transform the vector with it (transform as a normal).
I am not sure about the difference between the OpenGL's and D3D's representation of the vectors. But I think, it is all about memory usage which should be a thing you don't want to worry about.
I can not answer all of your questions, but in terms of what is 'valid' or not it all completely depends on if it contains all of the information that you need and it makes sense to you.
Furthermore it is a little strange to have the direction that an object is facing be a non-unit vector. Basically you do not need the information of how long the vector is to figure out the direction they are facing, You simply need to be able to figure out the radians or degrees that they have rotated from 0 degrees or radians. Therefore people usually simply encode the radians or degrees directly as many linear algebra libraries will allow you to do vector math using them.

Should I use a Cartesian (x and y) or polar (angle and magnitude) coordinate system to represent velocity?

I'm programming a physics game. It seems I can use 2 systems for storing a character's movement data:
A) x & y components (Cartesian coordinates)
B) speed and direction components (polar coordinates)
It seems I need to ultimately decide on one of these 2 systems because:
A) They both represent the same information about a vector
B) It seems redundant and inefficient to maintain both
Most game programming resources I've found use Cartesian. To my understanding, all transformations like friction, rotation, acceleration, etc are combined into each vector via multiplication, division, etc. But to me, polar feels more modular and, therefore, more malleable because each vector is comprised of and can be broken down into its two elements (direction and magnitude). If I want to modify one of these independently, I can set its value without needing to deconstruct it into separate parts.
I'm guessing that different models are suitable for different types of games. But...
What trade-offs affect the decision to use Cartesian versus polar?
When does one model become cumbersome or verbose?
Or am I way off?
The premise of your question is a bit odd. Magnitude plus angle and sum of 2 basis components are both ways to specify a vector in 2-space. In either case, you record 2 scalars (i.e. you do not have a separate variable to represent the x unit vector). The choice of rectangular vs polar coordinates doesn't change the nature of something from a vector to a scalar or vice versa.
However, different representations certainly have their uses. As you mention, breaking down into orthogonal components has a ready advantage for addition of two vectors and other operations. In addition, most displays use a x-y coordinate system, so rendering is easier because you don't have to do a coordinate transform.
If your game was based on a polar coordinate system (say a ship that always faces the center of a circle), you might actually want to represent it using polar coordinates. Other than that, rectangular coordinates are generally easier to use.
Either way, sin and cos will probably become your friend. Just remember that most graphical coordinate systems have y-down as positive.
You are confused about the difference between vectors and scalars.
The speed along the x-axis is a scalar.
The speed along the y-axis is also a scalar.
When you combine those two numbers into a single mathematical object, that object is the velocity vector. Think of it like a 2-element array: [x, y]
Similarly,
Thrust is a scalar.
Angle is a scalar.
The combination of these two numbers is a different kind of velocity vector [thrust, angle].
Any velocity that is expressable in your [x, y] system can be also expressed in your [thrust, angle] system.
You might be getting confused with "basis vectors." In your first coordinate system, a basis vector is a vector that is one unit long and which points along the x or y axis. So [1, 0] would be a basis vector that is one-unit along the x axis, and [0, 1] would be a basis vector that is one unit along the y axis. The thing that is interesting about basis vectors is that any vector at all can be expressed as a linear combination of basis vectors.
So if i = [1, 0], and j = [0, 1] then
(34.5 i + -4.45 j) is a vector,
(4.65 i + 23.3 j) is a vector,
etc. (if you're not familiar with vector addition, just google it, it's easy)
Now you might think that when take your 2-dimensional space and you use a different coordinate system (like polar coordinates, which is really what your thrust/angle coordinates are) you are getting away from basis vectors, but in fact you are not. So, for your thrust and angle coordinate system, your basis vectors are:
i = 1 unit of positive thrust, or radius
and
j = 1 degree (or radian) of positive angle
Any possible velocity is still a combination of i and j, your basis vectors.
The two representations are mathematically equivalent. Additionally, converting one to the other is a simple O(1) operation. So be aware that it's probably not a make-or-break decision. That said, in terms of ease-of-use:
You're probably right that it depends on the circumstance as to which is more appropriate, so whichever you can foresee yourself using more often, then go with that, and convert to the other form when necessary.
Use language features to help you abstract the specific type of implementation. E.g. If you're using Java, have a IPoint interface with the relevant methods. That way you can choose an implementation, or even more, to suit the needs. You can even choose certain parts of the program to work with one implementation, and other parts with other types. Proper architecture will make these things seemless.
Depending on certain calculations you might prefer to use ones that will provide you with more accuracy. If you're doing floating point arithmetic with vastly different magnitudes you might suffer precision loss. In that case it may, for example, be easier to use the angle and length representation, because angles will have persistent accuracy, and lengths might be of similar magnitude, whereas there is no guarantee of such in the x and y representation. Although granted that this is a slightly less pressing issue if you're values will be reasonable and calculations nominal.
What you're calling "scalar quantities" is really just a polar vector, right? So your question isn't so much about vectors vc scalars as it is about cartesian vs polar coordinate systems. [x,y] and [theta,r] are both vectors.
I haven't done a whole lot of physics programming, but the last time I did and it started to get complicated (modeling fish swimming in a three-dimensional space), I was much more comfortable dealing with polar coordinates. I was working from scratch implementing a boids-like algorithm, and I found it much more straightforward to think in terms of polar vectors, especially when working in 3 dimensions. I also found using trigonometric functions (acos(), asin(), etc.) cleaner than using the pythagorean formulae you'd use in a cartesian system.
But are you actually coding things from such a low level?
The dynamics of a system are usually easier to describe in the (point, velocity) framework. Indeed, the "fundamental" ODE is usually described in this system:
d (mv) / dt = force(x)
and hence are also easier to plug into a black box Runge Kutta solver.
However, any system will do, thanks to canonical transformations.

What is a 3D Vector and how does it differ from a 3D point?

Does a 3D vector differ from a 3D point tuple (x,y,z) in the context of 3D game mathematics?
If they are different, then how do I calculate a vector given a 3d point?
The difference is that a vector is an algebraic object that may or may not be given as the set of coordinates in some space. (thanks to bungalobill for correcting my sloppiness).
A point is just a point given by coordinates. Generally, one can conflate the two. If you are given a set of coordinates, and told that they constitute a 'point' with no further information (choice of basis, etc), then you can just hand that set of numbers back and legitimately claim to have produced a vector.
The largest difference between the two is that it makes no sense to do things to one that you can do to the other. For example,
You can add vectors: <1 2 3> + <3 2 1> = <4 4 4>
You can multiply (or scale) a vector by a number (generally called a scalar)
2 * <1 1 1> = <2 2 2>
You can ask how far apart two points are: d((1, 2, 3), (3, 2, 1) = sqrt((1 - 3)2 + (2 - 2)2 + (3 - 1)2) = sqrt(8) ~= 2.82
A good intuitive way to think about the association between a vector and a point is that a vector tells you how to get from the origin (that one point in space to which we assign the coordinates (0, 0, 0)) to its associated point.
If you translate your coordinate system, then you get a new vector for the same point. Although the coordinates that make up the point will undergo the same translation so it's a pretty easy conflation to make between the two.
Likewise if rotate the coordinate system or apply some other transformation (e.g. a shear), then the coordinates and vector associated to the point will also change.
It's also possible for a vector to be something else entirely, for example a bounded function on the interval [0, 1] is a vector because you can multiply it by a real number and add it to another function on the interval and it will satisfy certain requirements (namely the axioms of a vectorspace). In this case one thinks of having one coordinate for each real number, x, in [0, 1] where the value of that coordinate is just f(x). So that's the easiest example of an infinite dimensional vector space.
There are all sorts of vector spaces and the notion that a vector is a 'point and a direction' (or whatever it's supposed to be) is actually pretty vacuous.
A vector represents a change from one state to another. To create one, you need two states (in this case, points), and then you subtract the initial state from the final state in order to get the resultant vector.
Vectors are a more general idea that a point in 3D space.
Vectors can have 2, 3, or n dimensions. They represent many quantities in the physical world (e.g., velocity, force, acceleration) besides position.
A mathematician would say that a vector is a first order tensor that transforms according to this rule:
u(i) = A(i, j)v(j)
You need both point and vector because they are different. A point in 3D space denoting position is a vector, but every vector is not a point in 3D space.
Then there's the computer science notion of a vector as a container - it's an abstraction for an array of values or references. This is a different concept from a mathematician's idea of a vector, because every vector container need not obey the first order tensor transformation law (e.g. a Vector of OrderItems). That's yet another separate idea.
It's important to keep all these in mind when talking about vectors and points.
Does a 3D vector differ from a 3D point tuple (x,y,z) in the context of 3D game mathematics?
Traditionaly vector means a direction and speed. A point could be considered a vector from the world orgin of one time step. (even though it may not be considered mathematically pure)
If they are different, then how do I calculate a vector given a 3d point?
target-tower is the common mnemonic.
Careful on your usage of this. The resulting vector is really normal*velocity. If you want to change it into something useful in a game application: you will need to normalize the vector first.
Example: Joe is at (10,0,0) and he wants to go to (10,10,0)
Target-Tower: (10,10,0)-(10,0,0)=(0,10,0)
Normalize the resulting vector: (0,1,0)
Apply "physics": (0,1,0) * speed*elapsed_time < speed = 3 and we'll say that the computer froze for a whole 2 seconds between the last step and this one for ease of computation >
=(0,6,0)
Add the resulting vector to Joes current point in space to get his next point in space: ... =(10,6,0)
Normal = vector/(sqrt(x*x+y*y+z*z))
...I think I have everything here
Vector is the change in the states. A point is the static point. Two vectors can be parallel or perpendicular. You can have product of two vectors which is a third vector. You can multiply a vector by a constant. You can add two vectors.
All these operations are not allowed on point. So program wise if you think both as a C++ class, there will be many such methods in the vector class but probably only Get and Set for point.
In the context of game mathematics there is no difference.
Points are elements of an affine space.† Vectors are elements of a vector (aka linear) space. When you choose an origin in an affine space it automatically induces a linear structure on that affine space. The contrary is also true: if you have a vector space it already satisfies all the axioms of an affine space.
The fact is that when it comes to computation, the only way to represent an affine space numerically is to use tuples of numbers, which also form a vector space.
Each object in a game always has an origin, and it is crucial to know where it is. That origin is set relative to the origin of the world, which is set relative to the origin of the camera/viewport. The vertices of the object are represented as vectors -- offsets from the object origin. You use matrix multiplication to transform the objects -- that is too a purely vector space operation (you cannot multiply an affine point by a matrix without specifying the origin first). Etc, etc... As we see all those triplets of numbers that we might think of as 'points' are actually vectors in the local coordinate system.
So is there any reason to distinguish between the two outside the study of algebra? It is an unnecessary abstraction, and unnecessary abstractions are harmful (KISS). So my answer is no, just go with a single vector type.
† Or any topological space outside the context of game development.
A vector is a line, that is a sequence of points but that it can be represented by two points, the starting and the ending point.
If you take the origin as the starting point, then you can describe your vector giving only the ending point.

Resources