1
$\begingroup$

I have a set of vertexes (x, y, z) in normalized device coordinates. Its x, y, and z values are in the range (-1, 1). Normalized device coordinates use the left-handed coordinate system, as shown below

ndc

I want to convert NDC vertexes into a viewport whose coordinate system looks like this

vp

It is a standard coordinate system used by most 2D graphics libraries. x starts from the top left corner and goes to the right while y starts from the same corner and goes down. I decided to make z to go into the page. All NDC vertexes must fit inside the dotted rectangular box, shown above.

What is the set of transformation matrixes that converts NDC coordinates $(x, y, z, 1)$ (note that I am using homogenous coordinates here) to viewport coordinates $(x', y', z', 1)$?

This is what I came up with

$$ \begin{bmatrix} x' \\ y' \\ z' \\ 1 \end{bmatrix} = \begin{bmatrix} 1 & 0 & 0 & width/2 \\ 0 & 1 & 0 & height/2 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} width/2 & 0 & 0 & 0 \\ 0 & -height/2 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} $$

where $width$ and $height$ are width and height of viewport. I first scale vertexes to viewport width and height and also flip the y coordinate (notice the minus sign). Then I translate the resulting vertex to fit into the viewport. But I'm not sure if my viewport transformation matrix is correct because I think the resulting z value might be wrong. What should I change here?

—————-

Crossposted in math.stackexchange.

$\endgroup$

1 Answer 1

1
$\begingroup$

The z-axis is indeed not correct if you want to transform to the space depicted in the second picture, because you perform no transformations on the z-axis. So your coordinate origin lies in the middle between the top-left-front and the top-left-back vertex. The coordinate range is still -1 to 1. You can easily fix it by applying the same transformation as for the other axis. Introduce a depth to define the coordinate range in the z-direction. Then your correct transformation should be:

$$ \begin{bmatrix} x' \\ y' \\ z' \\ 1 \end{bmatrix} = \begin{bmatrix} 1 & 0 & 0 & width/2 \\ 0 & 1 & 0 & height/2 \\ 0 & 0 & 1 & depth/2 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} width/2 & 0 & 0 & 0 \\ 0 & -height/2 & 0 & 0 \\ 0 & 0 & depth/2 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} $$

Multiplication yields the following transformation matrix:

$$ \begin{bmatrix} width/2 & 0 & 0 & width/2 \\ 0 & -height/2 & 0 & height/2 \\ 0 & 0 & depth/2 & depth/2 \\ 0 & 0 & 0 & 1 \end{bmatrix} $$

To understand it a bit better it is probably easier to postpone the scaling until the end and look at the different substeps. Starting in NDC coordinates, we first flip the y-axis using the reflection matrix:

$$ \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} $$

As a result, the point (-1,-1,-1) in the new intermediate coordinate system is the top-left-front point which is (-1, 1,-1) in NDC coordinates. Since we want our coordinates to be in the range (0, x) we translate all vertices in every axis by 1. This moves the origin of the next coordinate system to (-1,-1,-1) in our current intermediate system:

$$ \begin{bmatrix} 1 & 0 & 0 & 1 \\ 0 & 1 & 0 & 1 \\ 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 1 \end{bmatrix} $$

Now the values are in the range (0, 2) and the current coordinate systems' origin is at the NDC coordinates (-1, 1,-1).

If you multiply both matrices you would get:

$$ \begin{bmatrix} 1 & 0 & 0 & 1 \\ 0 & -1 & 0 & 1 \\ 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 1 \end{bmatrix} $$

All that is left now is to apply the correct scaling. So we need to divide by 2 in every direction and multiply by the corresponding maximum value:

$$ \begin{bmatrix} width/2 & 0 & 0 & 0 \\ 0 & height/2 & 0 & 0 \\ 0 & 0 & depth/2 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} $$

So the final result would be:

$$ \begin{bmatrix} x' \\ y' \\ z' \\ 1 \end{bmatrix} = \begin{bmatrix} width/2 & 0 & 0 & 0 \\ 0 & height/2 & 0 & 0 \\ 0 & 0 & depth/2 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 1 \\ 0 & -1 & 0 & 1 \\ 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} $$

If you multiply it, you will get the same transformation matrix as above

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.