Perspective projection

Hi,

I'm working on a 3D engine, but I'm stuck on perspective projection. The documentation is a bit confusing. I've got some wireframe objects moving around so far, but I need to add the perspective distortion, as well as move the points so they're relative to the screen's centre, rather than its top/left.

I know how to do this with calculations:

X' = (X*D) / (Z + D)

Y' = (Y*D) / (Z + D)

Then X' = X' + (vWidth/2). and Y' = Y' + (vHeight/2)

Where D is the eye's distance from the front view of the frustum.

I could use the above maths, but I'm assuming that it's quicker to use something in my transformation matrix.

DirectX has a function called Matrix.PerspectiveLH(vWidth, vHeight, D, F), but this messes things up. I think one tutorial said you have to divide the X,Y and Z by the W after you've done the point transformation, but this doesn't work.

Can anyone help me understand this

Thanks - Gary



Answer this question

Perspective projection

  • Albino

    Projection is indeed hard to understand at first,< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

     

    First you have 2 kind of Projections :

     

    Perspective Projection

    and

    Orthogonal Projection

     

    In 2D you define a Projection to be Orthogonal

    In 3D you define a Projection to be Perspective

     

    Most of the time the Z negative is toward you

    The more z the more in the back you are

    that's why we call it a Z buffer...

     

    The X positive are going right

    The Y Positive are getting up

     

    This is by convention but it may be totally different...

    LH means Left hand orientation

    RH is right hand orientation

     

    This is based on a trick that use your real hand as a tool...

    if you extend your right hand palm side down pointing finger in front of you

    The direction of your extended finger are the X positive

    If you bend your finger down towayd the Y positive axis

    you see that your tumb point to the left, so it's the Z positive (right hand axis)

     

    If you do the opposite and use your left hand you'll see that

    by using your left hand the Z positif point to the right (the direction of your tumb)

    (normally the Left hand rule is what we use)

     

    Now if you talk about centering the view on the center and not top left

    it's maybe because you think in 2D

     

    In 2D you set the Ortho Perspective Matrix and then use DXTransform to

    set the Projection matrix

     

    This is done by setting -Xmin and +Xmax and then +yMax and -yMin

    (a rectangular section on 2d axis X and Y)

     

    It's like the definition of a cartesian plane with 2 axis X and Y

    You tell the view what rectangulare section of the cartesian plan you want to see

     

    You can have a screen of 0 to 10 in X and 0 to 10 in Y (positive X right, positive Y up)

    (the basic bottom/left are 0,0 view)

    You can set -10 to 10 in X and -10 in 10 in Y

    (the 0,0 will be in the center of the screen)

     

    As for the Z axis positive in the back (left hand rule...)

    (with the left hand ''palm up'' and flat on a table point your finger extended to the right,

    this point the X positive

    when you bend your finger up you get the Y positive,

    you see that your tumb point to the back of the screen toward the Z positive...)

    The rule is good in 2D (ortho) and 3D (perspective)

     

     

    In 2D ortho projection 2 same sized cube one at z=0 and one at z=-100 side by side

    will appear as the same square...in 2D

    In 3D (perpective projection) the same sized cube farther will appear smaller...

     

    Weirdly the 2D (ortho) is in reality 3D also...you do have a third dimension...

     

    Now this was for ''2D''...

     

    For perpective projection the notion of top/left or center is not so important

     

    Your LookAt function that do the VIEW matrix will consider the center of

    the screen to be your eyes x,y,z position

     

    It's not in the perspective projection that you decide what your eye position should be

    It's more the View matrix

     

    The perspective projection (3D) give you a frustum ("Rectangular Cone")

    that is a rectangular box

    that begin with your rectangular screen and go in the back to a smaller rectangular shape

    (or bigger at the back, I'm not sure)

     

    It's by the View matrix that you move that Rectangular Cone around in 3D

    to see your 3D world...Your eye are in the middle of the screen

    But with the view matrix (and the lookat function) you can move that Cone

     

    If you want to see your same 2D cube in 3D

    You set your View matric (using LookAt) at this position:

    Eye=D3DVEctor3(0,0,-10) (z negative are where your eyes are behind the keyboard)

    Target to see = D3DVector3(0,0,0)

    Up axis=D3DVEctor3(0,1,0)

     

    This way your 0,0,0 will be in the center of the screen where your ''eyes'' lookat

     

    To set your bottom left view you do this in lookat function (to set view matrix)

    Eye=D3DVector3(10,10,-10)

    Target to see = D3DVector3(10,10,0)

    Up axis=D3DVEctor3(0,1,0)

     

    You will have 10,10 as the center of your screen

    But the rest is up to the perspective to decide...

    You will not have 0,0 for bottom/left view...it depend of the perpective frustum

     

    You define the perspective projection as the frustum view (aspect and Z plane of frustum ''rectangular cone'') (set up the size of the ''flash light cone'' to use)

     

    You use the View projection to set the eye position (by using LookAt function)

    (this will move the ''rectangular cone'' around in your world...

    like a spot light of a flash light vision in the dark)

     

    You use the World matrix to place object in the scene, this put it in the world

    (don't care about anything else when you place object in the scene

    the Proj and view matrix do the work)

     

    as for your PerpectiveLH function maybe it would be easier to use another function

    that set the matrix then use D3DXTransform to set the View, Proj and World matrix

     

    Set Proj matrix once by Function MatrixPerspective or MatrixOrtho set D3D_PROJ with a D3DTransform that use your matProj

    (only have to do this once if your window size stay the same)

     

    Set the ''camera'' with Lookat to create the View matrix (use D3DXTransform set the D3D_VIEW)

    (once by scene)

     

    Create a D3DIdentity matrix for the World martix (add translation, multiply to add those matrix)

    Set the D3DTranform to set the D3D_World...put your object using only the world matrix set

    by the transform

     (Set a World matrix for each element you want to place in scene) 

     

    In resume we draw in a World matrix referential, you move that referential around to draw

     

    The perspective matrix define a ''flash light cone''

     

    You move that flash light cone in your world by defining a view matrix

    (using where your eyes are placed and where you look at) (using Lookat function)

     

    The only stuff you see of your world is in that cone that you move around

     

    Hoping this can help...

     

     


  • Hari M

    Thanks for the reply!

    I should have realised I don't need to move each point to the centre of the screen after each point translation.

    I'm not using DX3, but I'll look into it.

    Thanks - Gary.


  • Perspective projection