Homogeneous coordinates in 3D

Here is an animation of a house. It’s special because it’s drawn using my very own ✨homogeneous coordinates✨ library.

In my previous post, I showed homogeneous coordinates in 2D. I can geometrically visualize homogeneous coordinates for 2D space - the hard part being the projection matrix that warps a 3D space of homogeneous coordinates to create a 1D projection of a 2D space. But my brain melts when trying to visualize how a 4D projection matrix warps 4D space to create a 2D projection of a 3D space. Therefore, for this 3D animation, I reasoned entirely by analogy with my 2D implementation. That said, the conversion from 2D to 3D was clean and mechanical.

Here are the matrices I derived for rotation, scaling, translation and projection. They are in column-major format, which is the only sensible format, and the one used by my 5-line matrix library.

const rotateZHom3d = a => [
  [ Math.cos(a), Math.sin(a), 0, 0], // x
  [-Math.sin(a), Math.cos(a), 0, 0], // y
  [0,            0,           1, 0], // z is unchanged
  [0,            0,           0, 1], // w is unchanged
];
const rotateXHom3d = a => [
  [1,            0,           0, 0], // x is unchanged
  [0,  Math.cos(a), Math.sin(a), 0], // y
  [0, -Math.sin(a), Math.cos(a), 0], // z
  [0,            0,           0, 1], // w is unchanged
];
const rotateYHom3d = a => [
  [ Math.cos(a), 0, Math.sin(a), 0],
  [0,            1, 0,           0],  // y is unchanged
  [-Math.sin(a), 0, Math.cos(a), 0],
  [0,            0, 0,           1],  // w is unchanged
];
const scaleSepHom3d = (s) => [ 
  [s[0],     0,    0, 0],  // x 
  [0,    s[1],     0, 0],  // y
  [0,        0, s[2], 0],  // z
  [0,        0,    0, 1],  // w
];
const scaleHom3d = s => scaleSepHom3d([s,s,s]);
const translateHom3d = v => [
  [   1,    0,    0, 0],  // x
  [   0,    1,    0, 0],  // y
  [   0,    0,    1, 0],  // z
  [v[0], v[1], v[2], 1],  // w
];

// Projects onto the z=1 plane from the origin
const projectHom3d = [
  [1,0,0,0], // x is unchanged
  [0,1,0,0], // y is unchanged
  // Points scaled down in proportion with their distance from the projection plane
  [0,0,1,1], 
  // A point's w-factor is IGNORED. For projection, we're only interested in _direction_ from the origin
  [0,0,0,0],
];
Tagged #mathematics, #programming, #js, #graphics.

Similar posts

More by Jim

👋 I'm Jim, a full-stack product engineer. Want to build an amazing product and a profitable business? Read more about me or Get in touch!

This page copyright James Fisher 2020. Content is not associated with my employer. Found an error? Edit this page.