Here is a report of the Ray Tracer written by myself Christopher Chedeau and Gauthier Lemoine. We've taken the file format and most of the examples from the Ray Tracer of our friends Maxime Mouial and Clément Bœsch. The source is available on Github.

It is powered by Open Source technologies: glMatrix, CodeMirror, CoffeeScript, Twitter Bootstrap, jQuery and Web Workers.

Check out the demo, or click on any of the images.

Objects

Our Ray Tracer supports 4 object types: Plane, Sphere, Cylinder and Cone.

The core idea of the Ray Tracer is to send rays that will be reflected on items. Given a ray (origin and direction), we need to know if it intersect an object on the scene, and if it does, how to get a ray' that will be reflected on the object.

Knowing that, we open up our high school math book and come up with all the following formulas.

Legend: Ray Origin \(O\), Ray Direction \(D\), Intersection Position \(O'\), Intersection Normal \(N\) and Item Radius \(r\).

Intersection Normal
Plane \[t = \frac{O_z}{D_z}\] \[
N = \left\{
\begin{array}{l}
x = 0 \\
y = 0 \\
z = -sign(D_z)
\end{array} \right.
\]
Sphere \[
\begin{array}{l l l}
& t^2 & (O \cdot O) \\
+ & 2t & (O \cdot D) \\
+ & & (O \cdot O) - r^2
\end{array}
= 0\]
\[
N = \left\{
\begin{array}{l}
x = O'_x \\
y = O'_y \\
z = O'_z
\end{array} \right.
\]
Cylinder \[
\begin{array}{l l l}
& t^2 & (D_x D_x + D_y D_y) \\
+ & 2t & (O_x D_x + O_y D_y) \\
+ & & (O_x O_x + O_y O_y - r^2)
\end{array}
= 0\]
\[
N = \left\{
\begin{array}{l}
x = O'_x \\
y = O'_y \\
z = 0
\end{array} \right.
\]
Cone \[
\begin{array}{l l l}
& t^2 & (D_x D_x + D_y D_y - r^2 D_z D_z) \\
+ & 2t & (O_x D_x + O_y D_y - r^2 O_z D_z) \\
+ & & (O_x O_x + O_y O_y - r^2 O_z O_z)
\end{array}
= 0\]
\[
N = \left\{
\begin{array}{l}
x = O'_x \\
y = O'_y \\
z = - O'_z * tan(r^2)
\end{array} \right.
\]

In order to solve the equation \(at^2 + bt + c = 0\), we use
\[\Delta = b^2 - 4ac \]\[
\begin{array}{c c c}
\Delta \geq 0 & t_1 = \frac{-b - \sqrt{\Delta}}{2a} & t_2 = \frac{-b + \sqrt{\Delta}}{2a}
\end{array}
\]

And here is the formula for the reflected ray:

\[
\left\{
\begin{array}{l}
O' = O + tD + \varepsilon D' \\
D' = D - 2 (D \cdot N) * N
\end{array}
\right.
\]

In order to fight numerical precision errors, we are going to move the origin of the reflected point a little bit in the direction of the reflected ray (\(\varepsilon D'\)). It will avoid to falsely detect a collision with the current object.

Coordinates, Groups and Rotations

We want to move and rotate objects. In order to do that, we compute a transformation matrix (and it's inverse) for each object in the scene using the following code:

\[
T = \begin{array}{l}
(Identity * Translate_g * RotateX_g * RotateY_g * RotateZ_g) * \\
(Identity * Translate_i * RotateX_i * RotateY_i * RotateZ_i)
\end{array}
\]\[ I = T^{-1} \]

\[Translate(x, y, z) = \left(\begin{array}{c c c c}
1 & 0 & 0 & x \\
0 & 1 & 0 & y \\
0 & 0 & 1 & z \\
0 & 0 & 0 & 1
\end{array}\right)\]
\[RotateX(\alpha) = \left(\begin{array}{c c c c}
1 & 0 & 0 & 0 \\
0 & cos(\alpha) & -sin(\alpha) & 0 \\
0 & sin(\alpha) & cos(\alpha) & 0 \\
0 & 0 & 0 & 1
\end{array}\right)\]
\[RotateY(\alpha) = \left(\begin{array}{c c c c}
cos(\alpha) & 0 & sin(\alpha) & 0 \\
0 & 1 & 0 & 0 \\
-sin(\alpha) & 0 & cos(\alpha) & 0 \\
0 & 0 & 0 & 1
\end{array}\right)\]
\[RotateZ(\alpha) = \left(\begin{array}{c c c c}
cos(\alpha) & -sin(\alpha) & 0 & 0 \\
sin(\alpha) & cos(\alpha) & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & 1
\end{array}\right)\]

We have written the intersection and normal calculations in the object's coordinate system instead of the world's coordinate system. It makes them easier to write. We use the transformation matrix to do object -> world and the inverse matrix to do world -> object.

\[
\left\{\begin{array}{l}
O_{world} = T * O_{object} \\
D_{world} = (T * D_{object}) - (T * 0_4)
\end{array}\right.
\]
\[
\left\{\begin{array}{l}
O_{object} = I * O_{world} \\
D_{object} = (I * D_{world}) - (I * 0_4)
\end{array}\right.
\]
\[0_4 = \left(\begin{array}{c} 0 \\
0 \\
0 \\
1
\end{array}\right)
\]


Bounding Box

The previous equations give us objects with infinite dimensions (except for the sphere) whereas objects in real life have finite dimensions. To simulate this, it is possible to provide two points that will form a bounding box around the object. On the intersection test, we are going to use the nearest point that is inside the bounding box.

This gives us the ability to do various objects such as mirrors, table surface and legs, light bubbles and even a Pokeball!


Light

An object is composed of an Intensity \(I_o\), a Color \(C_o\) and a Brightness \(B_o\). Each light has a Color \(C_l\) and there is an ambient color \(C_a\). Using all those properties, we can calculate the color of a point using the following formula:

\[
I_o * (C_o + B_o) * \left(C_a + \sum_{l}{(N \cdot D) * C_l}\right)
\]

Only the lights visible from the intersection point are used in the sum. In order to check this, we send a shadow ray from the intersection point to the light and see if it intersects any object.

The following images are examples to demonstrate the lights.


Textures

In order to put a texture on an object, we need to map a point \((x, y, z)\) in the object's coordinate system into a point \((x, y)\) in the texture's coordinate system. For planes, it is straightforward, we just the \(z\) coordinate (which is equal to zero anyway). For spheres, cylinders and cones it is a bit more involved. Here is the formula where \(w\) and \(h\) are the width and height of the texture.

\[
\begin{array}{c c}
\phi = acos(\frac{O'_y}{r}) & \theta = \frac{acos\left(\frac{O'_x}{r * sin(\phi)}\right)}{2\pi}
\end{array}
\]\[
\begin{array}{c c}
x = w * \left\{\begin{array}{l l} \theta & \text{if } O'_x < 0 \\
1 - \theta & \text{else}\end{array}\right. & y = h * \frac{\phi}{\pi}
\end{array}
\]

Once we have the texture coordinates, we can easily create a checkerboard or put a texture. We added options such as scaling and repeat in order to control how the texture is placed.


We also support the alpha mask in order to make a color from a texture transparent.

Progressive Rendering

Ray tracing is a slow technique. At first, I generated pixels line by line, but I found out that the first few lines do not hold much information.

Instead, what we want to do is to have a fast overview of the scene and then improve on the details. In order to do that, during the first iteration we are only generating 1 pixel for a 32x32 square. Then we generate 1 pixel for a 16x16 square and so on ... We generate the top-left pixel and fill all the unknown pixels with it.

In order not to regenerate pixels we already seen, I came up with a condition to know if a pixel has already been generated. \(size\) is the current square size (32, 16, ...).

\[\left\{\begin{array}{l}
x \equiv 0 \pmod{size * 2}\\
y \equiv 0 \pmod{size * 2}
\end{array}\right.
\]

Supersampling

Aliasing is a problem with Ray Tracing and we solve this issue using supersampling. Basically, we send more than one ray for each pixel. We have to chose representative points from a square. There are multiple strategies: in the middle, in a grid or random. Check the result of various combinations in the following image:

Perlin Noise

We can generate random textures using Perlin Noise. We can control several parameters such as \(octaves\), the number of basic noise, the initial scale \(f\) and the factor of contribution \(p\) of the high frequency noises.

\[ noise(x, y, z) = \sum_{i = 0}^{octaves}{p^i * PerlinNoise(\frac{2^i}{f}x, \frac{2^i}{f}y, \frac{2^i}{f}z)} \]


\[noise\] \[noise * 20 - \lfloor noise * 20 \rfloor\] \[\frac{cos(noise) + 1}{2}\]

As seen in the example, we can apply additional functions after the noise has been generated to make interesting effects.

Portal

Last but not least, Portals from the self-titled game. They are easy to reproduce in a Ray Tracer and yet, I haven't seen any done.

If a ray enters portal A, it will go out from portal B. It is trivial to implement it, it is just a coordinates system transformation. Like we did for world and object transformation, we do it between A and B using their transformation matrix.

\[
\left\{\begin{array}{l}
O_{a}' = T * O_{b} \\
D_{a}' = (T * D_{b}) - (T * 0_4)
\end{array}\right.
\]
\[
\left\{\begin{array}{l}
O_{b}' = T * O_{a} \\
D_{b}' = (T * D_{a}) - (T * 0_4)
\end{array}\right.
\]

Scene Editor

In order to create scenes more easily, we have defined a scene description language. We developed a basic CodeMirror syntax highlighting script. Just enter write your scene down and press Ray Trace :)

Diablofans.com needed a bit of love. It is really gratifying to be able to visually improve a website by an order of magnitude just by changing some colors and fixing broken layout :)

Here are some of the changes I made:

Post

Poll

Blizzquote

For a school project, I have to implement Simulated Annealing meta heuristic.

Thanks to many open source web tools, I've been able to quickly do the project and have a pretty display. CoffeeScript, Raphael, Highcharts, Three.js, Twitter Bootstrap, jQuery and Web Workers.

2D Demo

You have a shuffled grid and you have to find the original grid. The only operation available is to swap 2 random elements. The cost function is the distance of the point with their original neighbors.

3D Demo

On this one, we are given many functions and we have to find the global minimum. The challenge was to be able to display the evolution of the algorithm, as it traverses 200k points per second.

CoffeeScript Sexyness

I've written the project in CoffeeScript and I don't regret it. I find myself writing code a lot faster because I have a lot less to type. Most of the Javascript syntax is either shortened (function to ->) or optional (parenthesis, curly brackets ...) in CoffeeScript. There are also handy features such as splats, generators ...

Destructuring Assignment

worker.onmessage = (data: [id, rest...]) ->
	switch id
		when 'update'
			[cost, temperature, accepted, tried, data, force] = rest

Trimmed JSON

chart = new Highcharts.Chart
	chart:
		renderTo: 'container'
	yAxis: [
		title:
			text: 'Cost'
	]
	tooltip:
		formatter: ->
			this.series.name + ': ' + this.y

Report

Felix Abecassis wrote a report that explains everything :) It's in French, sorry!

Download PDF

MMO-Champion is a World of Warcraft news website. When a new patch is released, we want to show what has changed in the game (Post Example). An english summary of each spell change is hand written, but we want to show the exact tooltip changes.

Generate Tooltips

First, we use the database application to generate the tooltips in HTML form.

Epic
Binds when equipped
Chest
1669 Armor
+341 Intellect
+512 Stamina
Requires Level 85
Item Level 359
Equip: Improves critical strike rating by 205.
Equip: Increases your mastery rating by 241.
Epic
Binds when equipped
Chest
1669 Armor
+321 Intellect
+512 Stamina
Requires Level 85
Item Level 359
Equip: Improves critical strike rating by 205.
Equip: Increases your mastery rating by 221.

Tokenize

We are not going to do a full HTML diff which is really difficult. Instead, the trick is to parse the HTML and extract only text nodes. We split them by space to generate a token stream.

ChestguardofNature'sFuryBindswhenequippedChest1669Armor+341Intellect+512StaminaRequiresLevel85Equip:Improvescriticalstrikeratingby205.Equip:Increasesyourmasteryratingby241. ChestguardofNature'sFuryBindswhenequippedChest1669Armor+321Intellect+512StaminaRedSocketSocketBonus:+10HasteRatingRequiresLevel85Equip:Improvescriticalstrikeratingby205.Equip:Increasesyourmasteryratingby221.

Diff

Paul Butler SimpleDiff algorithm is used on the two token streams to label each token with old, new or both.

ChestguardofNature'sFuryBindswhenequippedChest1669Armor+341Intellect+512StaminaRequiresLevel85Equip:Improvescriticalstrikeratingby205.Equip:Increasesyourmasteryratingby241. ChestguardofNature'sFuryBindswhenequippedChest1669Armor+321Intellect+512StaminaRedSocketSocketBonus:+10HasteRatingRequiresLevel85Equip:Improvescriticalstrikeratingby205.Equip:Increasesyourmasteryratingby221.

Combine

We parse the HTML again. This time we pretty-print the HTML while traversing it. As we parse text nodes, we add <ins> tags where we need to. We just make sure to group contiguous insertions.

Epic
Binds when equipped
Chest
1669 Armor
+341 Intellect
+512 Stamina
Requires Level 85
Item Level 359
Equip: Improves critical strike rating by 205.
Equip: Increases your mastery rating by 241.
Epic
Binds when equipped
Chest
1669 Armor
+321 Intellect
+512 Stamina
Requires Level 85
Item Level 359
Equip: Improves critical strike rating by 205.
Equip: Increases your mastery rating by 221.

Text Diff

We would also like to get a text-based diff we can insert in a Patch Note. We combine both token streams into one.

Chestguard of Nature's Fury
Binds when equipped
Chest
1669 Armor
+341+321 Intellect
+512 Stamina
Red Socket
Socket Bonus: +10 Haste Rating
Requires Level 85
Equip: Improves critical strike rating by 205.
Equip: Increases your mastery rating by 241.221.

Chestguard of Nature's Fury Binds when equipped Chest 1669 Armor +341+321 Intellect +512 Stamina Red Socket Socket Bonus: +10 Haste Rating Requires Level 85 Equip: Improves critical strike rating by 205. Equip: Increases your mastery rating by 241.221.

However, the result isn't that readable. There is too much noise. We want to show only the information that has changed! In order to do that, we are going to keep only the lines that contain changes.

+341+321 Intellect
Red Socket
Socket Bonus: +10 Haste Rating
Equip: Increases your mastery rating by 241.221.

+341+321 Intellect Red Socket Socket Bonus: +10 Haste Rating Equip: Increases your mastery rating by 241.221.

And it works a lot better :)

Conclusion

This approach is working really well with the World of Warcraft tooltips. After many patches and hundreds of changes, I haven't seen any weird behavior. They were common before using this technique. The only downside: non textual changes such as icons or colors will be completly ignored.

During the course "Introduction to Model Checking" by Alexandre Duret-Lutz we've been assigned to create a Binary Decision Diagram library. Contrary to most people, I've been writing mine in Javascript instead of C++. Overall it is running slower but by an acceptable factor (around x5).

Display

I've written a BDD display using the graph library called Dracula which is built on-top of RaphaëlJS. The API of the lib is really neat but there are only 2 available node layout algorithms and none of them really fit my needs. I'd love to have the ones available in GraphViz.

In order to enter a formula, I've written a small parser that accepts most common binary operations. The little dice gives you some random formula. Also, on the left, you have all the evaluations that satisfy your formula.

Use Case

Binary Decision Diagram are used in Boolean Satisfiability Problem and Model Checking. As a benchmark example, we use the BDD to solve the 8-Queens problem.

A version using web-workers is available. However, using more than one worker will be slower as the cost of communication (through JSON serialization) is really high (hundreds of thousands nodes). You can also try to use a random ordering for the variables, but beware, the execution time varies a lot (up to x100 for the fastest/slowest)!

Conclusion

It was a really fun project to do. You can view the sources and probably use them as a base if you ever need to use a BDD in your life :P


Starcraft II has been a beta for a month and I've been actively working on the map making features. The Galaxy Map Editor has not been released yet however it is already possible to do edit the map files.

My goal is not to develop a map but to build a community around that editor. With Curse co-workers we have launched the website SC2Mapster.com.

In order to prepare the future We set up a documentation wiki. It is being filled by the community and currently contains the function listing, the xml files descriptions, a Galaxy language overview and much more ...

Here is a small part of the function listing:

Trigger

Triggers are function that are executed when an event occur. These functions allow the user to create new triggers from custom functions and bind them to different events.

This is a preview of the Starcraft II Galaxy Functions API.

The website also hosts many map making related projects such as maps, galaxy scripts or tilesets. In order to prove that we are able to start working, I've been working on a Tower Defense: Mapster TD.

Working on the World of Raids Guild Recruitment I needed to make sure the user was really member of the guild he claimed to represent. Since there is no official API and we don't want to ask for the user login and password, we had to find an other way.

The idea is to take advantage of the official Armory. When the user logs off the game, his character profile is updated on the website. To make sure the user is who he pretends to be, we are going to ask him to make a change on his character, wait for the armory to update and verify.

Since it's a tool that can be useful to anyone, we decided to make it a standalone service with an open API. If you have a World of Warcraft website and feel the need to verify that your users are genuine, this is your chance!

It has been in activity since the launch of the recruitment tool. So far 100 conflicts have been automatically resolved thanks to this tool.

Check out WoW Genuine.com.

World of Raids Guild Recruitment

Guild recruitment is a recurrent problem in World of Warcraft, many attempt have been made but none succedeed so far. After a brainstorming we decided that the following points were crucial.

  • The guild recruiter has to spend less time as possible to set-up a guild and maintain it.
  • The guild search must be easy and focus on what people expect from their guild.

With these points in mind, we had to find technical responses in order to make the World of Raids Guild Recruitment Tool.

  • What You See Is What You Get: The guild management interface is the final display, there is no intermediate step.
  • Tailored Widgets: About every widget has been heavily customized to fit the user need.
  • Automatic Save: Every time you make a change, it is automatically published and available to anyone!
  • Javascript Search: Having all the guilds fetched during the loading allows to have a complex filtering system instantly updated.

Guild Search

Looking for a guild should no more be a pain! You just have to tweak the filters and result appear sorted as you edit them! No more long page reload or even ajax requests. It is instant!

We focused hard on making filters one click away. We also took great care of the raid time filter, it is an important aspect of the guild choice that is too often avoided because of its complexity.

For more details on the optimizations made, see the post Guild Recruitement – Search Optimizations.

Guild Management

Our original goal was to be able to create a guild in less than a minute (yes, 60 seconds!) and we pretty much did it. The proof in the following video.

In order to achieve this, we opted for a Wysiwyg approach to remove the need of making two interfaces for both display and edition. Every widget has been tailored to fit the user needs. For example, as soon as you enter your name and realm, it automatically gathers your progression from the official website.

Presentation

Fooo is my first year school project written in Delphi. During 8 months, Vladimir Nachbaur, Alban Perillat-Merceroz, Felix Abecassis and I developed a game that mimics Warcraft III and achieved to be major of the promotion.

We tried to make no use of copyrighted Warcraft files, however, a large majority of custom models are based on Warcraft files at some point and use some of their textures. All the interface graphic, icons, models has been made by fans and we are using them with their approbation.

What's the game able to do :

  • Animated 3D Models
  • Interface in XML/Lua
  • Building & Unit creation
  • Group and Subgroup management
  • Group movement with formations
  • Ranged & Melee Attacks
  • Multiplayer over LAN or Internet
  • Ingame Chat
  • 2 Races: Treants and Rats
  • And much more ...

Demonstration Video

My work in the project

Interface

A RTS game is requiring a lot of user interaction, so it needs a complex interface. I decided to make an interface engine like the one used by World of Warcraft. The content is displayed through XML files and scripted with Lua. If you are not familiar with this, you can think the XML as HTML and Lua as Javascript.

The interface engine is able to do the following:

  • Supports Frame, Texture and FontString elements
  • Ability to draw Backgrounds and Borders from images
  • Mouse and Keyboard Interaction
  • Inheritance and Virtual Frames
  • Position through 2 Anchor points (element and its relative)

3D Engine

The 3D Engine is written on top of OpenGL. I've been confronted to two major problems. The first one is the Warcraft III models: there is really few documentation on them so i had to spent quite some time to reverse engineer them and figure out how animation were working.
The engine had to be optimized in many ways. At first, displaying one building was freezing the PC, now we are able to show more than 100 units and the game still runs smoothly.

The 3d engine is able to do the following:

  • Animated Warcraft III Models
  • Camera: Zoom and Rotation
  • 3D Picking
  • Frustum Culling
  • Vertex Array

Learn more

If you want to learn more, for each presentation we made a 30 page document (french) explaining in detail the progression. You can read them at hgf.fooo.fr.