Camera Projection Matrix

Camera Projection Matrix

Anonymous
Not applicable
4,432 Views
16 Replies
Message 1 of 17

Camera Projection Matrix

Anonymous
Not applicable

I am attempting to obtain the camera projection matrix from a free camera that I matched to the prospective view. However, the only script I found was viewport.getTM() which gave me a matrix for the active viewport's matrix, I believe, not a camera projection matrix. Is there a way to find a camera projection matrix within 3DS Max? Also, does anyone know what viewport.getTM() is actually giving me?

0 Likes
4,433 Views
16 Replies
Replies (16)
Message 2 of 17

10DSpace
Advisor
Advisor

@Anonymous 

 

Sounds like you already may have read the Max docs which state that viewport.getTM() operates on perspective viewports and then goes on to say that the matrix 3 value that is returned from this function is the "affine" camera or viewport matrix.  I had to look up "affine" myself for which I found,  the following,

 

"Affine transformation is a linear mapping method that preserves points, straight lines, and planes. Sets of parallel lines remain parallel after an affine transformation. The affine transformation technique is typically used to correct for geometric distortions or deformations that occur with non-ideal camera angles"

 

After which I said to myself, Huh?  But affine aside, the returned a matrix 3 value in max terms is best explained here: 

 

 http://docs.autodesk.com/3DSMAX/15/ENU/MAXScript-Help/index.html?url=files/GUID-D77C780A-4E8A-4528-949F-CC09AAE048DA.htm,topicNumber=d30e162398

 

But what are you trying to do with this information?  I ask, because I wrote a script recently to automatically construct a pyramid aligned with the camera focal point and the FOV at the camera's target distance.  It was written for target cameras but I could easily adapt it to a free camera if it would be useful to you.    

 

 

Message 3 of 17

leeminardi
Mentor
Mentor

A camera's 3 columns by 4 rows transform matrix only contains the location and orientation of the camera.  You can get it with:

 

$camera001.transform

 

The first row of the matrix is a unit vector of the camera's x axis in world coordinates.  The second row the y unit vector and the third row is the z unit vector.  The fourth row in the position of the camera.  Since the matrix has only 3 columns the result is an axonometric  projection.  A forth column would be necessary in the matrix to support perspective.  How to access other camera properties that provide perspective and data can be found here.

lee.minardi
Message 4 of 17

10DSpace
Advisor
Advisor

@leeminardi 

 

Thanks, Lee for that clarification.  It seems from your comments and the documentation that viewport.getTM() and $camera001.transform both return matrix 3 values that give the x, y and Z unit vectors and camera position and should be the same thing (for cameras), unless I misunderstand.  But when I type each command in separately for a selected camera view, I get a completely different set of values in the 4 rows of each matrix.  Do you have any insight into why?   Is this to do with Local vs World Coordinate space?

0 Likes
Message 5 of 17

leeminardi
Mentor
Mentor

@10DSpace 

Let's say we have a scene with camera001.  The following will give us the transform for the camera.

$Camera001.transform
(matrix3 [0.803647,0.594875,0.0166065] [-0.283417,0.358047,0.88965] [0.523285,-0.719671,0.45634] [-30.7219,-47.907,50.5595])

Note that the camera position is [-30.7219,-47.907,50.5595] and that the camera is pointing in a direction opposite to the z unit vector of the matrix or  -1* [0.523285,-0.719671,0.45634]

 

If we now  make the viewport view from camera001 we get the following (assigning it to the variable vm view matrix).

 

vm = viewport.getTM()
(matrix3 [0.803647,-0.283417,0.523285] [0.594875,0.358047,-0.719671] [0.0166065,0.88965,0.45634] [52.3486,-36.5344,-41.4734])

Taking the inverse of vm we get the camera transform.

vmI = inverse(vm)
(matrix3 [0.803647,0.594875,0.0166065] [-0.283417,0.358047,0.88965] [0.523285,-0.719671,0.45634] [-30.7219,-47.907,50.5595])

 

lee.minardi
Message 6 of 17

10DSpace
Advisor
Advisor

@leeminardi 

 

Thanks for the explanation.  I see that the inverse function actually moves the values around from different rows (it's not just about the z unit vector facing the wrong way -- all the rows are affected including camera position).  There is much I do not understand about matrix math.  

 

But in practical terms, and to return to the OP's questions, with the availability of the camera transform matrix, as you pointed out via $Camera001.transform (without having to invert it) and all of the other camera properties available via maxscript (FOV, target position, etc.)  is there even any special reason to use viewport.getTM()  for a  camera?   I can see the case for a viewport to produce an "eye view location" in the absence of camera, but it's not clear to me what the use case is for a camera.  Thanks again for your explanation.   

0 Likes
Message 7 of 17

Anonymous
Not applicable

@leeminardi

@10DSpace 

 

Thank you for your responses. That gives more clarity into what I am trying to accomplish. Do you know if the $Camera001.transform function gives an equivalent 4x3 matrix as the camera projection matrix described here? https://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/EPSRC_SSAZ/node3.html

 

I am attempting to pull these properties from an unknown real-world camera position so that I can calibrate my pixel space from video. This is for graduate biomedical research into head injuries, so any help is super appreciated!

0 Likes
Message 8 of 17

10DSpace
Advisor
Advisor

@Anonymous 

 

You may find a recent thread on this forum useful to what you are working on:

 

https://forums.autodesk.com/t5/3ds-max-shading-lighting-and/dimensions-for-field-of-view/td-p/9769282

 

 

Briefly, some research engineers wanted a way to  determine the dimensions (and aspect ratio which you are asking about)  of the field-of-view at the camera target distance for use with the spatial resolution of their optical (and often laser-based) diagnostics measurement set-up (e.g. mm/pix) for various camera positions.    There is a maxscript that does what they wanted at the end of the thread that I wrote, that may be helpful to you.

Message 9 of 17

leeminardi
Mentor
Mentor

@10space

Since you asked about matrices here are a couple of points to keep in mind. 

If we know that matrix A = the product of B times C we can write this as:

[A] = [B]*[C]

Let’s say we know [A] and [B] but not [C].  How can we find [C]?

We CANNOT write [C] = [A] / [B]

but can write [C] = inverse([B]) * [A]

Where [B] * inverse([B]) = [I]  the indentity matrix (a square matrix with 1’s for the diagonal and 0’s elsewhere).  Some square matrices cannot be inverted. I won’t get into the details here as to why.

 

In 3ds Max we are working with 4 x 3 matrix (4 rows and 3 columns) which is not a square matrix.  To invert the viewport matrix “vm” of my post #5, an additional column must be added to make it square. The contents of the column are 0 0 0 1 and the full matrix for the viewport becomes:

[0.803647,-0.283417,0.523285,0] [0.594875,0.358047,-0.719671,0] [0.0166065,0.88965,0.45634,0] [52.3486,-36.5344,-41.4734,1]

 

I use Excel to sometimes invert a matrix.  Here’s the result for this example.

image.png

 

The Maxscript invert function automatically adds the fourth column to enable the matrix inversion.

 

Bottom line, I think you can use the $Camera001.transform function or the inverse of the viewport transform matrix for the camera projection reference you cite.

 

A little off topic but an example of using matrices you might find interesting is a tutorial I put together earlier this year on rigging a hexapod .

 

 

lee.minardi
Message 10 of 17

10DSpace
Advisor
Advisor

@leeminardi 

 

Thanks very much for you patient explanation of the inverse function.  The Excel spreadsheet really helps to see that Inverting the Viewport matrix (after the addition of the 4th column),  results in the first 3 Columns of the viewport matrix becoming the first 3 Rows of the Camera matrix, which I interpret to be a re-orientation of the perpendicular x, y & z unit vectors/axes.   But, I am still puzzled by why position in the 2 matrices is different because I had assumed that the viewport "Eye Level" position was supposed to be the same as the camera (nodal point?) position.    But obviously that assumption must be wrong.

 

Thanks also for the video too because that demonstrates a good use case for using matrices and unit vectors in solving animation problems.    (I had previously believed that unit vectors and matrices were just punishment for bad behavior of some sort).   They still make my head hurt a little, but after the pain subsided, I can see their utility now thanks to your video.  That's a pretty impressive set up for the hexapod.   

Message 11 of 17

leeminardi
Mentor
Mentor

@10DSpace 

 

The attached Max file is what I used to evaluate the camera and viewport transforms.   As noted earlier you can invert the viewport matrix to get the camera matrix.  I was wondering what might be the spatial relationship between the 2 matrices in addition to the mathematical relationship.

 

In addition to camera001, the file contains a point at the position vector noted in the viewport transform [52.3486,-36.5344,-41.4734].  I added red, green, and blue lines that are in the direction of the x, y, z, unit vectors of the viewport transform.  I could not see any spatial correlation between the camera and the viewport transform.  Perhaps you can see one!

image.png 

 

After using matrices a bit in Max you will really appreciate their power.  The main disadvantage of using matrices for rigging is the potential for gimbal lock.  That's when you need to turn to quaternions (quats).   Quat math causes my brain some pain but are the foundation for TCB rotational controllers.  

lee.minardi
Message 12 of 17

10DSpace
Advisor
Advisor

@leeminardi 

 

I see the error of my logic now.  I was (unreasonably) expecting the getViewTM() function to return for a Perspective Viewport the "eye" position without inversion.  But in playing further with the example in the Max docs (see code below) even for a Perspective Viewport, you must use the inverse of the getViewTM() function to derive a meaningful position.   So, I first selected the camera view, hit "P" to change it to Perspective view and then ran the code below and a sphere was constructed and aligned to the camera nodal point proving that the "eye" position for a  Perspective Viewport does in fact correspond to the camera position for the same view.   You just have to remember to always get the inverse of the getViewTM() function for a meaningful/useful position. 

 

--/////////////////From Max Docs--\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

--The following function returns as a Ray value the "eye" location and direction for the active viewport.
--The viewport needs to be a non-orthographic viewport.

 

fn getViewDirectionRay =
(
-- The affine TM transforms from world coords to view coords
-- so we need the inverse of this matrix
local coordSysTM = Inverse(getViewTM())
-- The Z axis of this matrix is the view direction.
local viewDir = -coordSysTM.row3
-- get the view position from this matrix
local viewPt = coordSysTM.row4
return ray viewPt viewDir
)

r = getViewDirectionRay()

--Added section----------------
--Now make a sphere and align it with the "eye" location
s = sphere()
s.radius = 1
s.pos = r.pos

 

Thanks again, Lee for your wealth of information on the topic.  It really helped get my head around this stuff a little better. 

Message 13 of 17

domo.spaji
Advisor
Advisor

Really useless things, can't imagine someone doing any of mxs examples on this topic.

 

Here's how you can get an idea about it:

Switch from some ortho to persp. view. Create targeted camera Ctrl+C (from view).

Back to persp. view.

Evaluate inverse$transform with camera selected

Take a look to cam. target distance

Take a look to cam Y (-) value

Open transform tipe-in, look at Dolly value

Hopefully cam target is on 0 Y value, you'll have same numbers

If not cam. distance is difference from cam Y (to 0) and target Y (to 0)

 

If you move target alone it will not be at image plane center any more

 

You can do the same with directional light, more fun...

Change FOV with cone falloff field

 

But you don't have to create camera at all, renderer can't work without it and still we can render any view

 

 

 

0 Likes
Message 14 of 17

leeminardi
Mentor
Mentor

@domo.spaji 

"Really useless things, can't imagine someone doing any of mxs examples on this topic."

 

Both @10DSpace  and I learned something in this exercise.  Not so useless.  

 

lee.minardi
Message 15 of 17

10DSpace
Advisor
Advisor

@domo.spaji 

 

Really useless things, can't imagine someone doing any of mxs examples on this topic.

 

Useless to you perhaps, but not to others on this thread. You should learn some respect for the interests of others.  This is not the first time I have seen you intrude on a thread with negative, inflammatory and disparaging statements.  It's really a shame, because you could make your points (none of which were particularly useful, relevant or helpful to me in this case)  without any of that.   I am not sure why you feel the need to constantly disparage others on the forums here but it is not really in the spirit of collaborative problem solving that I think is what best serves the forum.    

Message 16 of 17

domo.spaji
Advisor
Advisor

@10DSpaceand @leeminardi 

So thats all you get from my message?

Yeah, you are teachers, no more learning for you.

Don't sell me helping and serving stories... Offering answers and scripts on something you never heard before.

 

One mayor thing about scripting - Things are first enabled in Max with all tolls and solutions, than in Maxscript, and if in Maxscript. It's not other way around.

0 Likes
Message 17 of 17

leeminardi
Mentor
Mentor

@domo.spaji 

 

Let's keep this on learning please.  We all have something useful to share and learn.

 

Would you expand on what you meant by "Things are first enabled in Max with all tolls and solutions, than in Maxscript, and if in Maxscript. It's not other way around."   What is your "tolls" reference?

lee.minardi
0 Likes