jdelauney / SIMD-VectorMath-UnitTest

For testing asm SIMD (SSE/SSE 2/SSE 3/SSE 4.x / AVX /AVX 2) vector math library (2f, 4f, matrix, quaternion...) with Lazarus and FreePascal Compiler
Mozilla Public License 2.0
8 stars 0 forks source link

Vector Helper Rotate and RotateX #23

Closed dicepd closed 6 years ago

dicepd commented 6 years ago

Ok doing test for VectorHelper.

Rotate seems to work the way I think it should

  vt1.Create(1,1,1,1);  // unit point
  vt4 := vt1.Rotate(ZHmgVector, pi/2);
  AssertEquals('Rotate:Sub1 X failed ', -1.0, vt4.X);
  AssertEquals('Rotate:Sub2 Y failed ',  1.0, vt4.Y);
  AssertEquals('Rotate:Sub3 Z failed ',  1.0, vt4.Z);
  AssertEquals('Rotate:Sub4 W failed ',  1.0, vt4.W);
  vt4 := vt1.Rotate(ZHmgVector, -pi/2);
  AssertEquals('Rotate:Sub5 X failed ',  1.0, vt4.X);
  AssertEquals('Rotate:Sub6 Y failed ', -1.0, vt4.Y);
  AssertEquals('Rotate:Sub7 Z failed ',  1.0, vt4.Z);
  AssertEquals('Rotate:Sub8 W failed ',  1.0, vt4.W);
  // inverted axis vector result should be opposite from above
  vt4 := vt1.Rotate(-ZHmgVector, pi/2);
  AssertEquals('Rotate:Sub9 X failed ',   1.0, vt4.X);
  AssertEquals('Rotate:Sub10 Y failed ', -1.0, vt4.Y);
  AssertEquals('Rotate:Sub11 Z failed ',  1.0, vt4.Z);
  AssertEquals('Rotate:Sub12 W failed ',  1.0, vt4.W);
  vt4 := vt1.Rotate(-ZHmgVector, -pi/2);
  AssertEquals('Rotate:Sub13 X failed ', -1.0, vt4.X);
  AssertEquals('Rotate:Sub14 Y failed ',  1.0, vt4.Y);
  AssertEquals('Rotate:Sub15 Z failed ',  1.0, vt4.Z);
  AssertEquals('Rotate:Sub16 W failed ',  1.0, vt4.W);              

These tests pass. So looking at the first test I am looking from +Z onto plane of XY, I have a point, X:1,Y:1,(can't see Z component parallel projection) I rotate positive 90degs around Z I now see a point at X:-1,Y:1

That is the convention I am used to :). Now for RotateAroundZ I get results as the inverted axis, any reason for this before I go changing lots of pascal code?

jdelauney commented 6 years ago

I take look quickly into rotate function axis have a w of 0 instead of 1 before normalize this can be the problem

In TGLZMatrix4f.CreateRotationMatrix change axis.AsVector3f := anAxis; by axis.Create(anAxis); for assuming is affine

instead of homogenous yous can direct pass affine as parameter. At final, an affine vector is used for axis param

dicepd commented 6 years ago

So you think that Rotate is wrong and RotateAroundZ is right then?

I do not understand about the axis as ZHmgVector already has a W of 0 ZHmgVector : TGLZVector = (X:0; Y:0; Z:1; W:0); Axis W plays no part in any of the pascal calculations, I cannot see why this should matter.

Slightly puzzled here.

dicepd commented 6 years ago

Ok I just went into the GLScene code where I found this

procedure TGLNodes.RotateAroundZ(Angle: Single);
var
  I: Integer;
  C, S, V1: Single;
  V: PAffineVector;
begin
  SinCos(CPIDiv180 * Angle, S, C);
  for I := 0 to Count - 1 do
  begin
    V := PAffineVector(Items[I].AsAddress);
    V1 := V^.V[1];
    V^.V[1] := C * V1 + S * V^.V[0];     <---- Y = Cos(Y) + Sin(X)
    V^.V[0] := C * V^.V[0] - S * V1;      
  end;
  NotifyChange;
end;                               

This is our current code

function TGLZVectorHelper.RotateAroundZ(alpha : Single) : TGLZVector;
var
   c, s : Single;
begin
   SinCos(alpha, s, c);
   Result.X:=c*Self.X+s*Self.Y;      <---- X = Cos(Y) + Sin(X)
   Result.Y:=c*Self.Y-s*Self.X;
   Result.Z:=Self.Z;
end;                       

I think you transposed X and Y when you modified this for use as a method on Vector.

jdelauney commented 6 years ago

It's misunderstanding by me

So the functional code you wrote, above is Ok

and this is from glvectorgeometry.pas

function VectorRotateAroundZ(const v : TAffineVector; alpha : Single) : TAffineVector;
var
   c, s : Single;
begin
   GLVectorGeometry.SinCos(alpha, s, c);
   Result.X:=c*v.X+s*v.Y;
   Result.Y:=c*v.Y-s*v.X;
   Result.Z:=v.Z;
end;
dicepd commented 6 years ago

So the question remains why is it that way and where is it used, could it be for some screen or view coord system rather than world coord system?

Whoever wrote TGLNodes did not like the glvectorgeometry.pas version

jdelauney commented 6 years ago

The RotateAround funcs are for screen or view coord. Rotate func use matrix and here it's not the case. So we can keep this in our mind and see later. And for be in concordance with rotate just write RotateAround as is

function TNativeGLZVectorHelper.RotateAroundZ(angle : Single):TNativeGLZVector;
var
   rotMatrix : TNativeGLZMatrix;
begin
   rotMatrix.CreateRotationMatrixZ(Angle);
   Result:=rotMatrix*Self;
end; 
dicepd commented 6 years ago

Ahh, it all become a bit clearer now, I suspect that this was written for the 3DS file. AutoDesk were always idiots with their file formats trying to make it harder for other people to use them, and not reflect their internal model.

jdelauney commented 6 years ago

I'm just going to take look on the rotation math

rotate around z is x' = xcos q - ysin q y' = xsin q + ycos q z' = z

for inverse rotation we just need change the sign of angle

function TNativeGLZVectorHelper.RotateAroundZ(alpha : Single) : TNativeGLZVector;
var
   c, s : Single;
begin
   SinCos(-alpha, s, c);
   Result.X:=c*Self.X+s*Self.Y;
   Result.Y:=c*Self.Y-s*Self.X;
   Result.Z:=Self.Z;
end; 

an now result is correct is -1,1 instead of 1,-1

left hand, right hand, cc,ccw......the big deal :)

jdelauney commented 6 years ago

I'm think using matrix it's better, like i say above

dicepd commented 6 years ago

But a lot slower when just doing a rotation.

jdelauney commented 6 years ago

Yes, it surely possible, so we let it as is (just change the sign of angle) ? but need to check other rotatearound to. Or perhaps clone movearound by adding fast as prefix will have MoveAround and FastMoveAround or something like this ?

so for those finals words for today (damn it's already tomorrow ) i'm going to sleep.... see you son :)

dicepd commented 6 years ago

I had not got to MoveAround yet, if it is used in there then that may be one reason for it. So in conclusion

No wonder you wanted a rewrite. TBH as we are doing testing on all these I would be inclined to stick to the pure math model and fix up usage, it confuses people less.

dicepd commented 6 years ago

Ok I have had a look at the MoveAround code and if we change to pure math model then the only change is we no longer have to negate PitchNow and DegToRadian(turnDelta) thus reducing the processing by a few clock cycles and should you wish to convert to assembler then two expensive load masks are eliminated.

jdelauney commented 6 years ago

No wonder you wanted a rewrite. TBH as we are doing testing on all these I would be inclined to stick to the pure math model and fix up usage, it confuses people less.

I'm agree with you. And this is why i'd like write my own engine. Many little things in GLScene are non-sens or not used

So let's go for pure math model. It's better 👍

i'll take a look also to movearound. Just for infos this function was extracted from the Camera. I think this why is inverted

And for CreateMatrix function we can save around 12 multiply with the use of some temp vars

dicepd commented 6 years ago

Ok I need a few pointers on the usage of the last four routines in VectorHelper. Looks like they are used for numbers between 0 and 1 but to what end?

dicepd commented 6 years ago

I have spent too long looking at why TestRotateWithMatrixAroundZ fails I probably can no longer see the wood from the trees and it needs another pair of eyes on it. As far as I can see all the math is right but it is coming out with the wrong answer. This is for pure pascal code.

See if you can spot whatever silly mistake I have made Jerome. As the matrix code worked without issue I thought this would be a few mins work last night before i gave up for the day.

jdelauney commented 6 years ago

Ok i've checked you've forget change MoveAround by MoveWithMatrixAround in functionnals test so the 3 RotateWithMatrixAround fails.

I've check the CreateRotationMatrix actually is for Left Hand just need to invert sign of sin for back to Right Hand

This is for pure pascal code.

All RotateWithMatrixAround Tests failed with NATIVE code. It's crazy. I'll must debug full output data to see. Don't see anything in code why this happened

And with SSE tests are green.

For Average4 and FaceForward failed. For FaceFoward i think i've the solution. And i must take into average4

jdelauney commented 6 years ago

Now i've also a little doubt. With CreateRotationMatrix it is for Left or Right Hand. I must check.

dicepd commented 6 years ago

Have you got latest changes some of those issues were fixed.

jdelauney commented 6 years ago

Ok Native code for RotateWithMatrixAround work just forget to make change in native.inc (pff.....)

dicepd commented 6 years ago

All good here, that must have had some head scratching moments in Scene if you tried using rotate and rotate axis in the same routine.

jdelauney commented 6 years ago

Yes, that's what I feared #25