Originally posted in https://github.com/dotnet/corefx/issues/157
as this is also features which would benefit from ref passing into and out-of matrix... unfortunatly I though I could be clever and give an interface to a struct and get just a reference of that struct, but it ends up being a separate entity entirely. Especially in a full suite, the same vector(s) might be easily reference by multiple consumers without having to keep a reference of the object they are in generically.
can we have additional matrix methods, that are rotate( axis1, axis2, angle) where axis1 and 2 are enumerations for 'forward', 'right' and 'up' or whatever native direction your matrices are?
enum { forward, right, left, back[ward], up, down }; where you can specify a direction normal from the matrix and rotate that towards another vector, with a given angle.
( Another solution would be to propose the rules of the JIT and allow adding/extending classes in System.Numerics.Vectors from 3rd party places instead of also requiring optimizations only get considered if the code is in a specifically named DLL; since this does seem to be a 1-off )
In real physics you rarely would apply exactly on a singular axis. It's only convenient in navigating virtual spaces from current input devices...
More specifically
I have a RotateRelative( x, y, z ) method that internally has a tick counter that goes from 0 to 5 for the 6 combinations of roll, pitch and yaw... or rotation about primary axis... This calls a more general function that does rotate( x_axis, /*to*/ y_axis, angle ) to roll left(or right depending on direction of your axis I guess, or -angle which is just a float)
rotate pitch up (pulling back on a airplane yoke)...
rotate( y_axis, z_axis, angle ) /* rotates pitch down in a positive direction. */
These are simply sin(angle),cos(angle) applied to 2 lines of the matrix. (unfortunately I think your matrix is column major, so the rows can't be treated as the direction numbers for the matrix... to apply forward/backward translation as scale(forward, x ) to move in space that much? getting too abstract again?
a third method I think already exists to rotate a axis around an arbitrary axis by an angle? can build a quaternion for that and reduce to a matrix?
Experimentation has shown that in small increments ( < 90 degrees/sec in 60th of that intervals for 90 degress/60 frames) it's not too inaccurate to just use the same order (roll, pitch, yaw) to get a resulting transformation. But I do prefer to just keep my matrix as the orientation representation with an offset that works as the origin of that matrix... which an inverse application of that can work as a camera, which is a rare computation compared to other relative motion calculations....
https://docs.google.com/document/d/1_6JdZ0VplMFpBeR3QOcV5vhlOGYyn52T4-fITgI6lbc
I jotted that down a bit ago.
https://d3x0r.org:444/javascript/test3d/ (self signed certificate, beware, I'm spreading knowledge, please login and save the sources yourself) ... I did update my fork of three.js to have to above mentioned methods.
There's a few buttons at the top, Mode 1, Mode 2 and Mode 3; and Controls 1 and Controls 2.
Mode 1 and Controls 1 is the default. Controls1 click and drag moves like first person camera, controls 2 , click and move is an obit camera (not really important; no motion really required)
Mode 1 - top left cube is reference relative rotation cube stepping through each of the variations... The bottom 6 cubes have their relative rotation always applied in the same order (the order specified by the text over them) ... The 3 cubes above the bottom 6 are single rotation references for directionality... It turns 90 degress and then pauses. Mode 2 is the same as Mode 1 really except slightly faster; so the divergences appear sooner...
Mode 1 - the lower 6 are slow motion, as if rotated sequentailly 90 degrees in each of it's directions; in the various combinartions. THe three rotations happen then a pause showing completed doing 90 degrees each way.
Mode2 - always applies the rotations in the same order but in smaller steps; some of these are faster than the ideal (top left) and some are slower.... I'm not sure what the reason exactly is for the combinations of three that are the same.
Mode 3 the lower 6 cubes are based on building a quaternion using roll pitch yaw... multiplying in order (if text is yaw, pitch, roll... the multiplication is ( ( yaw * pitch ) * roll ) . This is saved as a target vector, and then a slerp is used between initial position and the computed target... so especially with larger angles applied; the resulting computation is not the same... demonstrating quaternions to have similar problems... and ideally should also be muxed though an iteration of applied ordering.
I'm having a bit of trouble understanding what the specific request is. It sounds like what you are trying to do is roughly "interpolate between two direction vectors". If that's an accurate description, do Quaternion.Lerp and/or Quaternion.Slerp help you at all? It seems like you can accomplish what you are describing with those functions, but perhaps I'm misunderstanding your proposal.
I am also unclear on what the specific request is here.
Regarding this:
( Another solution would be to propose the rules of the JIT and allow adding/extending classes in System.Numerics.Vectors from 3rd party places instead of also requiring optimizations only get considered if the code is in a specifically named DLL; since this does seem to be a 1-off )
I'm not sure what it would mean to "propose the rules of the JIT", but I assume that what you mean is to have an extension mechanism that would provide assembly implementations for user-specified methods, that the JIT would recognize and "plug in". Such a mechanism might be interesting, but would be non-trivial to provide.
would be to propose the rules of the JIT
should read... "would be to propose that the rules of the JIT be published so others can take advantage of it."
There's nothing special in the code (at least in the case of how mono implemented it) just that the JIT recognizes a series of math ops as able to be SIMD'd - but, they do only apply that to a specific DLL/.so . There's no attributes; no strange syntax or keywords that are outside the normal language.
re: "interpolate between two direction vectors"
As far as I can tell you can scale between 0-1 as being between two axis... wouldn't help if I say rotated 95 degrees which would put the first axis past the position of the second axis...
INLINEFUNC( void, Rotate, ( RCOORD dAngle, P_POINT vaxis1, P_POINT vaxis2 ) )
{
_POINT v1, v2;
_POINT vsave;
RCOORD dsin = (RCOORD)SIN( dAngle )
, dcos = (RCOORD)COS( dAngle );
MemCpy( vsave, vaxis1, sizeof( _POINT ) );
DOFUNC(scale)( v1, vaxis1, dcos );
DOFUNC(scale)( v2, vaxis2, dsin );
DOFUNC(sub)( vaxis1, v1, v2 );
DOFUNC(scale)( v2, vsave, dsin );
DOFUNC(scale)( v1, vaxis2, dcos );
DOFUNC(add)( vaxis2, v2, v1 );
}
copy of the C code; DOFUNC is a wraper that switches inline/external reference... it's a noop, other others scale is _, add/sub are +/- respectifly.
an RCOORD is a real coordiate (float/double implementation externally defined)
a _POINT is a RCOORD[nDimensions] whereas a VECTOR is a RCOORD_
but that works as vectors directly from the matrix, since the first row is 'right' the second row is 'up' and the third row is 'forward' (row as in a horizontal set of numbers, not column which is a vertical set of numbers in a matrix)
@mellinoe, @CarolEidt
The request was defined clearly.
The op wants to be able to use the reference to the vector structures instead of copying the, Does that not compute?
He indicates that he understands that he can make his own interface which exposes the API he desires but the difficulty underlying is that all the MS implementations seem to take the type without the REF annotation which required that the vector be copied by value when passing it to to such functions.
What is so hard to understand about that? Did you guys think adding ref locals was going to mitigate this? ;)
His proposal also included an a request of an addition to methods on the Vector Type, the methods themselves are possibly not warranted simply because one would be able to interpolate in the application as required however none the less....
I furthermore support the initial portion of the proposition and further propose that all Collection types should provide a ref overload for methods such as Add, Remove, Contains etc as well AND ALSO that Equals and operators provide true reference support as well.
I.e. in struct implementations as this == this as well as this.Equals(this) shouldn't perform any copying...
Especially since TypedReference is not allowed to used in Equals at all...
__makeref(@this).Equals(__makeref(that));
In interim you can define a reference delegate and use that to suit your needs.
internal delegate T ReferenceFunc<T>(ref T t);
internal delegate void ReferenceAction<T>(ref T t);
internal delegate T BoxingReference<T>(ref object o);
Sorry if I'm coming off as obtuse, but if the operation is just a combination of the above functions (i.e. Scale-Subtraction-Scale-Add), can you simply implement the function over those other primitives that we provide? I'm not sure such a specific compound operation is used widely enough to warrant it's own specialized function. After all, there are an infinite number of compound operations we could provide, but it really only makes sense to add them if they are universally useful (or close to it).
Your totally missing the point which is:
One would be copying the vectors in those methods in such cases, e.g. if he used your methods.... he would have to define his own (and would probably use ref)
@d3x0r This topic's fallen inactive, so I'm going to close it for now. If you still feel strongly that there's some functionality missing here, please clarify some of the above and we can continue the discussion.
Most helpful comment
There's nothing special in the code (at least in the case of how mono implemented it) just that the JIT recognizes a series of math ops as able to be SIMD'd - but, they do only apply that to a specific DLL/.so . There's no attributes; no strange syntax or keywords that are outside the normal language.
re: "interpolate between two direction vectors"
As far as I can tell you can scale between 0-1 as being between two axis... wouldn't help if I say rotated 95 degrees which would put the first axis past the position of the second axis...
copy of the C code; DOFUNC is a wraper that switches inline/external reference... it's a noop, other others scale is _, add/sub are +/- respectifly.
an RCOORD is a real coordiate (float/double implementation externally defined)
a _POINT is a RCOORD[nDimensions] whereas a VECTOR is a RCOORD_
but that works as vectors directly from the matrix, since the first row is 'right' the second row is 'up' and the third row is 'forward' (row as in a horizontal set of numbers, not column which is a vertical set of numbers in a matrix)