# What are viewport transformation matrixes for this coordinate system?

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 I want to convert NDC vertexes into a viewport whose coordinate system looks like this 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.

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