Hello, I’m Glenn Fiedler and welcome to ** Virtual Go**, my project to simulate a Go board and stones.

Our first goal is to develop a physically accurate simulation of the motion of a go stone.

The first step towards this goal is to study and understand the shape of a go stone in detail.

If you’ve ever played go, you know that a go stone has a particularly interesting wobble when placed on the board. This wobble is a direct consequence of its unique shape.

It’s very important to understand this shape so we can simulate it properly. *So lets get started!*

## Slate And Shell

In Japan, Go stones are traditionally made out of slate and clam shell.

Clam shell stones come in several grades of quality the highest being yuki or “snow” grade with fine regularly spaced lines.

Go stones also come in various sizes, the choice of which is mostly personal preference. The thicker the stone the more expensive it is as only a small portion of the clam shell is suitable.

At first the go stone seems like an ellipse, but side-on you can see that it is not. Instead it is a very interesting shape called a biconvex solid.

This shape is interesting because it is the intersection of two spheres.

We can study this shape in 2D by looking at the intersection of two circles:

By varying the radius of the circle and how far apart the center of the circles are, we can generate go stones of different sizes.

This is interesting, but when I’m creating a go stone I don’t really want it to be parameterized this way. Instead I’d like to say, “Hey, I want a stone this width and this height” and have a function that calculates what the radius of the circles are and how far apart they should be.

In order to write this function we need to do some math:

First notice that the point Q lies on the generating circle, so the line CQ has length r:

[latex]d + h/2 = r[/latex]

[latex]d = r – h/2[/latex]

The point P is also on the generating circle so the green line CP has length r as well. Using Pythagoras theorem and substituting for d:

[latex]r^2 = d^2 + (w/2)^2[/latex]

[latex]r^2 = ( r – h/2 )^2 + (w/2)^2[/latex]

[latex]r^2 = ( h^2/4 – hr + r^2 ) + w^2/4[/latex]

[latex]r^2 = h^2/4 – hr + r^2 + w^2/4[/latex]

[latex] 0 = h^2/4 – hr + 0 + w^2/4[/latex]

[latex] hr = h^2/4 + w^2/4[/latex]

[latex] r = ( h^2 + w^2 ) / 4h[/latex]

Which gives us everything we need to write the function:

void calculateBiconvex( float w, float h, float & r, float & d ) { r = ( w*w + h*h ) / ( 4*h ); d = r - h/2; }

Now that we can mathematically define a go stone parameterized by its width and height, there is just one problem: the edge is very sharp!

In order for our our stone to be aesthetically pleasing we need to round off the edge with a bevel.

Lets parameterize the bevel by its height b:

In three dimensions the bevel is actually a torus (donut) around the edge of the go stone. We need to calculate the major and minor radii r_{1} and r_{2} of the torus as a function of b and the dimensions of the go stone:

The key to solving this is to realize that if the go stone and the bevel are to match perfectly then the tangent of the two circles must be equal at the point P.

If the tangent is equal then the normal must be equal as well. This means that the center of the bevel circle lies at the intersection of the line CP and the x axis. We already know C so if we can find the point P then we can find this intersection point. Once we know the intersection point we can find r_{1} and r_{2}.

Since P is at the start of the bevel:

[latex]P_y = b/2[/latex]

Because P lies on the biconvex circle with center C and radius r we can use the equation of the circle to find x as a function of y:

[latex]x^2 + y^2 = r^2[/latex]

[latex]x = \sqrt{ r^2 – y^2 }[/latex]

We need y relative to the circle center C, not in go stone coordinates, so we add d and substitute y’ for y:

[latex]y’ = b/2 + d[/latex]

[latex]P_x = \sqrt{ r^2 – ( b/2 + d )^2 }[/latex]

We can now find r_{1} by similar triangles:

[latex]r_1/P_x = d / ( d + b/2 )[/latex]

[latex]r_1 = P_x d / ( d + b/2 )[/latex]

and q by Pythagoras theorem:

[latex]q^2 = d^2 + r_1^2[/latex]

[latex]q = \sqrt{ d^2 + r_1^2 }[/latex]

Because line CP has length r and substituting for q:

[latex]q + r_2 = r[/latex]

[latex]r_2 = r – q[/latex]

[latex]r_2 = r – \sqrt{ d^2 + r_1^2 }[/latex]

Now we have everything we need to write the function:

void calculateBevel( float r, float d, float b, float & r1, float & r2 ) { const float y = b/2 + d; const float px = sqrt( r*r - y*y ); r1 = px * d / ( d + b/2 ); r2 = r - sqrt( d*d + r1*r1 ); }

An important note: we’re only going to apply this bevel to the go stone that we render.

All physics calculations use the biconvex solid with sharp edges.

Why? Well, the bevel is very small and it has very little effect on how the stone moves. Plus, seeing as how the go stone typically spends most of it’s time wobbling about on the sphere surface, cutting a small corner here (or not) seems a perfectly good approximation.

Using approximate collision detection like this is actually quite common in video games. For example, a highly detailed triangle mesh is typically approximated with one or more convex shapes because doing exact triangle-triangle collision detection is very slow.

**Next:** Tessellating The Go Stone

If you enjoyed this article please consider making a small donation. __Donations encourage me to write more articles!__

it should be x = sqrt(r^2-y^2)

You are right. Thanks!