Page 5 of 6 FirstFirst ... 3456 LastLast
Results 41 to 50 of 56

Thread: OpenGL 3.x Rotation Problem

  1. #41

    Re: OpenGL 3.x Rotation Problem

    haha, that was on purpose!

    Three positive feedback! Waitin for more.

  2. #42

    Re: OpenGL 3.x Rotation Problem

    Hello again!

    This time there seems to be a problem with scaling. I created a 3D cube and when the model matrix is scaled, it shrinks and grows back to its original dimensions! Here's how the model matrix is calculated:
    [code=delphi]
    if UpdateNeeded then
    begin
    CachedMatrix := Mat4Scale(Mat4Translate(Mat4CreateRotationEuler(FR otation),
    Vec3Negate(FPosition)), FScale);

    UpdateNeeded := False;
    end;
    Result := CachedMatrix;
    [/code]
    I suppose the scaling should be placed somewhere else, but where?

    Oh, and here's Mat4Scale's code:
    [code=delphi]
    function Mat4Scale(const M: TBrainMatrix; const V: TBrainVector): TBrainMatrix; inline;
    begin
    Result := M;

    Result.M[0, 0] := Result.M[0, 0] + V.X;
    Result.M[1, 1] := Result.M[1, 1] + V.Y;
    Result.M[2, 2] := Result.M[2, 2] + V.Z;
    end;
    [/code]

    Any ideas, guys?

  3. #43

    Re: OpenGL 3.x Rotation Problem

    If you scale matrix by constant it goes like:
    [pascal]procedure Scale(var M: TMatrix; const s: Single);
    var i: Integer;
    begin
    for i:=0 to 2 do begin
    M[i, 0]:=M[i, 0] * s;
    M[i, 1]:=M[i, 1] * s;
    M[i, 2]:=M[i, 2] * s;
    end;
    end;[/pascal]

    Extending that function to work with vector might be something like: (i'm just guessing here...)
    [pascal]procedure Scale(var M: TMatrix; const v: TVector);
    var i: Integer;
    begin
    for i:=0 to 2 do begin
    M[i, 0]:=M[i, 0] * v.x;
    M[i, 1]:=M[i, 1] * v.y;
    M[i, 2]:=M[i, 2] * v.z;
    end;
    end;[/pascal]

  4. #44

    Re: OpenGL 3.x Rotation Problem

    I tried it, but if the scale vector is (1,1,1), multiplication won't change the matrix.

  5. #45

    Re: OpenGL 3.x Rotation Problem

    Exactly! Because the vector contains scaling "factors", a factor of one means "keep this the same" (a * 1 = a).

    Because the scaling vector contains factors, your code will not work:

    [pascal]
    function Mat4Scale(const M: TBrainMatrix; const V: TBrainVector): TBrainMatrix; inline;
    begin
    Result := M;

    Result.M[0, 0] := Result.M[0, 0] + V.X;
    Result.M[1, 1] := Result.M[1, 1] + V.Y;
    Result.M[2, 2] := Result.M[2, 2] + V.Z;
    end;
    [/pascal]

    Let's say you have an identity matrix:

    1, 0, 0, 0
    0, 1, 0, 0
    0, 0, 1, 0
    0, 0, 0, 1
    And you want to make it twice as big (factor 2). Acoording to your code, this would result in:

    3, 0, 0, 0
    0, 3, 0, 0
    0, 0, 3, 0
    0, 0, 0, 1
    The numbers in the diagonal part of the matrix are also used as scaling factors. As you see, it will result in 3x scaling instead of 2x.

    So, first of all, treat the numbers as factors!

    Secondly, concatenating two transforms is ALWAYS done by matrix multiplication. In this case we would have a scaling matrix, constructed by vector V. It would look like this:

    V.x, 0, 0, 0
    0, V.y, 0, 0
    0, 0, V.z, 0
    0, 0, 0, 1
    Secondly, we have our original matrix M.
    We need to multiply these to get the matrix M with the scaling applied on it.
    This brings me to a more difficult issue:

    Matrix multiplication is not commutative, which means that A x B will not yield the same result as B x A. We should be aware of the order in which we multiply matrices.

    I still haven't figured this part out, so I better don't give any advice, other than that you have to be carefull.

    This is what I'd do:

    [pascal]
    function Mat4Scale(const M: TBrainMatrix; const V: TBrainVector): TBrainMatrix; inline;
    begin
    Result := MatIdentity();
    Result.M[0, 0] := V.X; //The identity matrix has only 1's diagonally, so multiplying
    Result.M[1, 1] := V.Y; //V with 1 makes no sense.. we can assign it directly
    Result.M[2, 2] := V.Z;

    //multiply with M here, this could be
    Result = MatMultiply( Result, M)
    // OR !!
    Result = MatMultiply( M, Result )
    end;
    [/pascal]

    Also, I suggest you study a few examples of matrices and see how they affect geometry:

    http://msdn.microsoft.com/en-us/libr...8VS.85%29.aspx

    (I know it's direct3D, but you can still use this knowledge).

    Also, take a very close look at existing matrix code, instead of writing your own (I use math code written by others. )

    Hope this helps
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  6. #46

    Re: OpenGL 3.x Rotation Problem

    Thanks for this, chronozphere, but I've already tried this approach and it didn't work either.

    Maybe I should scale the vertices when creating an object, let's say a triangle?
    [code=delphi]
    // No scaling
    Vertices.Add(Vec3(0.0, 1.0, 0.0));
    Vertices.Add(Vec3(-1.0, -1.0, 0.0));
    Vertices.Add(Vec3(1.0, -1.0, 0.0));

    // Scaling on
    Vertices.Add(Vec3(0.0 * FScale.X, 1.0 * FScale.Y, 0.0 * FScale.Z));
    Vertices.Add(Vec3(-1.0 * FScale.X, -1.0 * FScale.Y, 0.0 * FScale.Z));
    Vertices.Add(Vec3(1.0 * FScale.X, -1.0 * FScale.Y, 0.0 * FScale.Z));
    [/code]
    But then everytime I change scaling, I'd have to re-build the object's VAO and VBOs... That is certainly not what I want.

  7. #47

    Re: OpenGL 3.x Rotation Problem

    It does work for me. (Oh, note that if your matrix has translation included in it, it will be used in scaling aswell. You need to multiply rotation matrix in different function without translation part)
    [pascal]procedure Scale(var M: TMatrix; const v: TVector); overload;
    var M2: TMatrix;
    begin
    M2:=NewMatrix;
    M2[0,0]:=v.x; M2[1,1]:=v.y; M2[2,2]:=v.z;
    M:=Multiply(M,M2);
    end;

    // call it like this to triple size in Y direction:
    Scale(m2,vector(1,3,1));

    // if you use this kind of vector nothing will happen as intended
    Scale(m2,vector(1,1,1));[/pascal]

  8. #48

    Re: OpenGL 3.x Rotation Problem

    But then everytime I change scaling, I'd have to re-build the object's VAO and VBOs... That is certainly not what I want.
    yeah.. That's why matrices are THE way to do transformations.

    Can you tell me what doesn't work?
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  9. #49

    Re: OpenGL 3.x Rotation Problem

    I tried these both (not at the same time, of course):
    [code=delphi]
    FScale := Vec3(2.0, 2.0, 2.0);
    // #1
    CachedMatrix := Mat4Multiply(Mat4Multiply(Mat4CreateRotationEuler( FRotation),
    Mat4CreateTranslation(Vec3Negate(FPosition))), Mat4CreateScale(FScale));
    // #2
    CachedMatrix := Mat4Multiply(Mat4Multiply(Mat4CreateRotationEuler( FRotation),
    Mat4CreateScale(FScale)), Mat4CreateTranslation(Vec3Negate(FPosition)));
    [/code]

    EDIT
    I got it working. It's still in tests, though. Here's the code anyway:
    [code=delphi]
    CachedMatrix := Mat4Translate(Mat4Multiply(Mat4CreateRotationEuler (FRotation),
    Mat4CreateScale(FScale)), Vec3Negate(FPosition));
    [/code]

  10. #50

    Re: OpenGL 3.x Rotation Problem

    It's me again.

    The problem with scalling has been solved once and for all. Everything works like a charm.

    Now, I want to expand the possibilities of my camera class by adding a third-person mode. The idea to create the camera matrix is simple:
    [code=delphi]
    CachedMatrix := LookAt(Position, Target.Position, Vec3(0.0, 1.0, 0.0));
    [/code]
    This works great, but now, how do I implement moving and strafing? In a first-person mode, I used these:
    [code=delphi]
    procedure TBrainCamera.Move(const AFactor: Single);
    begin
    if (AFactor <> 0.0) then
    begin
    FDirection := Mat4GetDirectionVector(Mat4CreateRotationEuler(Rot ation));

    case FCamType of
    ctFree:
    Position := Vec3(Position.X + (FDirection.X * -AFactor),
    Position.Y + (FDirection.Y * -AFactor),
    Position.Z + (FDirection.Z * -AFactor));
    ctFirstPerson:
    Position := Vec3(Position.X + (FDirection.X * -AFactor),
    Position.Y, Position.Z + (FDirection.Z * -AFactor));
    end;

    UpdateNeeded := True;
    UpdateInvNeeded := True;
    end;
    end;
    procedure TBrainCamera.Strafe(const AFactor: Single);
    begin
    if (AFactor <> 0.0) then
    begin
    FDirection := Mat4GetDirectionVector(Mat4CreateRotationEuler(Rot ation));
    Position := Vec3(Position.X + (FDirection.Z * -AFactor),
    Position.Y, Position.Z + (-FDirection.X * -AFactor));

    UpdateNeeded := True;
    UpdateInvNeeded := True;
    end;
    end;
    [/code]

    My first idea was to translate the target object and change the camera position accordingly to a new target's position. So the code for a third-person camera would be here:
    [code=delphi]
    procedure TBrainCamera.Move(const AFactor: Single);
    begin
    {...}
    ctThirdPerson:
    begin
    Target.Move(AFactor);
    Position := Vec3Subtract(Target.Position, Position);
    end;
    [/code]
    But this approach doesn't seem to work.

    EDIT
    I followed the instructions given here, but it didn't help either.

    From all I know, the best thing would be to base the camera on quaternions, but that would mean re-inventing the whole design from the ground up. I don't want them and I believe it can be done on Euler angles.

    Do you have any suggestions?

Page 5 of 6 FirstFirst ... 3456 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
  •