Confetti

Date: 2023-07-20 ๏ฝœ Author: Jason Eveleth

Table of Contents

Overview

I took computer vision many years ago, and I wanted to refresh my knowledge of camera matrices and rendering. So I created this website that displays an infinite stream of confetti. It calculates the movement of confetti in real-time. The code can be found here.

Design

I wanted physics and camera matrices to be the focus of the project, so the UI is spartan.

To describe what is happening, we will assume that in the world, x,y,zx,y,z are arranged as if we're looking at an xx-yy graph, and zz is coming toward us:

We need to convert a point in that, to a point on the screen, which has coordinates (0,0)(0,0) in the top left, and increasing xx and yy going down and right. We can do that using Rt, which is the extrinsic matrix:

[Rโˆฃt]=[100tx010ty001tz].[R\mid t]=\begin{bmatrix}1&0&0&t_x\\ 0&1&0&t_y\\ 0&0&1&t_z\end{bmatrix}.

This matrix describes how the camera is positioned in relation to the origin. Our rotation is the identity, and our translation is 1010 in the zz direction (since our camera is oriented normally at (0,0,โˆ’10)(0,0,-10)). Thus, tx=ty=0,tz=10t_x=t_y=0,t_z=10. Left multiplying this matrix with a vector will move it 10 units in the zz direction (bringing the camera to the origin).

The second matrix we need is the intrinsic matrix:

K=[fxsu0fxv00s].K=\begin{bmatrix}f_x&s&u\\ 0&f_x&v\\ 0&0&s\end{bmatrix}.

fx,fyf_x, f_y are the focal length in pixels of the camera. u,vu,v are the principle point offset (shift in the sensor inside the camera). ss is skew. For us, fx=fy=maxโก(w,h)/2f_x=f_y=\max(w, h)/2, which is the maximum of the width and height of the screen. Our skew is 1, and our principle point offsets are 0.

The index.js file holds most of the code, and math.js has some utility functions (like matrix multiplication). There is one function I want to highlight in math.js, and that is world2image. It converts world coordinates to image coordinates. It multiplies Kโ‹…[Rโˆฃt]โ‹…cK \cdot [R\mid t] \cdot c, where cc is the world coordinates and rescales the x,yx,y values by zz. The KRt matrix is a precomputed multiplication of the intrinsic and extrinsic matrices and will take a point in 3D world coordinates and convert it to an x,yx,y coordinate system which is what the camera sees. Finally, we convert the x,yx,y coordinates to screen coordinates.

With the camera matrix calculation out of the way, let's dig into the implementation. I keep track of confetti using its center (in world coordinates), velocity, acceleration, and its two rotation parameters ฮธ\theta and ฯ•\phi. I used a constant acceleration down at โˆ’9.81-9.81 (for obvious reasons). I initialize the position to be the center of the screen (the origin). I initialize the velocity randomly and uniformly from the top quadrant of a circle. I initialize the rotation parameters, and their deltas randomly.

The main approach is to keep a big array of confetti, and on each rendering step:

Since we are calculating how each confetti would fall in real-time, large amounts of confetti (or badly optimized browsers), can really slow down a machine. Something to keep in mind if you use the website. Overall, I really enjoyed this project.

ยฉ Jason Eveleth 2023 ยท Powered by Franklin.jl ยท Last modified: December 31, 2024 Page Source