I need to flip a quaternion from right:
x = left to right
y = front to back
z = top to bottom
to left handed coordinates where:
x = left to right
y = top to bottom
z = front to back
How would I go about doing this?
I don't think any of these answers is correct.
Andres is correct that quaternions don't have handedness (*). Handedness (or what I'll call "axis conventions") is a property that humans apply; it's how we map our concepts of "forward, right, up" to the X, Y, Z axes.
These things are true:
Pure-rotation matrices (orthogonal, determinant 1, etc) can be converted to a unit quaternion and back, recovering the original matrix.
Matrices that are not pure rotations (ones that have determinant -1, for example matrices that flip a single axis) are also called "improper rotations", and cannot be converted to a unit quaternion and back. Your mat_to_quat() routine may not blow up, but it won't give you the right answer (in the sense that quat_to_mat(mat_to_quat(M)) == M).
A change-of-basis that swaps handedness has determinant -1. It is an improper rotation: equivalent to a rotation (maybe identity) composed with a mirroring about the origin.
To change the basis of a quaternion, say from ROS (right-handed) to Unity (left-handed), we can use the method of .
mat3x3 ros_to_unity = /* construct this by hand */;
mat3x3 unity_to_ros = ros_to_unity.inverse();
quat q_ros = ...;
mat3x3 m_unity = ros_to_unity * mat3x3(q_ros) * unity_to_ros ;
quat q_unity = mat_to_quat(m_unity);
Lines 1-4 are simply the method of https://stackoverflow.com/a/39519079/194921: "How do you perform a change-of-basis on a matrix?"
Line 5 is interesting. We know mat_to_quat() only works on pure-rotation matrices. How do we know that m_unity is a pure rotation? It's certainly conceivable that it's not, because unity_to_ros and ros_to_unity both have determinant -1 (as a result of the handedness switch).
The hand-wavy answer is that the handedness is switching twice, so the result has no handedness switch. The deeper answer has to do with the fact that similarity transformations preserve certain aspects of the operator, but I don't have enough math to make the proof.
Note that this will give you a correct result, but you can probably do it more quickly if unity_to_ros is a simple matrix (say, with just an axis swap). But you should probably derive that faster method by expanding the math done here.
(*) Actually, there is the distinction between Hamilton and JPL quaternions; but everybody uses Hamilton so there's no need to muddy the waters with that.
I think that the solution is:
Given: Right Hand: {w,x,y,z}
Convert: Left Hand: {-w,z,y,x}
In unity:
new Quaternion(rhQz,rhQy,rhQx,-rhQw)
Ok, just to be clear, quaternions don't actually have handedness. They are handless(see wikipedia article on quaternions). HOWEVER, the conversion to a matrix from a quaternion does have handedness associated with it. See http://osdir.com/ml/games.devel.algorithms/2002-11/msg00318.html
If your code performs this conversion, you may have to have two separate functions to convert to a left handed matrix or a right handed matrix.
Hope that helps.
Once you do that, you no longer have a quaternion, i.e. the usual rules for multiplying
them won't work. The identity i^2 = j^2 = k^2 = ijk = -1 will no longer hold if you swap
j and k (y and z in your right handed system).
http://www.gamedev.net/community/forums/topic.asp?topic_id=459925
To paraphrase, negate the axis.
I know this question is old, but the method below is tested and works.
I used pyquaternion to manipulate the quaternions.
To go from right to left.
Find the axis and angle of the right hand quaternion.
Then convert the axis to left hand coordinates.
Negate the right hand angle to get the left hand angle.
Construct quaternion with left handed axis and left hand angle.
Related
Edit: My question may be too complex for what I am really asking, so skip to the TLDR; if you need it.
I have been programming 3D graphics for a while now and up until now I never seemed to have this issue, but maybe this is the first time I really understand things like I should (or not). So here's the question...
My 3D engine uses the typical OpenGL legacy convention of a RH coordinate system, which means X+ is right, Y+ is up and Z+ is towards the viewer, Z- goes into the screen. I did this so that I could test my 3D math against the one in OpenGL.
To coop with the coordinate convention of Blender 3D/Collada, I rotate every matrix during importing with -90 degrees over the X axis. (Collada uses X+ right, Y+ forward, Z+ up if I am not mistaken)
When I just use the projection matrix, an identity view matrix and a model matrix that transforms a triangle to position at (0, 0, -5), I will see it because Z- is into the screen.
In my (6DOF space) game, I have spaceships and asteroids. I use double-precision coordinates (because they are huge) and by putting the camera inside a spaceship, the coordinates are made relative every frame so they are precise enough to fit a single-precision coordinate for rendering on the GPU.
So, now I have a spaceship, the camera is inside, and it its rotation quaternion is identity. This gives an identity matrix and if I recall correctly, row columns 1-3 are representing the X, Y and Z axis of where the object is pointing at. To move the ship, I use this Z axis to go forward. With the identity matrix, the Z-axis will be (0, 0, 1).
Edit: actually, I don't take the columns from the matrix, I extract the axes directly from the quaternion.
Now, when I put the the camera in the spaceship, this means that its nose is pointing at (0, 0, 1) but OpenGL will render with -1 going into the screen because of its conventions.
I always heard that when you put the camera inside an object in your scene, you need to take the model matrix and invert it. It's logical: if the ship is at (0, 0, 1000) and an asteroid is at (0, 0, 1100), then is makes sense that you need to put the camera at (0, 0, -1000) so that the ship will be at (0, 0, 0) and the asteroid will be at (0, 0, 100).
So when I do this, the ship will be rendered with its nose looking at Z-, but now, when I start moving, my ship moves to its rotation (still identity) Z being (0, 0, 1) and the ship will back up instead of going forward. Which makes sense if (0, 0, 1) is towards the viewer...
So now I am confused... how should I handle this correctly??? Which convention did I use incorrectly? Which convention did I forget? It doesn't seem logical, for example, to invert the rotation of the ship when calculation the movement vectors...
Can someone clarify this for me? This has been bothering me for a week now and I don't seem to get it straight without doubting that I am making new errors.
Edit: isn't it at all very strange to invert the rotational part of the model's matrix for a view matrix? I understand that the translation part should be inverted, but the view should still look at the same direction as the object when it would be rendered, no?
TLDR;
If you take legacy OpenGL, set a standard projection matrix and an identity modelview matrix and render a triangle at (0, 0, -5), you will see it because OpenGL looks at Z-.
But if you take the Z-axis from the view matrix (3rd row column), which is (0, 0, 1) on an identity matrix, this means that going 'forward' means that you will be getting further away from that triangle, which looks illogical.
What am I missing?
Edit: As the answer is hidden in many comments below, I summarize it here: conventions! I chose to use the OpenGL legacy convention but I also chose to use my own physics convention and they collide, so I need to compensate for that.
Edit: After much consideration, I have decided to abandon the OpenGL legacy convention and use whatever looks most logical to me, which is the left-handed system.
I think the root cause of your confusion might lie here
So, now I have a spaceship, the camera is inside, and it its rotation quaternion is identity. This gives an identity matrix and if I recall correctly, row 1-3 are representing the X, Y and Z axis of where the object is pointing at. To move the ship, I use this Z axis to go forward. With the identity matrix, the Z-axis will be (0, 0, 1).
Since we can assume that a view matrix contains only rotations and translations (no scaling/shear or perspective tricks), we know that the upper left 3x3 sub-matrix will be a rotation only, and those are orthogonal by definition, so the inverse(mat3(view)) will be the transpose(mat3(view)), which is where your rows are coming from. Since in a standard matrix which you use to transform objects in a fixed coordinate frame (as opposed to moving the coordinate frame of reference), the columns of the matrix will simply show where the unit vectors for x, y and z (as well as the origin (0,0,0,1) will be mapped to by this matrix. By taking the rows, you use the transpose, which, in this particular setup, is the inverse (not considering the last column containing the translation, of course).
The view matrix will transform from wolrd space into eye space. As a result, inverse(view) will transform from eye space back to world space.
So, inverse(view) * (1,0,0,0) will give you the camera's right vector in world space, inverse(view) * (0,1,0,0) the up vector, but as per convention the camera will be looking at -z in eye space, so forward direction in wolrd space will be inverse(view) * (0,0,-1,0), which, in your setup, is just the third row of the matrix negated.
(Camera position will be inverse(view) * (0,0,0,1) of course, but we have to do a bit more than just transposing to get the fourth column of inverse(view) right).
Trying to understand vectors a bit more.
What is the need for normalizing a vector?
If I have a vector, N = (x, y, z)
What do you actually get when you normalize it - I get the idea you have to divide x/|N| y/|N| & z/|N|. My question is, why do we do this thing, I mean what do we get out of this equation?
What is the meaning or 'inside' purpose of doing this.
A bit of a maths question, I apologize, but I am really not clear in this topic.
For any vector V = (x, y, z), |V| = sqrt(x*x + y*y + z*z) gives the length of the vector.
When we normalize a vector, we actually calculate V/|V| = (x/|V|, y/|V|, z/|V|).
It is easy to see that a normalized vector has length 1. This is because:
| V/|V| | = sqrt((x/|V|)*(x/|V|) + (y/|V|)*(y/|V|) + (z/|V|)*(z/|V|))
= sqrt(x*x + y*y + z*z) / |V|
= |V| / |V|
= 1
Hence, we can call normalized vectors as unit vectors (i.e. vectors with unit length).
Any vector, when normalized, only changes its magnitude, not its direction. Also, every vector pointing in the same direction, gets normalized to the same vector (since magnitude and direction uniquely define a vector). Hence, unit vectors are extremely useful for providing directions.
Note however, that all the above discussion was for 3 dimensional Cartesian coordinates (x, y, z). But what do we really mean by Cartesian coordinates?
Turns out, to define a vector in 3D space, we need some reference directions. These reference directions are canonically called i, j, k (or i, j, k with little caps on them - referred to as "i cap", "j cap" and "k cap"). Any vector we think of as V = (x, y, z) can actually then be written as V = xi + yj + zk. (Note: I will no longer call them by caps, I'll just call them i, j, k). i, j, and k are unit vectors in the X, Y and Z directions and they form a set of mutually orthogonal unit vectors. They are the basis of all Cartesian coordinate geometry.
There are other forms of coordinates (such as Cylindrical and Spherical coordinates), and while their coordinates are not as direct to understand as (x, y, z), they too are composed of a set of 3 mutually orthogonal unit vectors which form the basis into which 3 coordinates are multiplied to produce a vector.
So, the above discussion clearly says that we need unit vectors to define other vectors, but why should you care?
Because sometimes, only the magnitude matters. That's when you use a "regular" number (something like 4 or 1/3 or 3.141592653 - nope, for all you OCD freaks, I am NOT going to put Pi there - that shall stay a terminating decimal, just because I am evil incarnate). You would not want to thrown in a pesky direction, would you? I mean, does it really make sense to say that I want 4 kilograms of watermelons facing West? Unless you are some crazy fanatic, of course.
Other times, only the direction matters. You just don't care for the magnitude, or the magnitude just is too large to fathom (something like infinity, only that no one really knows what infinity really is - All Hail The Great Infinite, for He has Infinite Infinities... Sorry, got a bit carried away there). In such cases, we use normalization of vectors. For example, it doesn't mean anything to say that we have a line facing 4 km North. It makes more sense to say we have a line facing North. So what do you do then? You get rid of the 4 km. You destroy the magnitude. All you have remaining is the North (and Winter is Coming). Do this often enough, and you will have to give a name and notation to what you are doing. You can't just call it "ignoring the magnitude". That is too crass. You're a mathematician, and so you call it "normalization", and you give it the notation of the "cap" (probably because you wanted to go to a party instead of being stuck with vectors).
BTW, since I mentioned Cartesian coordinates, here's the obligatory XKCD:
Reading Godot Game Engine documentation about unit vector, normalization, and dot product really makes a lot of sense. Here is the article:
Unit vectors
Ok, so we know what a vector is. It has a direction and a magnitude. We also know how to use them in Godot. The next step is learning about unit vectors. Any vector with magnitude of length 1 is considered a unit vector. In 2D, imagine drawing a circle of radius one. That circle contains all unit vectors in existence for 2 dimensions:
So, what is so special about unit vectors? Unit vectors are amazing. In other words, unit vectors have several, very useful properties.
Can’t wait to know more about the fantastic properties of unit vectors, but one step at a time. So, how is a unit vector created from a regular vector?
Normalization
Taking any vector and reducing its magnitude to 1.0 while keeping its direction is called normalization. Normalization is performed by dividing the x and y (and z in 3D) components of a vector by its magnitude:
var a = Vector2(2,4)
var m = sqrt(a.x*a.x + a.y*a.y)
a.x /= m
a.y /= m
As you might have guessed, if the vector has magnitude 0 (meaning, it’s not a vector but the origin also called null vector), a division by zero occurs and the universe goes through a second big bang, except in reverse polarity and then back. As a result, humanity is safe but Godot will print an error. Remember! Vector(0,0) can’t be normalized!.
Of course, Vector2 and Vector3 already provide a method to do this:
a = a.normalized()
Dot product
OK, the dot product is the most important part of vector math. Without the dot product, Quake would have never been made. This is the most important section of the tutorial, so make sure to grasp it properly. Most people trying to understand vector math give up here because, despite how simple it is, they can’t make head or tails from it. Why? Here’s why, it’s because...
The dot product takes two vectors and returns a scalar:
var s = a.x*b.x + a.y*b.y
Yes, pretty much that. Multiply x from vector a by x from vector b. Do the same with y and add it together. In 3D it’s pretty much the same:
var s = a.x*b.x + a.y*b.y + a.z*b.z
I know, it’s totally meaningless! You can even do it with a built-in function:
var s = a.dot(b)
The order of two vectors does not matter, a.dot(b) returns the same value as b.dot(a).
This is where despair begins and books and tutorials show you this formula:
A ⋅ B = ∥A∥ ∥B∥ cos(θ)
And you realize it’s time to give up making 3D games or complex 2D games. How can something so simple be so complex? Someone else will have to make the next Zelda or Call of Duty. Top down RPGs don’t look so bad after all. Yeah I hear someone did pretty will with one of those on Steam...
So this is your moment, this is your time to shine. DO NOT GIVE UP! At this point, this tutorial will take a sharp turn and focus on what makes the dot product useful. This is, why it is useful. We will focus one by one in the use cases for the dot product, with real-life applications. No more formulas that don’t make any sense. Formulas will make sense once you learn what they are useful for.
Siding
The first useful and most important property of the dot product is to check what side stuff is looking at. Let’s imagine we have any two vectors, a and b. Any direction or magnitude (neither origin). Does not matter what they are, but let’s imagine we compute the dot product between them.
var s = a.dot(b)
The operation will return a single floating point number (but since we are in vector world, we call them scalar, will keep using that term from now on). This number will tell us the following:
If the number is greater than zero, both are looking towards the same direction (the angle between them is < 90° degrees).
If the number is less than zero, both are looking towards opposite direction (the angle between them is > 90° degrees).
If the number is zero, vectors are shaped in L (the angle between them is 90° degrees).
So let’s think of a real use-case scenario. Imagine Snake is going through a forest, and then there is an enemy nearby. How can we quickly tell if the enemy has seen discovered Snake? In order to discover him, the enemy must be able to see Snake. Let’s say, then that:
Snake is in position A.
The enemy is in position B.
The enemy is facing towards direction vector F.
So, let’s create a new vector BA that goes from the guard (B) to Snake (A), by subtracting the two:
var BA = A - B
Ideally, if the guard was looking straight towards snake, to make eye to eye contact, it would do it in the same direction as vector BA.
If the dot product between F and BA is greater than 0, then Snake will be discovered. This happens because we will be able to tell that the guard is facing towards him:
if (BA.dot(F) > 0):
print("!")
Seems Snake is safe so far.
Siding with unit vectors
Ok, so now we know that dot product between two vectors will let us know if they are looking towards the same side, opposite sides or are just perpendicular to each other.
This works the same with all vectors, no matter the magnitude so unit vectors are not the exception. However, using the same property with unit vectors yields an even more interesting result, as an extra property is added:
If both vectors are facing towards the exact same direction (parallel to each other, angle between them is 0°), the resulting scalar is 1.
If both vectors are facing towards the exact opposite direction (parallel to each other, but angle between them is 180°), the resulting scalar is -1.
This means that dot product between unit vectors is always between the range of 1 and -1. So Again...
If their angle is 0° dot product is 1.
If their angle is 90°, then dot product is 0.
If their angle is 180°, then dot product is -1.
Uh.. this is oddly familiar... seen this before... where?
Let’s take two unit vectors. The first one is pointing up, the second too but we will rotate it all the way from up (0°) to down (180° degrees)...
While plotting the resulting scalar!
Aha! It all makes sense now, this is a Cosine function!
We can say that, then, as a rule...
The dot product between two unit vectors is the cosine of the angle between those two vectors. So, to obtain the angle between two vectors, we must do:
var angle_in_radians = acos( a.dot(b) )
What is this useful for? Well obtaining the angle directly is probably not as useful, but just being able to tell the angle is useful for reference. One example is in the Kinematic Character demo, when the character moves in a certain direction then we hit an object. How to tell if what we hit is the floor?
By comparing the normal of the collision point with a previously computed angle.
The beauty of this is that the same code works exactly the same and without modification in 3D. Vector math is, in a great deal, dimension-amount-independent, so adding or removing an axis only adds very little complexity.
That's a bit like asking why we multiply numbers. It comes up all the time.
The Cartesian coordinate system that we use is an orthonormal basis (consists of vectors of length 1 that are orthogonal to each other, basis means that any vector can be represented by a unique combination of these vectors), when you want to rotate your basis (which occurs in video game mechanics when you look around) you use matrices whose rows and columns are orthonormal vectors.
As soon as you start playing around with matrices in linear algebra enough you will want orthonormal vectors. There are too many examples to just name them.
At the end of the day we don't need normalized vectors (in the same way as we don't need hamburgers, we could live without them, but who is going to?), but the similar pattern of v / |v| comes up so often that people decided to give it a name and a special notation (a ^ over a vector means it's a normalized vector) as a shortcut.
Normalized vectors (also known as unit vectors) are, basically, a fact of life.
You are making its length 1 - finding the unit vector that points in the same direction.
This is useful for various purposes, for example, if you take the dot product of a vector with a unit vector you have the length of the component of that vector in the direction of the unit vector.
The normals are supposed to be used as a direction vector only. They are used for lighting computation, which requires normalized normal vectors.
This post is very old, but there still isn't a very clear answer as to why we normalize. The reason is to find the exact magnitude of the vector and it's projection over another vector.
Example: Projection of vector a over b is b·cos(θ)
However, in the case of dot products, the dot product of two vectors a and b is a·b·cos(θ). This means the dot product is the projection of a over b times a. So we divide it by a to normalize to find the exact length of the projection which is b·cos(θ).
Hope it's clear.
For a game i'm trying to calculate the angle between where i'm looking at and the position of another object in the scene. I got the angle by using the following code:
Vec3 out_sub;
Math.Subtract(pEnt->vOrigin, pLocalEnt->vOrigin, out_sub);
float angle = Math.DotProductAcos(out_sub, vec3LookAt);
This code does give me the angle between where im looking at and an object in the scene. But there's a small problem.
When i don't directly look at the object but slightly to the left of it, then it says i have to rotate 10 degrees in order to directly look at the object. Which is perfectly correct.
But, when i look slightly to the right of the object, it also says i have to rotate 10 degrees in order to look directly to the object.
The problem here is, the i have no way to tell which way to rotate to. I only know its 10 degrees. But do i have to rotate to the left or right? That's what i need to find out.
How can i figure that out?
I feel the need to elaborate on Ignacio's answer...
In general, your question is not well-founded, since "turn left" and "turn right" only have meaning after you decide which way is "up".
The cross product of two vectors is a vector that tells you which way is "up". That is, A x B is the "up" that you have to use if you want to turn left to get from A to B. (And the magnitude of the cross product tells you how far you have to turn, more or less...)
For 3D vectors, the cross product has a z component of x1 * y2 - y1 * x2. If the vectors themselves are 2D (i.e., have zero z components), then this is the only thing you have to compute to get the cross product; the x and y components of the cross product are zero. So in 2D, if this number is positive, then "up" is the positive z direction and you have to turn left. If this number is negative, then "up" is the negative z direction and you have to turn left while upside-down; i.e., turn right.
You also need to perform the cross product on the vectors. You can then get the direction of the rotate by the direction of the resultant vector.
I want to instance a slider constraint, that allows a body to slide between point A and point B.
To instance the constraint, I assign the two bodies to constrain, in this case, one dynamic body constrained to the static world, think sliding door.
The third and fourth parameters are transformations, reference Frame A and reference Frame B.
To create and manipulate Transformations, the library supports Quaternions, Matrices and Euler angles.
The default slider constraint slides the body along the x-axis.
My question is:
How do I set up the two transformations, so that Body B slides along an axis given by its own origin and an additional point in space?
Naively I tried:
frameA.setOrigin(origin_of_point); //since the world itself has origin (0,0,0)
frameA.setRotation(Quaternion(directionToB, 0 rotation));
frameB.setOrigin(0,0,0); //axis goes through origin of object
frameB.setRotation(Quaternion(directionToPoint,0))
However, Quaternions don't seem to work as I expected. My mathematical knowledge of them is not good, so if someone could fill me in on why this doesn't work, I'd be grateful.
What happens is that the body slides along an axis orthogonal to the direction. When I vary the rotational part in the Quaternion constructor, the body is rotated around that sliding direction.
Edit:
The framework is bullet physics.
The two transformations are how the slider joint is attached at each body in respect to each body's local coordinate system.
Edit2
I could also set the transformations' rotational parts through a orthogonal basis, but then I'd have to reliably construct a orthogonal basis from a single vector. I hoped quaternions would prevent this.
Edit3
I'm having some limited success with the following procedure:
btTransform trafoA, trafoB;
trafoA.setIdentity();
trafoB.setIdentity();
vec3 bodyorigin(entA->getTrafo().col_t);
vec3 thisorigin(trafo.col_t);
vec3 dir=bodyorigin-thisorigin;
dir.Normalize();
mat4x4 dg=dgGrammSchmidt(dir);
mat4x4 dg2=dgGrammSchmidt(-dir);
btMatrix3x3 m(
dg.col_x.x, dg.col_y.x, dg.col_z.x,
dg.col_x.y, dg.col_y.y, dg.col_z.y,
dg.col_x.z, dg.col_y.z, dg.col_z.z);
btMatrix3x3 m2(
dg2.col_x.x, dg2.col_y.x, dg2.col_z.x,
dg2.col_x.y, dg2.col_y.y, dg2.col_z.y,
dg2.col_x.z, dg2.col_y.z, dg2.col_z.z);
trafoA.setBasis(m);
trafoB.setBasis(m2);
trafoA.setOrigin(btVector3(trafo.col_t.x,trafo.col_t.y,trafo.col_t.z));
btSliderConstraint* sc=new btSliderConstraint(*game.worldBody, *entA->getBody(), trafoA, trafoB, true);
However, the GramSchmidt always flips some axes of the trafoB matrix and the door appears upside down or right to left.
I was hoping for a more elegant way to solve this.
Edit4
I found a solution, but I'm not sure whether this will cause a singularity in the constraint solver if the top vector aligns with the sliding direction:
btTransform rbat = rba->getCenterOfMassTransform();
btVector3 up(rbat.getBasis()[0][0], rbat.getBasis()[1][0], rbat.getBasis()[2][0]);
btVector3 direction = (rbb->getWorldTransform().getOrigin() - btVector3(trafo.col_t.x, trafo.col_t.y, trafo.col_t.z)).normalize();
btScalar angle = acos(up.dot(direction));
btVector3 axis = up.cross(direction);
trafoA.setRotation(btQuaternion(axis, angle));
trafoB.setRotation(btQuaternion(axis, angle));
trafoA.setOrigin(btVector3(trafo.col_t.x,trafo.col_t.y,trafo.col_t.z));
Is it possible you're making this way too complicated? It sounds like a simple parametric translation (x = p*A+(1-p)*B) would do it. The whole rotation / orientation thing is a red herring if your sliding-door analogy is accurate.
If, on the other hand, you're trying to constrain to an interpolation between two orientations, you'll need to set additional limits 'cause there is no unique solution in the general case.
-- MarkusQ
It would help if you could say what framework or API you're using, or copy and paste the documentation for the function you're calling. Without that kind of detail I can only guess:
Background: a quaternion represents a 3-dimensional rotation combined with a scale. (Usually you don't want the complications involved in managing the scale, so you work with unit quaternions representing rotations only.) Matrices and Euler angles are two alternative ways of representing rotations.
A frame of reference is a position plus a rotation. Think of an object placed at a position in space and then rotated to face in a particular direction.
So frame A probably needs to be the initial position and rotation of the object (when the slider is at one end), and frame B the final position and rotation of the object (when the slider is at the other end). In particular, the two rotations probably ought to be the same, since you want the object to slide rigidly.
But as I say, this is just a guess.
Update: is this Bullet Physics? It doesn't seem to have much in the way of documentation, does it?
Perhaps you are looking for slerp?
Slerp is shorthand for spherical
linear interpolation, introduced by
Ken Shoemake in the context of
quaternion interpolation for the
purpose of animating 3D rotation. It
refers to constant speed motion along
a unit radius great circle arc, given
the ends and an interpolation
parameter between 0 and 1.
At the end of the day, you still need the traditional rotational matrix to get things rotated.
Edit: So, I am still guessing, but I assume that the framework takes care of the slerping and you want the two transformations which describes begin state and the end state?
You can stack affine transformations on top of the other. Except you have to think backwards. For example, let's say the sliding door is placed at (1, 1, 1) facing east at the begin state and you want to slide it towards north by (0, 1, 0). The door would end up at (1, 1, 1) + (0, 1, 0).
For begin state, rotate the door towards east. Then on top of that you apply another translation matrix to move the door to (1, 1, 1). For end state, again, you rotate the door towards east, then you move the door to (1, 1, 1) by applying the translation matrix again. Next, you apply the translation matrix (0, 1, 0).
Okay, so I need to make C go the shortest path from A to B. A to B is the hypotenuse of my right triangle, and I need to give C the arctan of said triangle. How do I do this, and does the formula have a name?
It's not clear exactly what you're asking, but I think you're trying to find the angle of the A-B line. I'm going to make the assumption that you know, or can figure out the (x,y) coordinates of both A and B, because otherwise you won't be able to solve the issue.
It sounds like you've outlined the majority of the solution...the angle will be equal to the arctan of the (y/x) distance. So if we consider A(y) to be the y coordinate of A, then you're looking at something like:
arctan ((A(y) - B(y)) / (A(x) - B(x)))
Does that help? Or are you looking for something slightly different?
EDIT: One thing to be aware of is the order in which you consider the terms (whether you're going from A to B or vice versa), etc. You will have to be thoughtful about this or you could end up with some sign problems.
Most systems have Arctan2(dy, dx) which gives you an angle in a full circle (and takes care of verticals), so you would say Arctan2((By - Ay), (Bx - Ax)) to get the direction in radians (counterclockwise from East). For degrees multiply by 360/(2*PI).
Just make sure A != B.
Arctan would result in degrees or radians so your A and B most likely have coordinates like (x, y). Then you do arctan((By - Ay) / (Bx - Ax)) if I remember correctly, here Bx is the x coordinate of B etc.
If A and B do not have coordinates, you cannot get degrees out meaningfully.
If you only have one length and there is no hidden assumption here (like say, one side of the triangle has been normalized): you can't.
An interesting hidden assumption might be:
All distances are integers
The triangle is at least as long as it is tall.
Then the problem is merely hard.
If A and B are points, then the angle you want is presumable the one taken to the x-axis, and you get it by (using the fortranish names):
atan((B.y - A.y)/(B.x - A.x))
or if you have it in your library
atan2((B.y - A.y),(B.x - A.x))
which handles the divide by zero cases neatly...
If A to B is the hypotenuse of your right triangle, A to B will also be the shortest path from A to B because it is a straight line between the points.
You can calculate the arctangent of either non-right angle by dividing the length of the adjacent side by the length of the opposite side because it's the inverse of the tangent. But, with the information you've described, you will be lacking either the numerator or the denominator.
There are an infinite number of right triangles with a hypotenuse of a given length.