Page 1 of 2 12 LastLast
Results 1 to 10 of 20

Thread: Velocity based on angles

  1. #1
    Legendary Member NecroDOME's Avatar
    Join Date
    Mar 2004
    Location
    The Netherlands, Eindhoven
    Posts
    1,059

    Velocity based on angles

    So, I have a vector (x, y, z) representing angles (in 3D - doh) and a vector velocity (x, y ,z).

    For example, if velocity := (10, 0, 0) and the angle := (0, 0, Pi/2), my final vector needs to point up.

    Currenly I have this, but I think it's not correct... (tis rotates a point around a point)
    [pascal]
    function RotateVector(RotatePoint, v, Angle : TD3DVector) : TD3DVector;
    var NilPoint : TD3DVector;
    begin
    NilPoint := VectorSub(v, RotatePoint); // get dist from nilpoint...
    v := Nilpoint;

    // Z-axis
    NilPoint.X := v.X * cos(Angle.Z) - v.Y *sin(Angle.Z);
    NilPoint.Y := v.X * sin(Angle.Z) + v.Y *cos(Angle.Z);
    v.X := NilPoint.X;
    v.Y := NilPoint.Y;

    // Y-axis
    NilPoint.Y := v.Y * cos(Angle.Y) - v.Z *sin(Angle.Y);
    NilPoint.Z := v.Y * sin(Angle.Y) + v.Z *cos(Angle.Y);
    v.Y := NilPoint.Y;
    v.Z := NilPoint.Z;

    // X-axis
    NilPoint.X := v.X * cos(Angle.X) - v.Z *sin(Angle.X);
    NilPoint.Z := v.X * sin(Angle.X) + v.Z *cos(Angle.X);
    v.X := NilPoint.X;
    v.Z := NilPoint.Z;

    Result := VectorAdd(RotatePoint, NilPoint);
    end;
    [/pascal]

    Why I need this? I'm trying to make a helicopter fly
    NecroSOFT - End of line -

  2. #2

    Velocity based on angles

    do this:

    normalise your vector so it will have length of 1 (but still point into same direction), then multiply all xyz components of it it by the new length you desire!
    This is my game project - Top Down City:
    http://www.pascalgamedevelopment.com...y-Topic-Reboot

    My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
    http://www.pascalgamedevelopment.com...source+manager

  3. #3
    Legendary Member NecroDOME's Avatar
    Join Date
    Mar 2004
    Location
    The Netherlands, Eindhoven
    Posts
    1,059

    Velocity based on angles

    yes... but I still have the same direction... I need to rotate the vector.

    btw thanx, I also have some use for that
    NecroSOFT - End of line -

  4. #4

    Velocity based on angles

    Quote Originally Posted by NecroDOME
    yes... but I still have the same direction... I need to rotate the vector.

    btw thanx, I also have some use for that
    to rotate a vector (this is for 2D XY plane only):

    Code:
    procedure RotateVertexXY(var vector; const angle: decimal);
    var
    COORDS: array[0..1] of single absolute vector;
    TEMP: array[0..1] of single;
    AFUNC: array[0..1] of single;
    anglerad: Single;
    begin
    TEMP[0]:= COORDS[0];
    TEMP[1]:= COORDS[1];
    
    anglerad:= degtorad(angle);
    
    // caching is faster
    AFUNC[0]:= Cos(anglerad);
    AFUNC[1]:= Sin(anglerad);
    
    COORDS[0]:= TEMP[0] * AFUNC[0] - TEMP[1] * AFUNC[1];
    COORDS[1]:= TEMP[0] * AFUNC[1] + TEMP[1] * AFUNC[0];
    end;
    This is my game project - Top Down City:
    http://www.pascalgamedevelopment.com...y-Topic-Reboot

    My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
    http://www.pascalgamedevelopment.com...source+manager

  5. #5
    Legendary Member NecroDOME's Avatar
    Join Date
    Mar 2004
    Location
    The Netherlands, Eindhoven
    Posts
    1,059

    Velocity based on angles

    in 2D it isn't that difficult... I'm not home now, butt ill try something when I get home.

    I post update soon....
    NecroSOFT - End of line -

  6. #6

    Velocity based on angles

    have you considered using quarternions?
    This is my game project - Top Down City:
    http://www.pascalgamedevelopment.com...y-Topic-Reboot

    My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
    http://www.pascalgamedevelopment.com...source+manager

  7. #7
    Legendary Member NecroDOME's Avatar
    Join Date
    Mar 2004
    Location
    The Netherlands, Eindhoven
    Posts
    1,059

    Velocity based on angles

    I have no clue how quarternions work of what they are or how they work.
    NecroSOFT - End of line -

  8. #8

    re-

    For 3d vectors there is two comun way of doing rotation:
    -Using a matrix
    -Using a Quaternion.

    With matrix you need to store 9 float values but you can do rotations, translations and scale, you can accumulate severals of those operation in a single matrix. If you use APIs like opengl or direct3d then you already have support for work with matrix.

    With Quaternions you only need 4 float values, but you can just do rotations with it, (but translation and scale are a trivial calc to do anyway), the big adventage over matrices is that you can do easily the Interpolate operation (called Slerp) between two quaternion, this is a initial rotation and a final rotation and then using a value like 0.5 for get the half way rotation. Quaternion is the preffered way to do skeletal animations in characters; also people say quaternion avoid a problem called Gimbal Lock.

    Google for a file unit called GEOMETRY.PAS, which is a collection of useful 3d geometry functions and procedures including matrices and quaternions operations.

    anyway here are some of my quaternion procedures:


    [pascal]

    type
    TQuaternion = record
    (x, y, z, w: single);
    end;


    //you have to use this for initialize the quaternion before acumulating rotations.
    Procedure QuaternionIdentity(var Q:tquaternion; add:boolean=false);
    begin
    q.w:=1;
    q.x:=0;
    q.y:=0;
    q.z:=0;
    if add then q.w:=0;
    end;


    procedure QuaternionMultiply(q1,q2:tquaternion; var Qr:tquaternion);
    var
    _qr:tquaternion;
    begin

    _qr.w:=q1.w*q2.w-q1.x*q2.x-q1.y*q2.y-q1.z*q2.z;
    _qr.x:=q1.y*q2.z-q1.z*q2.y+q1.w*q2.x+q2.w*q1.x;
    _qr.y:=q1.z*q2.x-q1.x*q2.z+q1.w*q2.y+q2.w*q1.y;
    _qr.z:=q1.x*q2.y-q1.y*q2.x+q1.w*q2.z+q2.w*q1.z;
    qr:=_qr;

    end;


    //angles are in degree!!! not in radians!.
    procedure QuaternionSetAxisAngle(var q:TQuaternion; angle:single; const mx,my,mz:single);
    var
    factor, scaleBy, sinhalfangle: single;
    Qa:Tquaternion;
    begin

    angle:=angle*cpidiv180; //cpidiv180 is a const, convert to radians.

    factor := mx*mx+my*my+mz*mz;
    if factor=0 then factor := EPSILON;
    scaleBy := 1/sqrt(factor);
    qa.w := cos(angle/2);
    sinHalfAngle := sin(angle/2);
    qa.x := mx*scaleBy*sinHalfAngle;
    qa.y := my*scaleBy*sinHalfAngle;
    qa.z := mz*scaleBy*sinHalfAngle;

    quaternionmultiply(qa,q,q); //very important, seem quaternion multiply is not commutative,
    //the acumulative quaternion have to be the 2th operand


    end;


    //warning, result is not accumulative!. we are using here pitch-heading-bank, or (x,y,z) order;

    procedure QuaternionSetEulerangles_XYZ(var q:TQuaternion; x,y,z:single);
    var
    xQ, yQ, zQ:TQuaternion;
    begin
    QuaternionIdentity(Q);
    QuaternionIdentity(xq);
    QuaternionIdentity(yQ);
    QuaternionIdentity(zQ);

    QuaternionSetAxisAngle(xQ,x, 1,0,0);
    QuaternionSetAxisAngle(yQ,y, 0,1,0);
    QuaternionSetAxisAngle(zQ,z, 0,0,1);

    QuaternionMultiply(yQ,xQ,q);
    QuaternionMultiply(zQ,q,q);

    end;

    //same as prior procedure but in this the Result is acumulative, mean if Q already have a rotation then it is acumulated with this another one.

    Procedure Quaternion_Rotation_XYZ(var q:TQuaternion; x,y,z:single); //in degrees;
    var
    q2:tquaternion;
    begin
    QuaternionSetEulerangles_xyz(q2,x,y,z);
    QuaternionMultiply(q,q2,q);
    end;

    //P1 is a vector, Q is a rotation stored in a quaternion, p2 will get p1 rotated by Q.

    Procedure Transform_from_Quaternion(p1:tvector; var p2:tvector; Q:tquaternion);
    var
    x,y,z,w:single;
    begin
    x:=q.x;
    y:=q.y;
    z:=q.z;
    w:=q.w;
    p2.x:= w*w*p1.x + 2*y*w*p1.z - 2*z*w*p1.y + x*x*p1.x + 2*y*x*p1.y + 2*z*x*p1.z - z*z*p1.x - y*y*p1.x;
    p2.y:= 2*x*y*p1.x + y*y*p1.y + 2*z*y*p1.z + 2*w*z*p1.x - z*z*p1.y + w*w*p1.y - 2*x*w*p1.z - x*x*p1.y;
    p2.z:= 2*x*z*p1.x + 2*y*z*p1.y + z*z*p1.z - 2*w*y*p1.x - y*y*p1.z + 2*w*x*p1.y - x*x*p1.z + w*w*p1.z;
    end;

    //you pass a vector which is at absolute position from the origin, then you pass a Q which is already rotated.
    //the procedure will return back the absolute vector with the rotation found in the quaternion around the origen.

    Procedure Rotation_from_Origin(var v:tvector; const Q:TQuaternion; const origen:tvector);
    var
    a:tvector;
    begin
    vectorsubstract(v,origen,a); //substract two vector.
    Transform_from_Quaternion(a,a,q);
    vectoradd(origen,a,v); //add two vectors.
    end;

    [/pascal]


    [/pascal]

  9. #9

    Velocity based on angles

    Have a look at one of my projects:

    http://www.nitrogen.za.org/projectinfo.asp?id=19

    It shows a cylinder made up of vertexes getting rotated around a central point.. How to apply a rotation in a specific axis to a matrix, then how to apply that matrix to the vertex to get it to rotate!
    My site: DelphiTuts.com (coming soon)...

    Download Font Studio 4.21 here.

  10. #10
    Legendary Member NecroDOME's Avatar
    Join Date
    Mar 2004
    Location
    The Netherlands, Eindhoven
    Posts
    1,059

    Velocity based on angles

    Yeah, quaternions are exacly what I needed (I not yet understand them, but they work)

    Quaternion is the preffered way to do skeletal animations in characters
    Still need to implement that in my engine...
    NecroSOFT - End of line -

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •