Vector Operations OpenFrameworks

Embed Size (px)

Citation preview

  • 7/27/2019 Vector Operations OpenFrameworks

    1/4

    5/13 openFrameworks

    ww.openframeworks.cc/tutorials/maths/001_vector_maths.html

    Vector Maths2012/02/23 10:00:00 - Keith Pasko

    Moving through space requires knowledge of where things are and where they are going. Vector Maths is the class of

    mathematics that gives us understanding control over these things in space, allowing for elegant, intuitive, and general

    descriptions of complex structures and movement. Vectors are at the heart of animation, particle systems, and 3d graphics in

    fact, vector maths/linear algebra have made much of modern computer science possible.

    Let's jump into some technical details Shhhhh, hush now, it will all be over soon enough. A vector represents a direction and

    magnitude in an abstract "space" for our current purposes, we can just think of this "space" as the common 2d or 3d world. In

    these worlds, we have standard "basis vectors" and an origin everything else in the world is created from these fundamentals.

    For 3d, the standard origin is (0,0,0), and standard bases [1,0,0] , [0,1,0] , [0,0,1] (it is the same for 2d, but without the 3rd

    component, i.e. [0,0] origin, [1,0] , [0,1] bases). To put a perhaps more familiar name to these, we can call them the x, y, and z

    directions. The allowed operations on these vectors are addition and scalar multiplication - with these, we can generate any

    vector in space.

    Vector operationsscalar multiplication

    Let's say we want to go 3.14 units "to the right" ("along x", "along the first basis"). We multiply by component, so the result is [1 *

    3.14,0 * 3.14,0 * 3.14] = [3.14,0,0]. Similarly, if we want to go "up" ("along y", "along the second basis") by 1.71, we have [0,1,0]

    * 1.71 = [1 * 1.71,0 * 1.71,0 * 1.71] = [0,1.71,0]. We can see that multiplying by a scalar, fittingly, scales the vector, keeping the

    direction the same (or reversing it, if the scalar is negative).

    In OF, this can be done with the * operator or with scale/getScaled:

    The OF reference can be found here

    addition

    Now let's say we want to go 3.14 units to the right, and then 1.71 units up we can add the two vectors we've just created-

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    ofVec3f v(1,2,3);

    return v*3.14; // returns ofVec3f(3.14,6.28,9.42);

    return v.getScaled(3.14); // also returns ofVec3f(3.14,6.28,9.42);

    v.scale(3.14); // internally scales v to ofVec3f(3.14,6.28,9.42);

    //works with vec2f and vec4f as well

    ofVec2f v(0,1); return v*2.718; // returns ofVec3f(0,2.718,0);

    ofVec4f v(0,1,4,3); return v*2.718; // returns ofVec4f(0,2.718,10.872,8.154);

    //note there is also a * operator which is NOT scalar multiplication

    ofVec3f v1(1,2,3); ofVec3f v2(2,3,4);

    return v1*v2; // returns ofVec3f(2,6,12);

    // this is componentwise multiplication between two vectors, and is far less common than scalar mul

  • 7/27/2019 Vector Operations OpenFrameworks

    2/4

    5/13 openFrameworks

    ww.openframeworks.cc/tutorials/maths/001_vector_maths.html

    [3.14,0,0] + [0,1.71,0] = [3.14 + 0,0 + 1.71,0 + 0] = [3.14,1.71,0]. This is called "component-wise addition", as we just add the

    different components of each vector (i.e. x + x, y + y, z + z). This can be visualized by putting one vector at the tip of the other

    vector

    The OF reference can be found here

    application

    Who cares? How is this useful? Let's take a simple example - we have two points a and b in space, and we want to move from

    one to the other. Remember that addition is like putting a vector at the tip of another vector? Well, we know that if we add the

    direction from a to b (we'll call it c) to a, we'll get b: a + c = b. The vector we're looking for is c = b - a.

    Great, now we know the direction from a to b (c = b - a). Again, this means that if we add c to the tip of a, we'll end up at b. If we

    multiply c by various numbers between 0 and 1, we can progressively move from a to b.

    Pip pip, now we can shoot particles from one position to another with ease using our new vector maths. All of these operations

    and concepts work exactly the same way in 3d to go from one point to another in 3d, we once again do a + delta*(b - a) - nothing

    else needed!

    1

    2

    3

    ofVec3f v1(3.14,0,0);

    ofVec3f v2(0,1.71,0);

    return v1+v2; // returns ofVec3f(3.14,1.71,0);

  • 7/27/2019 Vector Operations OpenFrameworks

    3/4

    5/13 openFrameworks

    ww.openframeworks.cc/tutorials/maths/001_vector_maths.html

    Other helpful operations

    length/normalization

    The length of a vector is the square root of the sum of the squares of the components. Huh? In perhaps less obscure terms,

    length(x,y,...) = sqrt( xx + yy + ...) e.g the length of a vector (3,4) = sqrt(33 + 44) = sqrt(25) = 5. Remember our "aim" example,

    going from a to b? Well, now we know how far apart in space a and b are - the length of c (b - a), information crucial for

    simulations, among many other graphics applications. The length of a vector is often denoted by |v| or ||v|| if you see this on the

    wikipediaz somewhere, now you know what it means.

    Normalization is the concept of dividing a vector by its length, turning it into a "unit vector", or vector pointed in the same

    direction, but with a length of 1 this makes sure that the length of the vector doesn't "contaminate" any operations on it. Imagine

    if our basis vector from the first example wasn't normalized- say (1,0,0) was (25504.77707,0,0), then 3.14*basis1 = (80085,0,0),

    which is a bit counterintuitive (its more natural to think that the vector (3.14,0,0) actually goes 3.14 units in the x-direction, not

    80085 units). Now when we see v / |v| , we know it is the normalized vector in the v direction holla.

    dot product / projection / reflection

    The dot product can be a confusing thing. In keeping with the somewhat anal-retentive nature of this tutorial, let's just start with a

    definition- the dot product of a and b [ lets call it dot(a,b) ] = |a||b|cos(theta), where theta is the angle between the two vectors,

    and |a| and |b| are the lengths of a and b, as described in the last section. Great, but why is that useful? Well, first of all, it

    enables us to find the angle between any two vectors in any dimension (2d, 3d,...10d?) since dot(a,b) = |a| |b|cos(theta), theta,the angle between the vectors, is equal to acos(dot(a,b)/|a|*|b|) (a motivation for learning normalizing, as it quite simplifies this

    calculation...if a and b are unit vectors, this is just acos(dot(a,b)) ).

    If you don't care exactly what the angle itself between them is and just care about the cosine (and again assume a and b are

    normalized) then dot(a,b) = cos(theta), quite tidy. Why would we care about the cosine only? Recall that the cosine is positive

    when theta is between pi/2 (90 deg) and -pi/2 (-90 deg), so the dot product is the measure of how much the vectors are pointing

    "in the same direction" to a certain extent. If threshold

  • 7/27/2019 Vector Operations OpenFrameworks

    4/4

    5/13 openFrameworks

    ww.openframeworks.cc/tutorials/maths/001_vector_maths.html

    For the hardcore, our "space" is a vector space, which must be "closed under addition and scalar multiplication," which is the

    fancy way of saying that all combinations of addition and scalar multiplication are also vectors in that same space. The standard

    bases are usually referred to by "e", ie e1, e2, e3, etc we also note that we are most often discussing an orthonormal basis,

    which means that e1, e2, and e3 all have length 1, and are each at 90 degrees to one another. In the difference example, if we

    assume a and b are along a path, then c is one approximation of the path tangent. ** Before the uber-nerds out there slap my

    hand for being incomplete, there are a few other technical requirements to be a vector space these can be found here

    http://en.wikipedia.org/wiki/Vector_space. The dot product is also called the inner product, and with length and this innner product

    defined, we get an "inner product space". In linear algebra terms, this inner product is described by transposing the object and

    multiplying e.g. dot(a,b) = a(transpose) * b the square length of a vector is often written as v(transpose) * v. Projection onto a

    subspace represented by a matrix is similar, A(transpose) * A * x (where A could represent the basis vectors of a plane, for

    example).