## Learning and Applying Mathematics using Computing

### Another Brick In The Wall

In our last post, we drew a 3D view of being in a maze-like grid of blocks. But all the walls were of single uniform colour, which is quite dull. The early 3D games that used our 3D technique, raycasting, almost immediately switched to using images for the walls rather than plain colours. These images were referred to as textures, and the technique for drawing them is known as texture mapping.

Texture mapping with raycasting is actually very simple. The idea is that each wall-block being drawn has an image on it. While drawing the wall-block pixel-by-pixel in 3D, texture mapping amounts to finding the corresponding pixel in the source image to use. We can label the face of each of the blocks in the world as having coordinates somewhere between (0, 0) and (1, 1):

The challenge is then for a given pixel, such as the red circle in the picture above, to find out which texture coordinates to use. These coordinates are typically labelled (u, v) to avoid confusion with other (x, y) coordinates. In raycasting, it’s quite easy to determine the (u, v). The u component is a matter of recording where exactly on the wall the ray hit. We already record the x and y coordinate of impact, and we know which face we hit. The u coordinate is just the fractional part of the appropriate x or y coordinate. If the ray hits the horizontal face of a block at (x, y) = 3.45, 6.00 then the u coordinate is 0.45.

As for the v coordinate: that is the relative height within the block we are currently drawing. In each column, we already know how tall the block appears. So the v coordinate is just a proportion of that total block height as we draw downwards.

Once we know the (u, v) coordinates, we just pick out the appropriate pixel from our texture image. If our texture is 256 by 256, and our (u, v) = (0.45, 0.29), then we use the pixel at (115, 74). (This is called nearest-neighbour texture mapping, and is fastest, but it can look a bit “jagged”. Most games now use some form of linear texture mapping that looks smoother)

Here’s the code:

```            for (int wallY = 0; wallY <= 2 * height; wallY++)
{
double v = (double)wallY / (double)(2 * height);
double u = r.getImageOffset();

GreenfootImage texture = ((RaycastingWorld)getWorld()).getTextureFor(r.getX(), r.getY());

Color c = texture.getColorAt((int)(u * (texture.getWidth() - 1)), (int)(v * (texture.getHeight() - 1)));

int y = img.getHeight()/2 - height + wallY;
if (y >= 0 && y < img.getHeight())
{
img.setColorAt((int)column, y, c);
}
}
```

Here’s the texture:

And here’s a screenshot of what it looks like when used for texture-mapping: