• 10
• 9
• 13
• 10
• 18

# How to get an oblique projection matrix?

This topic is 2910 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I want to project a 3D point x onto a plane (defined by a b c d) along a 3D direction v. I looked at the wikipedia and could not understand, those explanation looks very abstract. Any one can help me to produce a matrix to do it.

##### Share on other sites
The following is not the most general approach, but maybe it gives you enough hints...

I allow an aberration of the LOS (line-of-sight) of the virtual camera (getters not shown):
class Camera {...public: // projection   /**   sets the mode of projection as specified.   */   void setModeOfProjection(Projection::mode_t mode);   /**   sets the LOS so that it makes the specified \a angleToHorizon and the also specified \a depthShortening. This routine   just does a setLOSAberration(float, float, bool), where the arguments are computed to:   \code     horinzontal = depthShortening * cos(angleToHorizon)     vertical = depthShortening * sin(angleToHorizon)   \endcode   */   void setLOS(angle_t angleToHorizon, float depthShortening);   /**   resets the LOS to be co-linear with the principal z-axis of this camera's frame. This routine is just a piggy-back on   setLOSAberration(float, float, bool) for convenience.   */   inline void resetLOS() {      setLOSAberration(0.0f, 0.0f);   }   /**   sets the LOS aberration. Normally, the LOS is co-linear to the principal z-axis of this camera's frame, but the   camera may also show an aberration here, likely in co-operation with a parallel projection mode, an oblique projection.   \post horizontalLOSAberration() == \a horizontal   \post verticalLOSAberration() == \a vertical   */   virtual void setLOSAberration(float horizontal, float vertical);...};

Using these setters looks e.g. like so:
voidProjection::setToPerspective(Camera& target) {   target.setModeOfProjection(PERSPECTIVE);   target.resetLOS();}voidProjection::setToOrthographic(Camera& target) {   target.setModeOfProjection(PARALLEL);   target.resetLOS();}voidProjection::setToCavalier45(Camera& target) {   target.setModeOfProjection(PARALLEL);   target.setLOS(Angle::HALF_PI/2.0f, 1.0f);}voidProjection::setToCavalier30(Camera& target) {   target.setModeOfProjection(PARALLEL);   target.setLOS(Angle::HALF_PI/3.0f, 1.0f);}voidProjection::setToCabinet45(Camera& target) {   target.setModeOfProjection(PARALLEL);   target.setLOS(Angle::HALF_PI/2.0f, 0.5f);}voidProjection::setToCabinet30(Camera& target) {   target.setModeOfProjection(PARALLEL);   target.setLOS(Angle::HALF_PI/3.0f, 0.5f);}voidProjection::setToDimetricTopView(Camera& target) {   target.setModeOfProjection(PARALLEL);   target.setLOSAberration(0.25f, 0.5f);}voidProjection::setToDimetricSideView(Camera& target) {   target.setModeOfProjection(PARALLEL);   target.setLOSAberration(0.5f, 0.25f);}

Then in OpenGL renderer, where the PROJECTION matrix set-up happens, I first generate the usual projection matrix by e.g. using glOrtho, and then consider LOS aberration as follows:
   if(_currentCamera->horizontalLOSAberration() || _currentCamera->verticalLOSAberration()) {      float matrix[16];      for(uint32_t i=0; i<16; ++i) {         matrix = (i%5==0) ? 1.0f : 0.0f;      }      const float viewDistance = _currentCamera->viewDistance();      matrix[8] = _currentCamera->horizontalLOSAberration();      matrix[9] = _currentCamera->verticalLOSAberration();      ::glTranslatef(0.0f, 0.0f, viewDistance);      ::glMultMatrixf(matrix);      ::glTranslatef(0.0f, 0.0f, -viewDistance);   }

As you can see from use of the indices [8] and [9], the aberrations are considered by offsetting x or y, resp., in dependence of the depth. Due to the surrounding glTranslate()s the offsets are enforced to be zero exactly at the distance of the view plane. So any plane parallel to the view plane and at the distance of viewDistance is left where it is.

##### Share on other sites
Quote:
 Original post by chiyuwangI want to project a 3D point x onto a plane (defined by a b c d) along a 3D direction v.

It sounds to me like you might be trying to find the intersection of a ray with a plane. If this is the case, you don't want to search for stuff on projection matrices. Projection matrices are applicable to your problem, but it seems like the hard way to approach it.

Instead, consider that you are sliding your point x in the direction of v. Eventually, you will hit the plane, and this is the point you are trying to find.

Use the parameter t to represent the sliding point like this

$\mathbf{x}^\prime = \mathbf{x} + t\mathbf{v}$

Now, you want to find the value of t so that the sliding point lies on the plane.

The condition that the sliding coordinates are lying on the plane is given by

$x^\prime a + y^\prime b + z^\prime c = d$

inserting the definition of the sliding coordinates with respect to the parameter t gives

$\left(x + t v_x\right)a + \left(y + t v_y\right)b + \left(z + tv_z\right)c = d$

Solving for t gives

$t = \frac{d - xa - yb - zc}{v_x a + v_y b + v_z c}$

NOTE: if the denominator of t is zero, then the sliding point will never come into contact with the plane.

Now, insert this value of t back into the equation of the sliding point to get the actual projected point.

$\mathbf{x}^\prime = \mathbf{x} + \frac{d - xa - yb - zc}{v_x a + v_y b + v_z c}\mathbf{v}$

##### Share on other sites
Thank you for your help. I will try it.

Anyway, if I can get a matrix, it will be very easy for me.

This matrix will concatenate with other transformation matrices and transfered into my pixel shader. In my shader it will be just a matrix multiplication.

Quote:
Original post by Eric_Brown
Quote:
 Original post by chiyuwangI want to project a 3D point x onto a plane (defined by a b c d) along a 3D direction v.

It sounds to me like you might be trying to find the intersection of a ray with a plane. If this is the case, you don't want to search for stuff on projection matrices. Projection matrices are applicable to your problem, but it seems like the hard way to approach it.

Instead, consider that you are sliding your point x in the direction of v. Eventually, you will hit the plane, and this is the point you are trying to find.

Use the parameter t to represent the sliding point like this

$\mathbf{x}^\prime = \mathbf{x} + t\mathbf{v}$

Now, you want to find the value of t so that the sliding point lies on the plane.

The condition that the sliding coordinates are lying on the plane is given by

$x^\prime a + y^\prime b + z^\prime c = d$

inserting the definition of the sliding coordinates with respect to the parameter t gives

$\left(x + t v_x\right)a + \left(y + t v_y\right)b + \left(z + tv_z\right)c = d$

Solving for t gives

$t = \frac{d - xa - yb - zc}{v_x a + v_y b + v_z c}$

NOTE: if the denominator of t is zero, then the sliding point will never come into contact with the plane.

Now, insert this value of t back into the equation of the sliding point to get the actual projected point.

$\mathbf{x}^\prime = \mathbf{x} + \frac{d - xa - yb - zc}{v_x a + v_y b + v_z c}\mathbf{v}$