<?xml version="1.0"?>
<!DOCTYPE content [ <!ENTITY nbsp " "> ]>
<rdf:RDF xml:base="http://snarfed.org/rdf"
         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:dc="http://purl.org/dc/elements/1.1/">

<rdf:Description rdf:about="http://snarfed.org">
  <dc:title> snarfed.org  </dc:title>
  <dc:description> draw group stream of consciousness </dc:description>
  <dc:creator> Ryan Barrett &lt;snarfed at ryanb dot org&gt; </dc:creator>
  <dc:language> en </dc:language>
  <dc:format> text/html </dc:format>
  <dc:rights> Copyright 2002-2007 Ryan Barrett </dc:rights>
</rdf:Description>

<rdf:Description rdf:about="http://snarfed.org/space/tictactoe">
  <dc:title> tictactoe </dc:title>
  <dc:creator> Ryan Barrett &lt;snarfed at ryanb dot org&gt; </dc:creator>
  <dc:date> 2003-01-01T05:00:00Z </dc:date>
  <dc:language> en </dc:language>
  <dc:format> text/html </dc:format>
  <dc:rights> Copyright 2002-2007 Ryan Barrett </dc:rights>

  <content>
    <p>For the impatient: <br />
<a href="/space/tictactoe.tar.gz">Download Linux tarball</a> <br />
<a href="/space/tictactoe.zip">Download Windows zipfile</a> <br />
<a href="http://www.xmission.com/~nate/glut.html">Download GLUT</a> (or <a href="/space/glut32.dll">just glut32.dll</a>) <br />
<a href="http://plib.sourceforge.net/">Download Plib</a> <br />
<a href="http://graphics.stanford.edu/courses/cs248-videogame-competition/cs248-01/#tictactoe">CS248 project page</a></p>

<p><a href="/space/refracted.jpg"><img src="/space/refracted_thumb.jpg" alt="/space/refracted_thumb.jpg" title="" /></a><a href="/space/plain.jpg"><img src="/space/plain_thumb.jpg" alt="/space/plain_thumb.jpg" title="" /></a></p>

<h3>Introduction</h3>

<p>Tic-tac-toe is a game that focuses on graphical effects, specifically realistic
3D rendering of water. The water surface is procedurally generated, and the
pieces float realistically on top of it. The water is textured, blended, and
environment mapped. It is fully refracted and incorporates the Fresnel term for
opacity.</p>

<p>Apart from the graphics, tic-tac-toe also has a full-featured, completely
dynamic user interface, sound, AI, and other effects. But you really only came
for the graphics. :P</p>

<h3>How to play</h3>

<p>When you run tic-tac-toe, the game will appear and immediately begin a game
pitting the AI against itself. To rotate your view, click and hold the left
mouse button and move the mouse. To bring up the in-game menu, right-click
anywhere in the screen. You can use the in-game menu to start a new game, make a
move (if it is your turn), change rendering options, or quit. Right-click to
select an item in any of the menus. To scroll the top-level menu, right-click
and hold on one of the scrollbars, then move the mouse.</p>

<p>You can also play with the keypad (make sure NumLock is on). Each button on the
keypad corresponds to a possible move. If you rotate your view around so that it
is not centered, press 'C' to center your view.</p>

<h3>Requirements</h3>

<p>Tic-tac-toe requires <a href="http://www.opengl.org/">OpenGL</a>, which you almost
certainly already have, <a href="http://www.xmission.com/~nate/glut.html">GLUT</a>, which
you probably don't have, and <a href="http://plib.sourceforge.net/">Plib</a>, which you
probably don't have. Tic-tac-toe is Copyright 2001 Ryan Barrett, and is
distributed under the <a href="http://www.gnu.org/licenses/gpl.html">GPL</a> license.</p>

<p>Tic-tac-toe is relatively optimized, but hasn't been tested on many different
video cards. If you have anything less than an nVidia TNT2 (or poor OpenGL
support), you'll probably want to crank down the detail. You can do that by
lowering the FineVerts value in the Water section of tictactoe.ini.</p>

<h3>Download</h3>

<p>Here is the <a href="/space/tictactoe.tar.gz">tarball for Linux</a>. Just run
make (no ./configure needed) to build it. If you've installed the OpenGL or PLIB
libraries in non-standard places, you'll need to edit the Makefile by hand to
point to wherever they're installed.</p>

<p>Here is the <a href="/space/tictactoe.zip">zipfile for Windows</a>. It includes
an executable and the source, along with workspace files for MSVC++. You'll need
opengl32.dll and glut32.dll in your Windows system directory to run it. Your
video card's drivers should come with opengl32.dll, and you can <a href="/space/glut32.dll">download
glut32.dll here</a>.</p>

<h3>Background</h3>

<p>I wrote Tic-Tac-Toe as my <a href="http://graphics.stanford.edu/courses/cs248-videogame-competition/cs248-01/#tictactoe">final
project</a>
for <a href="http://cs248.stanford.edu/">CS248</a> at <a href="http://www.stanford.edu/">Stanford</a>.
The inspiration came from the underground demo scene, specifically from a 64Kb
demo by <a href="http://foobug.yoki.org/">Foobug</a> called
<a href="ftp://ftp.yoki.org/pub/groups/foobug/exodus.zip">Exodus</a>. It has two or three
different water effects that are all incredible. (The first minute or two is
boring, but the rest is definitely worth it!)</p>

<p>If you aren't familiar with the demo scene, or you haven't watched demos before,
you should! Check out <a href="http://www.scene.org/">scene.org</a> or
<a href="http://www.pouet.net/">pouet.net</a>.</p>

<h3>Technical details</h3>

<p><strong><em>Procedural modeling</em></strong></p>

<p>One of the unusual features of tic-tac-toe is the procedural modeling and
dynamics of the water. The water is stored as a heightfield, and the ripples are
propagated with a surprisingly simple filter. I wish I could claim credit for
the filter, but I can't - it's down in the
<a href="/space/tictactoe#citations">citations</a> section. I did extend it to 3D, though -
it was originally conceived only for 2D images. I also added damping and
relaxation to the algorithm. Basically, I store the heightfields for the current
and previous game ticks, and to generate the next heightfield, I take the
difference between the current and previous heightfield at each point and use it
as the velocity for that point. There's more to it, but that's the gist.</p>

<p>To generate ripples, you can simply displace a point in the heightfield.
However, this creates jagged ripples if the displacement is large. So when the
game loads, I precompute a few ripples by displacing a heightfield and
repeatedly running the filter over it. Then, when I need to create a ripple
during this game, I add the heights from one of these precomputed ripples to the
heightfield, centered at the place the ripple should appear.</p>

<p>To make the pieces float, I store their velocity and orientation. For each game
tick, I apply the velocity along their orientation and then update their
velocity and orientation based on the heightfield below them and its normals.
Again, I use damping and relaxation to keep this smooth and somewhat delayed, so
that the look like they are reacting to the water's motion instead of moving
exactly in sync with it.</p>

<p><strong><em>Advanced rendering</em></strong></p>

<p>I implemented both refraction and the fresnel term in an attempt to make the
water appear more realistic. I approximated both of them with formulas that I
think are acceptable, since there's no need for it to be physically exact. For
more information, see refract.cpp and fresnel.cpp. The approximation I used for
refraction requires a fixed viewpoint, so it can only be turned on if the viewer
is at the top, looking straight down. I wish I'd used vertex shaders, which
would likely have been fast enough for any viewpoint using them...but I ran out
of time. :P</p>

<p>Strangely, though, it looks best without refraction or fresnel term, just with
plain texturing and environment mapping. I guess it's a lesson to be learned: if
you can get as good or better results with phenomenological models, go for it.</p>

<p><strong><em>In-game UI</em></strong></p>

<p>I wrote a windowing toolkit similar to GLUI or MUI, except that it is drawn in
the same window as your game. This allowed me to run my game full-screen, which
is more immersive. It provides windows, items, checkboxes, scrollbars, and
scrollable windows. (This is definitely less functionality than GLUI or MUI, but
it was all I needed and it was still plenty of work.) Windows can have child
windows, much the way application menus can have sub-menus in most common
windowing systems. It's modular, and could drop it into any other OpenGL program
with a negligible amount of effort.</p>

<p><strong><em>Models and textures</em></strong></p>

<p>I created the X piece model myself and the O piece is a call to glutSolidTorus.
Unfortunately, I don't know where the textures are from. I've compiled a small
library of public-domain textures and art assets over the last four years or so,
and all of these are taken from that.</p>

<p><strong><em>Other</em></strong></p>

<p>These features that didn't take a lot of work, but deserve mentioning:</p>

<ul>
<li><p>Rain. It rains on the water. The raindrops create ripples where they hit.</p></li>
<li><p>AI. The computer plays a pretty good game of tic-tac-toe.</p></li>
<li><p>Configurable settings. Most game and (especially) rendering settings can be
changed in tictactoe.ini without rebuilding the game. Settings that can be
changed include the size of the height field, the sound effects, all of the
textures, rain settings, and variables that affect the behavior of the water.
See the <a href="/space/tictactoe#citations">citations</a>.</p></li>
</ul>

<h3>Citations  <a name="citations"></a> <a href="/space/tictactoe#citations"><img src="/Icon-Permalink.png" alt="Icon-Permalink.png" title="" /></a></h3>

<ul>
<li><p><a href="http://freespace.virgin.net/hugo.elias/">Hugo Elias</a>' <a href="http://freespace.virgin.net/hugo.elias/graphics/x_water.htm">ripple
filter</a>. Hugo
didn't actually invent it, he just wrote it down. This is by far the most
important citation. I coded up the ripple engine, but I didn't come up with the
basic idea. I just took the algorithm, extended it to 3D, and added damping and
relaxing.</p></li>
<li><p><a href="http://robertk.com/">Robert Kesterson</a>'s <a href="http://robertk.com/source/">stlini
library</a> for reading .ini files.</p></li>
<li><p>Some of the GLUT initialization (like the code in main()) was copied from
<a href="http://matt.ginzton.net/">Matt Ginzton</a>'s
<a href="http://graphics.stanford.edu/courses/cs248-00/helpsession/opengl/code_example.html">glut_example</a>.</p></li>
</ul>

  </content>

  <rdf:Seq>

  </rdf:Seq>
</rdf:Description>
</rdf:RDF>
