RealPool

Anmelden Profil nicht verfügbar
← Blog
Engineering

How we built the pool table in code

A pool table looks simple. It is a green rectangle with six holes and a wooden frame. Building one in code that behaves like a real table is more work than it sounds, because every measurement matters once you start rolling balls into pockets and bouncing them off rails. This is how RealPool's table is put together, from the dimensions to the pockets to the cushions.

How big is a regulation pool table?

RealPool's table follows the WPA tournament 9-foot spec. The playing surface is 2540mm by 1270mm, and the ball radius is 28.575mm. Those are the same numbers a real tournament table is built to, so the model is a regulation table at scale rather than something that just looks about right.

Working in millimeters from a published spec has a nice side effect. When something in the simulation feels off, I can check it against a known number instead of guessing. The ball is the size it should be, the table is the shape it should be, and the rest of the geometry is built on top of those fixed values.

How are the pockets shaped?

The pocket mouth widths follow the spec too: roughly 116mm at the corners and about 127.65mm at the side pockets. But the mouth width is only the opening. The actual shape of each pocket, the curve of the jaws and the back of the hole, comes from the table artwork.

The table is drawn as an SVG. A build script (tools/build-pocket-polygons.mjs) reads that SVG and extracts each pocket's outline as a polygon, then writes those polygons into generated TypeScript. This happens at build time, so the physics matches the drawn table exactly and nothing has to load an image at runtime. The SVG is the artist-owned source. The polygons are regenerated from it whenever the artwork changes, and never hand-edited.

One source of truth

Keeping the pocket shape in the artwork means the picture and the polygon the physics uses come from the same outline. If the artist redraws a pocket, the polygon that decides whether a ball drops is regenerated with it. There is no second copy of the shape to keep in sync by hand.

Why is the table drawn as an SVG?

An SVG is vectors, not pixels, so the table stays sharp at any size and the geometry inside it is exact. That second part is what matters here. Because the file is made of real coordinates, a script can read it and pull out the pocket outlines as numbers the physics can use directly.

A flat image could be blitted to the screen, but you could not derive collision shapes from it without tracing pixels, which is fuzzy and slow. The vector file gives the renderer something to draw and gives the build a precise outline to extract, from one artist-owned source. If you want the longer story on how the table actually reaches the screen, the canvas to WebGL post covers the rendering side.

How are the rails and cushions built?

The rails are built from six straight cushion faces (the long rails are split where the side pockets interrupt them) and twelve angled jaws, two at each pocket, that funnel a ball into the hole. The jaw angles follow the spec: about 38 degrees at the corners and about 76 degrees at the sides. Those angles are why a ball rattling near a pocket sometimes drops and sometimes spits back out, the same way it does on a real table.

Each segment is a line the physics can test a ball against. When a ball reaches one, the code works out exactly when and where it touches, then computes the bounce. The pockets are not gaps in the rail by accident: they are the spaces between the segments, shaped by the jaws on either side.

Why do the physics and the picture use different pocket centers?

There are two sets of pocket centers, on purpose. The physics uses the true geometric pocket centers, so a ball that should drop does drop and the capture math is honest. The rendered pocket discs are pushed outward a little, so they sit in the rail wood instead of overlapping the felt.

If I used the true centers for the visuals, the dark pocket circles would creep onto the green and look wrong. If I used the shifted centers for the physics, balls would behave as though the holes were in the wrong place. So one set is for correctness and the other is for how it reads on screen. They live a few millimeters apart and never touch each other's job.

How do the cushions bounce?

A cushion bounce is not a simple mirror. A real rail squashes when a ball hits it, and the ball's spin grabs at the cloth, so the rebound angle depends on speed and english, not just the angle of approach. RealPool uses a published cushion model (Mathavan et al., IMechE 2010) to capture that, rather than flipping the ball's direction like light off a mirror.

The payoff is that rail shots feel like rail shots. A ball with running english widens off the cushion, a ball with check english shortens, and the angle changes with pace. It is physically grounded behavior that comes out of the model instead of being faked per shot. The rest of the motion, the rolling and the collisions between balls, runs through the same deterministic core described in the physics engine post.

Common questions

How big is a regulation pool table?

RealPool follows the WPA tournament 9-foot spec. The playing surface is 2540mm by 1270mm and the ball radius is 28.575mm, so the model matches a real tournament table at scale. If the dimensions or the terms are new to you, the pool terms glossary explains the parts of the table.

Where do the pocket shapes come from?

The table is drawn as an SVG, and a build script reads that file and extracts each pocket's outline as a polygon. The polygons are written into generated TypeScript at build time, so the physics matches the drawn table with no image loaded at runtime.

Why use two different pocket centers?

The physics uses the true geometric pocket centers so pocketing is accurate. The rendered pocket discs are pushed outward a little so they sit in the rail wood instead of overlapping the felt. One set is for correctness, the other is for how it looks. If you want to see how the table plays under the actual rules, the 8-ball rules post walks through a game.

Play a rack