Skip to main content TerryFunggg Blog

Perspectivce Divide

The differen with Orthographic projection , Perspectivce Projection which care about the z. Using z to represent depth.

Lets say we want to make vector P a 3D vector (x, y, z) to display on screen as vector P’(x,y) on screen.

The image show that this is a similar triangle from our eye A to point P which lable e with z depth

The similar trinangle is ADE and ABC, the the similar triangle formular is:

$$ \frac{BC}{DE} = \frac{AB}{AD} $$

Replace the label as our vector value: $$ \frac{P’x}{Px} = \frac{1}{Pz} $$

Do some simple algebra make the target P’x to the left: $$ P’x = \frac{Px}{Pz} $$

Now we get the formular that how to get the x on screen.

Same as P’y here:

$$ \frac{BC}{DE} = \frac{AB}{AD} $$

Replace the label as our vector value: $$ \frac{P’y}{Py} = \frac{1}{Pz} $$

Do some simple algebra make the target P’y to the left: $$ P’y = \frac{Py}{Pz} $$

Finally we get a formular call prespective divide: $$ P’x = \frac{Px}{Pz} $$ $$ P’y = \frac{Py}{Pz} $$ Simple formular, but tell you the magic - The x and y is relate with z value is big or small.

implement

Define vector 3D:

c code snippet start

typedef struct {
  float x;
  float y;
  float z;
} vec3_t;

c code snippet end

Define a simple camera as our eyes:

c code snippet start

vec3_t camera_position = { .x = 0, .y = 0, .z = -5 };

c code snippet end

z = -5 for adjust the view of 3D object.

Create a 3D cube (9x9x9) as example

c code snippet start


vec3_t cube_points[9 * 9 * 9];

for(float x = -1; x <= 1; x += 0.25) {
    for(float y = -1; y <= 1; y += 0.25) {
      for(float z = -1; z <= 1; z += 0.25) {
        vec3_t point = { .x = x, .y = y, .z = z}; // c99 format

        cube_points[point_count++] = point;
      }
    }
}

c code snippet end

Change the project function based on above formular:

c code snippet start


vec2_t project(vec3_t point) {
  vec2_t projected_point = {
    .x = (fov * point.x) / point.z,
    .y = (fov * point.y) / point.z
  };
  return projected_point;
}

c code snippet end

Render the Cube:

c code snippet start


for(int i = 0; i < (9 * 9 * 9); i++) {
    vec3_t point = cube_points[i];
    // adjust each point Z with camera.z
     point.z -= camera_position.z; 

    // Project the current point
    vec2_t projected_point = project(point);
    // Save the projected 2D vector in the array
    projected_points[i] = projected_point;
}

c code snippet end

Result:

Prove that the Z can effect the X and y. We adjust the Z value on each game loop.

c code snippet start

camera_position.z += 0.001;

c code snippet end