Nuke - Matrix4 camera constraint lock Z rotation - c++

So im building a plugin in Nuke (from The Foundry) that will mimic Maya's animation constraint behaviours. I have a parent, a child, and then options for point, orientation, aim, parent constraints. This is all working pretty well, however my biggest issue at the moment is the Aim constraint.
Some background:
Working with the Nuke Matrix4 class
Its worth noting this matrix is a 4x4 in which the first 3 columns of the first 3 rows apply to rotations/scale, and the last column of the first 3 rows is translation (X,Y,Z)
in Vector3 classes
I am getting the source and target position. Target-source = ST
Then im setting up a Y plane (one inverted, one not)
Then i get the corss product of my ST point and the Y plane, and then another cross product of my ST and inverted Y plane. (for when the parent is behind the child to invert it)
I then get the cross product of my ST and the result of my ST.cross(y_plane)
The aim constraint actually works quite well, but i get a lot of Z rotation in my camera (child) when the parent is in certain postions. I want to be able to avoid this Z rotation. Would anyone happen to know how to do so?

If you're emulating Maya's constraint system, Maya handles Z rotation through the up vector, which adjusts your Z rotation to align with one of five options:
scene up aims the top of your camera to +Y
object up aims the top of your camera toward a third object
object rotation up matches the camera's Z rotation to the XYZ rotation of a third object
vector aims the top of your camera at that vector
none Doesn't attempt to orient the top of your camera with anything. This must be what you have currently.
Additionally, there's an up vector which defines what is the "top of your camera" just like the aim vector defines where the camera should point.

Related

What is the standard place to keep the Model Matrix?

I have a "3D engine" which has a single model matrix.
All of my 3D objects uses this model matrix (for transformations stuff).
For each object i set the model identity before using it.
So far so great as it appears to be working just fine, and as expected.
But now i am suddenly wondering if i have a design flaw.
Should each 3D object (the base object) have their own model matrix?
Is there any value in doing it this way (model matrix per 3D object)?
That is literally what the point of the model matrix is. It is an optional transformation for each object you draw from object-space (its local coordinate system) to world-space (a shared coordinate system). You can define your objects such that their positions are already in world-space and then no model matrix is necessary (as you are doing if you use an identity model matrix).
GL uses (or at least historically, it did) a matrix stack for this and it is technically the very reason it uses column-major matrices and post-multiplication. That allows you to push/pop your local coordinate transformations to the top of the stack immediately before/after you draw an object while leaving the other transformations that rarely change such as world->eye (view matrix) or eye->clip (projection matrix) untouched.
Elaborating in a separate answer because a comment is too short, but Andon's answer is the right one.
Think for instance of loading two 3d meshes done from two different artists. ¹
The first artist assumed that 1 unit in your model space is 1 meter, while the other artist assumed 1 inch.
So, you load a car mesh done by the first artist, which maybe is 3 units long; and a banana mesh, which then is 8 units long.
Also, the first artist decided to put the origin of the points for the car mesh in its center, while the artist who did the banana mesh put the banana lying on the X axis, with the base of the fruit on the X=2000 point.
So how do you show both of this meshes in your 3d world? Are you going to have a banana whose length is almost thrice the length of your car? That makes absolutely no sense.
How are you going to place them next to each other? Or how are you going to place them lying on a plane? The fact that the local coordinate systems are totally random makes it impossible to translate your objects in a coherent way.
This is where the model->world matrix comes in.
It allows you to specify a per-model transformation that brings all models into a "shared", unique, coherent space -- the world space.
For instance, you could translate both models so that their origin would lie "in a corner" and all the mesh's vertices in the first octant. Also, if your world space uses "meters", you would need to scale the banana mesh by 0.0254 to bring its size in meters as well. Also, maybe you'd like to rotate the banana and having it lying on the Y axis instead of the X.
At the end of the game, for each "unique model" in your world, you'd have its associated model matrix, and use it when drawing it.
Also: for each instance of a model, you could think of applying an extra local trasformation (in world coordinates). For instance, you'd like to translate the car model to a certain point in the world. So instead of having
(Model space) --> Model matrix ---> (World space) ---> World matrix ---> (Final world space)
you could multiply the two matrices together and having only one matrix that brings points from model space straight to final world space.
¹ This point is a bit moot in that in any proper asset pipeline the first thing you'd do would be bringing all the models in a coherent coordinate system, just doing an example...

Getting all vertices of a rectangle

In my program, I had a requirement to plot a rectangle that that is prependicular to a line coming from the centre.
To orient the rectangle in this way in 3D space, I used the gluLookAt giving it the lookAt point and plotted the rectangular figure. This worked correctly for me.
To draw the rectangle (in my framework, that uses openGL at the back), I now use a rectangle class and have extended it with a 3D Node (where node is something that has a lookAt point). Given width, height and the top vertex, the rectangle is drawn (node is at the top left vertex and orients the rectangle using lookAt).
Node also has a getPosition() function that gives me its 3D position (top left in rectangle - say 300,400,20). I am trying to get the position of the other three vertices in 3D space to use for my operation. Since the rectangle is oriented in 3D space, other three vertices can't just be fetched by addition of width and height. With the rectangle oriented in 3D, how do I get the position of the other three vertices?
The minimum amount of coordinates is just slightly less than 9: that's three vertices of a generic rectangle in 3d-space (Ax,Ay,Az, Bx,By,Bz, Cx,Cy,Cz).
The last one is e.g. D=A+(B-A)+(C-A)=B+C-A.
Why it's slightly less, is that any triplet of A,B,C coordinates do not necessarily form a 90 degree angle -- but it really doesn't make much sense to pursuit for the simplistic possible arrangement and be prepared to calculate cross-products or normalize vectors.
A----B
| |
C---(D)
EDIT: Vector arithmetic primary:
To Add / Subtract vectors, one sums the elements.
A=B+C means (ax = bx+cx; ay=by+cy; az=bz+cz).
Dot product in (any dimension) is the sum of product of terms:
dot(A,B) = ax*bx + ay*by + az*bz; // for 2,3,4, any number of elements/dimensions.
Cross product is a special operator that is well defined at least in 2 and 3 dimensions. One of the geometric interpretations of cross product is that it produces a vector that is perpendicular to both vectors of it's parameters.
If A is a vector (ax,ay,az), it also means a direction vector from origin O=(0,0,0) i.e. A = A-O = (ax-0,ay-0,az-0);
Likewise (B-A) is a [direction] vector from A to B (sometimes written as AB (with an arrow --> on top))
One can 'add' these directed vectors e.g. as:
o----->
\
\
<------o
/
/
x
And so, if one adds the vector A+(B-A) + (C-A), one ends to the point D.
You can retreive the position of the 3 other points using the normal of the rectangle. In order to orient a rectangle in space, you need 2 information:
its position, commonly represented as a 3 or 4 components vector, or a 4x4 matrix ;
its orientation, commonly represented as a quaternion.
If you have the orientation represented with a normal, and only have one point, you just can’t deduce the other points (because you need another information to solve the rotation equation around the normal). I think the best idea is to use quaternion to orient things in space (you can still retreive the normal from it), but you can also use a normal + one vector from the rectangle. You said you only have one point, and a tuple (width,height), so the common method based on the × operation won’t make it through.
I suggest you to:
make your Node class a class that correctly handles orientation; lookAt isn’t designed for that job ;
combine the translation matrix (position) with a cast matrix from the quaternion (orientation) to correctly handle both position and orientation ;
use that matrix to extract a rotated vector you’ll used like rotated × normal to get the 3 points.

Convert GL modelview matrix to world coordinates

I'm using Qualcomm's AR SDK to track an object.
I have the following functions available:
https://ar.qualcomm.at/qdevnet/api (specifically look at "Namespace List->QCAR::Tool").
I can get the tracked item's modelview matrix by using the convertPose2GLMatrix (const Matrix34F &pose) function, as I get a pose matrix for each tracked item.
My goal - to determine the marker's location in "the real world". You can assume my camera will be stationary.
I have read numerous articles online, and my general understanding is this:
I need to pick a modelview matrix from where I choose the axis' 0,0,0 point to be (i.e. - copy the matrix I get for that point).
I then need to transpose that matrix. Then, each model view matrix I extract should be multiplied by that matrix and then by an (x,y,z,1) vector, to obtain the coordinates (ignoring the 4th item).
Am I correct? Is this the way to go? And if not - what is?
I like to think of ortho matrices as moving from one coordinate space to another, so what you suggest is correct, yet I would do it the other way around:
1.) Use a reference coordinate system S relative to your camera (i.e. just one of your matrices determined by the pose estimation)
2.) For each pose estimation T calculate the following:
W = S * T^-1 = S * transpose(T)
3.) From matrix W pick the 4 column, as your world position.

How to use and set axes in a 3D scene

I'm creating a simulator coded in python and based on ODE (Open Dynamics Engine). For visualization I chose VTK.
For every object in the simulation, I create a corresponding source (e.g. vtkCubeSource), mapper and actor. I am able to show objects correctly and update them as the simulation runs.
I want to add axes to have a point of reference and to show the direction of each axis. Doing that I realized that, by default, X and Z are in the plane of the screen and Y points outwards. In my program I have a different convention.
I've been able to display axes in 2 ways:
1) Image
axes = vtk.vtkAxes()
axesMapper = vtk.vtkPolyDataMapper()
axesMapper.SetInputConnection(axes.GetOutputPort())
axesActor = vtk.vtkActor()
axesActor.SetMapper(axesMapper)
axesActor.GetProperty().SetLineWidth(4)
2) Image (colors do not match with the first case)
axesActor = vtk.vtkAxesActor()
axesActor.AxisLabelsOn()
axesActor.SetShaftTypeToCylinder()
axesActor.SetCylinderRadius(0.05)
In the second one, the user is allowed to set many parameters related to how the axis are displayed. In the first one, I only managed to set the line width but nothing else.
So, my questions are:
Which is the correct way to define and display axes in a 3D scene? I just want them in a fixed position and orientation.
How can I set a different convention for the axes orientation, both for their display and the general visualization?
Well, if you do not mess with objects' transformation matrix for display
purposes, it could probably be sufficient to just put your camera into a
different position while using axes approach 2. The easy methods to adjust
your camera position are: Pitch(), Azimuth() and Roll().
If you mess with object transforms, then apply the same transform to the
axes.
Dženan Zukić kindly answered this question in vtkusers#vtk.org mail list.
http://www.vtk.org/pipermail/vtkusers/2011-November/119990.html

Coordinate Transformation C++

I have a webcam pointed at a table at a slant and with it I track markers.
I have a transformationMatrix in OpenSceneGraph and its translation part contains the relative coordinates from the tracked Object to the Camera.
Because the Camera is pointed at a slant, when I move the marker across the table the Y and Z axis is updated, although all I want to be updated is the Z axis, because the height of the marker doesnt change only its distance to the camera.
This has the effect when when project a model on the marker in OpenSceneGraph, the model is slightly off and when I move the marker arround the Y and Z values are updated incorrectly.
So my guess is I need a Transformation Matrix with which I multiply each point so that I have a new coordinate System which lies orthogonal on the table surface.
Something like this: A * v1 = v2 v1 being the camera Coordinates and v2 being my "table Coordinates"
So what I did now was chose 4 points to "calibrate" my system. So I placed the marker at the top left corner of the Screen and defined v1 as the current camera coordinates and v2 as (0,0,0) and I did that for 4 different points.
And then taking the linear equations I get from having an unknown Matrix and two known vectors I solved the matrix.
I thought the values I would get for the matrix would be the values I needed to multiply the camera Coordinates with so the model would updated correctly on the marker.
But when I multiply the known Camera Coordinates I gathered before with the matrix I didnt get anything close to what my "table coordinates" were suposed to be.
Is my aproach completely wrong, did I just mess something up in the equations? (solved with the help of wolframalpha.com) Is there an easier or better way of doing this?
Any help would be greatly appreciated, as I am kind of lost and under some time pressure :-/
Thanks,
David
when I move the marker across the table the Y and Z axis is updated, although all I want to be updated is the Z axis, because the height of the marker doesnt change only its distance to the camera.
Only true when your camera's view direction is aligned with your Y axis (or Z axis). If the camera is not aligned with Y, it means the transform will apply a rotation around the X axis, hence modifying both the Y and Z coordinates of the marker.
So my guess is I need a Transformation Matrix with which I multiply each point so that I have a new coordinate System which lies orthogonal on the table surface.
Yes it is. After that, you will have 2 transforms:
T_table to express marker's coordinates in the table referential,
T_camera to express table coordinates in the camera referential.
Finding T_camera from a single 2d image is hard because there's no depth information.
This is known as the Pose problem -- it has been studied by -among others- Daniel DeMenthon. He developed a fast and robust algorithm to find the pose of an object:
articles available on its research homepage, section 4 "Model Based Object Pose" (and particularly "Model-Based Object Pose in 25 Lines of Code", 1995);
code at the same place, section "POSIT (C and Matlab)".
Note that the OpenCv library offers an implementation of the DeMenthon's algorithm. This library also offers a convenient and easy-to-use interface to grab images from a webcam. It's worth a try: OpenCv homepage
If you know the location in the physical world of your four markers and you've recorded the positions as they appear on the camera, you ought to be able to derive some sort of transform.
When you do the calibration, surely you'd want to put the marker at the four corners of the table not the screen? If you're just doing the corners of the screen, I imagine you're probably not taking into acconut the slant of the table.
Is the table literally just slanted relative to the camera or is it also rotated at all?