Sunday, March 16, 2008

B001-moving things in 3D using the Vector3F class

Why do you need this tutorial?

This tutorial tells you how to move things in 3d using some basic vector math,
and introduce you to our Vector3F class. You can skip to the Vecto3F documentation
if you know vector math.


This tutorial includes:

A Concepts:

A1. What is vector?

A2. Normalizing vectors

A3. Adding vectors

A4. Subtracting vectors

A5. Scaling vectors

A6. Dot product

A7. Cross products


B HowTo:

B1. How to move a point from point A to point B?

B2. How to animate a point moving from A to B in N steps?

B3. How to find a normal of a plane?

B4. How to find a line perpendicular to a given line?

B5. How to scale a group of point with a base point?





A1. What is vector?


Vector


"vector, is a geometric object which has both
a magnitude and a direction"(Wikipedia)


A vector can be seen as point in space, it can be represented by three numeric
values, such as (x,y,z), that indicated the distance from this point to the
origin(0,0,0)


in our Vector3F class you can create a vector by calling:


Vector3F myPoint=new Vector3F(3,5,10);


this line creates a vector called myPoint at the
location x=3, y=5,z=10.


Direction

the direction from 0,0,0 to the point(x,y,z) is the direction of the vector.


Magnitude
the magnitude of this vector is the distance between (0,0,0) and (x,yz)
in our Vector3F class, you can find the magnitude of the vector by calling
the mag() method. For example:


//v is a vector

Vector3F v;

//get magnitude of v

Float magnitude = v.mag();





A2. Normalizing vectors


Normalizing a vector is to make the magnitude of a vector equals 1. This is
usually when we do different kinds of calculations such as scaling a vector
to a desire length or calculate angles


In out Vector3F class, you can use the normalize() method

Vector3F v=new vecto3F(0,5,0);

v.normalize();


the result is, v become (0,1,0);




A3. Adding vector


is best illustrated in this diagram


(hyperphysics)


in our Vector3F class, there are two ways to do this.

Assume we have two instances vector3F called A and B.

Vector3F A=new Vector(1,2,3);

Vector3F B=new Vector(2,3,4);


Case 1, we want to add B to A, so that

A=A+B

In this case, we can do:

A.add(B);

The result is A becomes (3,4,7)


Case 2, we want do want to change the values of A and B, we want to add them
to a new Vector called C such as C=A+B

In this case we do

Vector3F C=Vector3F.add(A,B);

The result is A and B are un changed, but C becomes (3,4,7)


See documentation for Vector3F.add(Vector3F) and
vector3F.add(Vector3F,Vector3F) for detail




A4. Subtracting vectors


vector subtraction can be described by this diagram:


(pearMath)


Simmular to addition, there are two ways to do subtractions:

Assume we have two instances vector3F called A and B.

Vector3F A=new Vector(1,2,3);

Vector3F B=new Vector(2,3,4);


Case 1, we want to subtract B from A, so that

A=A-B

In this case, we can do:

A.sub(B);

The result is A becomes (-1,-1,-1)


Case 2, we want do want to change the values of A and B, we want to subtract
them to a new Vector called C such that C=A-B

In this case we do

Vector3F C=Vector3F.subtract(A,B);

The result is A and B are un changed, but C becomes (-1,-1,-1)


See documentation for Vector3F.sub(Vector3F) and
vector3F.subtract(Vector3F,Vector3F) for detail





A5. Scaling vectors

scale a vector is to scale the magnitude of a vector by a number. in Vecto3F,
we can do this by:

Vector v=new Vector(0,3,0);

v.scale(4);


the result is v become (0,12,0)



A6. Dot product

"dot product, also known as the scalar product, is
an operation which takes two vectors over the real numbers R and returns a real-valued
scalar quantity. It is the standard inner product of the Euclidean space.
"(see
wikipedia for more detail
)


you may not need to use this, but the way to do it in Vector3F is:


First assume we have two vectors as such:

Vector3F A=new Vector(1,2,3);

Vector3F B=new Vector(2,3,4);




Case 1: A=A dot B

A.dot(B);




Case2: C=A dot B

Vector3F C=Vector3F.dot(A,B)





A7. Cross products

"the cross product is a binary operation on two
vectors in a three-dimensional Euclidean space that results in another vector
which is perpendicular to the two input vectors.
"(see
wikipedia for more detail
)


You may need to do a cross product very often when you a scripting sptial transformations.
In Vector3F, there are two ways to do it. First assume we have two vectors as
such:

Vector3F A=new Vector(1,2,3);

Vector3F B=new Vector(2,3,4);




Case 1: A=A cross B

A.cross(B);




Case2: C=A cross B

Vector3F C=Vector3F.cross(A,B)





B1. How to move a point from point A to point B?

Moving a point from A to B is changing the x,y,z value of point A into corresponding
values from point B.

Here is an example using Vector3F.

let say PointA and PointB are both instances of Vector3F.


PointA.set(PointB)


this line makes each of the x,y,z value of PointA equals to each of the x,y,z
values of PointB.

see Vector3F.set(Vector3F) method


B2. How to animate a point moving in space?

If you wan to animate a point moving from PointA to PointB in the duration of
10 frames, here are the things you may want to do:

1. find the distance between PointA and PointB

2. Divide the distance by 10 to get the length that the point wants to move
each frame

3. Using the move direction and move length to find the vector that indicates
the change of position in a single frame.

4. move the point.


here is the Vector3F version:

Assume the Point that is being animate is an instance of Vector3F called myPoint,
and Point A and B are also instance of Vector3F called PointA and PointB.

Initially myPoint is at PointA, we want to move it to PointB in 10 steps

//1. find the distance D between PointA and PointB

double distance = PointA.distanceTo(PointB);


//2. Divide the distance by 10

//to get the distance that the point

//wants to move each frame

double moveDist=distance/10;


//3. first fine the direction that the point

//moves towards

Vector3F direction=Vector3F.subtract(PointB, PointA);


//normalize the vector

direction.normalize();


//scale the direction vector with the distance you want
to move

direction.scale(moveDist);


//4. move the point in a single frame

myPoint.add(direction);


Because the behaviors are being called every frame, therefore you only have
script the movement in a single frame, and this action will be carried out every
frame automatically by the system. So how do you make it stop moving? Simply
check to see if myPoint has moved to PointB. The code is:

if ( myPoint.equals(PointB)) //than stop moving

However, it's better to put tolerance into our code to avoid bugs, so we change
above condition to :

if (myPoint.distanceTo(PointB)<0.001) //then stop

The "0.001" in the code is the tolerance. No need to explain this
line right?


We can look at the entire animation structure as:


//if the myPoint is not at PointB

//( pay attention to the negate sign "!" in the logical expression

if( ! myPoint.distanceTo(PointB)<0.001)>



//move the point one step

//put your code here:

double distance = PointA.distanceTo(PointB);

double moveDist=distance/10;

Vector3F direction=Vector3F.subtract(PointB, PointA);

direction.normalize();

direction.scale(moveDist);

myPoint.add(direction);





}




this illustration shows a movement in constant speed, however there are many
ways to move a point from A to B, such as:

if( ! myPoint.distanceTo(PointB)>0.001)

{



double distance = myPoint.distanceTo(PointB);

double moveDist=distance/10;

Vector3F direction=Vector3F.subtract(PointB, myPoint);

direction.normalize();

direction.scale(moveDist);

myPoint.add(direction);



}

In this case, the movement will slow down as it get closer to PointB exponentially,
and it will take forever to complete the movement if you don't set a tolerance.

you can come up with your own way of animating movements.




B3. How to find a normal of a plane?

The normal to plane is the cross product of two vectors on the plane

You make want to take note on the following scenarios:

1. when the plane is defined by 3 points:

let say there are point A,B,C on the plane, the math is:

normal=(A-B) cross (C-B)

the Vector3F version is:

Assume point A,B,C are expressed as instances of Vector3F.

Vector3F normal= Vector3F.cross( Vector3F.subtract(A,B),
Vector3F.subtract(C,B) ) ;


I know is not very readable, so you can also write it as:

// let value1=A-B

Vector3F value1=Vector3F.subtract(A,B);

//let value 2=C-B

Vector3F value2=Vector3F.subtract(C,B);

//let normal = value1 cross value2

Vector3F normal=Vector3F.cross(value1, value2);


let's just consider this case for the time being


B4. How to find a line perpendicular to a given line?

A normal of a plane is always perpendicular to any lines on that plane. Knowing
this will help us find lines perpendicular to a given line.

For example we want to find a line perpendicular to line A-B, and line A-B is
expressed as two endpoints A and B. A and B are instances of Vector3F.

We first assume line A-B exist in an arbitrary plane.

remember plane can be defined by three points, so we will make an arbitrary
point C.

C can be any thing, but if you want to have more control over where C is relative
to A, you can create C using an offset


//this offset tells you C is right above B at one unit.

Vector3F offset=new Vecto3F(0,0,1);

//let C=B+offset

Vector3F C=Vector3F.add(B, new Vector3F(0,0,1));


now you have a plane, the name thing is to find the normal.

Vector3F value1=Vector3F.subtract(A,B)

Vector3F value2=Vector3F.subtract(C,B)

Vector3F normal=Vector3F.cross(value1, value2);


this normal is perpendicular to lineA-B, you can move it anywhere like:

Vector3F D = Vector3F.add(normal,B)

this line will create a point D where line D-B is perpendicular to line A-B


B5. How to scale a group of point with a base point?


If we have to scale a group of points base on a given base point that is not
(0,0,0), there are basically three steps:


1. we have to translate all points to new position so that are based on (0,0,0)

2. scale all the points

3. undo the translate we have done in part 1


Vector3F version is:

Assume the base Point is a Vector3F called basePoint.

We want to scale 3 times in size


Foreach point P(which is a Vector3F) in our points:





Vector3F offset=Vector3F(basePoint-new Vector3F(0,0,0));

//translate to a 0,0,0 base coordinate system

P.sub(offset);

//scale the vector

P.scale(3);

//undo the translation

P.add(offset);






0 comments: