Skip to content

203. Castle 3D – Tower exterior

March 14, 2015

I’ll start my castle with something I know will be difficult (mainly to see if this project is possible) – towers.

Towers are basically thick cylinders with

  • large stone texturing
  • arrow slits
  • platform at top and crenellations ( the “teeth” on top)
  • a door at back
  • internal spiral stairs so you can climb up, look out the arrow slits, and walk out on the top

I can think of several challenges straight away

  • drawing a cylinder
  • making holes in it for arrow slits and doors
  • making crenellations
  • spiral stairs
  • making the walls look thick – rather than one pixel thin!

Drawing a cylinder

Drawing a cylinder can be done with LoopSpace’s shapes library. However, I want a lot of control over my cylinder, eg I want to punch holes in it.

I’m going to make a very simple cylinder with just 8 faces, and use a shader to make it look rounded. I can make the cylinder without any trigonometry whatsoever, like this.

  1. define four points round the base of the cylinder at 90 degree angles. So if my cylinder has radius r, I create points at (0,0,r), (0,r,0), (0,0,-r) and (0,-r,0).
  2. Then I average each pair of points to get the midpoint m. This is on a straight line between the two points, and lies within the circle they are on, so to push m out to lie on the circle, I adjust with m = m * r / m:len()
  3. Now I have 8 points on the circle at the base of the cylinder. The eight points at the top are the same with a higher y value, so now I can create 16 triangles, and my cylinder is done with just 48 vertices.

Punching holes in the tower

This is impossible of course. Once you’ve drawn a tower, you can’t rub out parts of it. You have to avoid drawing anything in the holes.

As you can imagine, it is messy building a mesh which has holes in it. It is even harder when the mesh is a cylinder!

So we’ll cheat, using a shader.

Shaders are very good for producing special effects. My castle shader is going to be quite busy, I expect, but for now, I want to use it to cut holes in my tower. I can do this by using a colour mask.

Using a mask

I calculate I will need an image 250 wide by 200 tall for my tower. So I use a paint program (I use paint.net but any good one will do) to create an image 4x this size (mainly so I will see enough detail when close up).

I tile the image manually with a nice block texture from the internet (note that if I wasn’t cutting holes, I would have used my shader to do the tiling [link], which I will do with the castle walls, the floor of the scene and other large areas).

Then I draw in arrow slits and a door at the bottom, using a special colour. My shader will test the value of each pixel colour, and if it is this special colour, it will not draw anything, leaving a hole. I need to choose it carefully, both to be a colour that I won’t use normally, and also, because shader colours go from 0 to 1, not 0 to 255,  I need to choose a number that is an exact fraction. I chose a colour of (51,102,153), since 51 divides exactly into 255. I will start by only testing if the red pixel = 0.2 (51/255), but if I need to, I can test the others as well.

So here is a closeup of part of my texture, with an arrow slit marked.

This is the fragment shader code that does the magic

//col is the texture colour of this pixel
if (col.r==0.2) discard; //draw nothing

And this shows the result. You can see through the arrow slit to the inside.

However, it is very obvious that the wall is one pixel thick, and that will be a problem. I don’t have a solution yet.

 Drawing the top of the tower and crenellations

I can make a floor for the top of the tower using the vertices I used to create the tower.

For crenellations, I can create alternating large and small stone blocks and position them round the edges. Hopefully, it won’t be too obvious that they aren’t round, and hopefully, they will look ok from a distance, and close up.

 Drawing the interior

The interior of the tower is clearly going to be complicated. I have a spiral staircase for a start. (For interest – they were cleverly designed to spiral clockwise, so climbing attackers couldn’t use their right arms freely, but defenders could, and steps were deliberately uneven to make attackers lose their footing).

All this drawing is going to slow me down, so maybe the best approach to start with is to simply make the arrow slits black from the outside – which is what you see when you look at pictures of a castle – and put a door on the bottom of the castle. Then I don’t need to draw the inside unless I actually go into it. When I am inside, I will need to cut holes for the arrow slits, and I still have the wall thickness problem, but I’ll leave that for now.

So I’ll go back and make my arrow slits pure black, and find a door to put at the bottom of the tower, and my shader isn’t needed for now, except maybe for lighting, which I’ll come to later.

So this is my first checkpoint.

Adding crenellations

Those are the toothy blocks at the top of the tower.

I tried adding four per tower, ie one tall block for every second pair of vertices, but that is not enough. I need at least 8, ie one short and one tall block per pair of vertices. That requires something like an extra 8 rectangles to be added per vertex pairs, or over 60 additional rectangles.

That is annoying when my whole tower so far only required 8 rectangles – I have to increase its complexity 8 times just to add some little blocks at the top!

I position each block so its outer edge is on the (straight) line joining its pair of vertices, so it is a nice fit. The shader will make the block look rounded, like the rest of the tower (I’ll discuss this later).

A little trick for finding a parallel offset

There is one useful trick here.

We’re looking down on the top of the tower from above. Suppose I’m adding the block between v1 and v2. I want it to be the shape of the blue rectangle. Obviously I know the points v1 and v2, but I need to create the line marked in red for the opposite side of the block, w pixels away. How do I find the position of the two endpoints of that line, when it is at an angle?

I could use trigonometry, but there is a simpler way.

If I could figure out what to add to v1 or v2 to move them 1 pixel in the direction of the arrow, then I could multiply that vector by w, and add it to v1 and v2 to get the end points I need.

The arrow is at right angles to the line between v1 and v2, ie rotated 90 degrees. This is where the trick comes in. If you have a point (x,y) on a 2D graph, and you rotate it 90 degrees (around the origin), the point is now at (-y,x). Try it and see.

In this case, we are working with x and z, rather than x and y, but the same formula applies.

I can calculate the direction of the line between v1 and v2 by subtracting them, say v12 = v2 – v1, which gives me a vec3(x,0,z). Note that y=0 because v1 and v2 have the same height.

If I rotate 90 degrees, the direction is vec3(-z,0,x). This direction points along the arrow in the diagram above, and I just need to make it the right length. Let’s “normalise” the direction to make it length 1, then multiply by w. The complete formula is then

a = vec3( -(v2.z-v1.z,0), 0, v2.x-v1.x):normalize() * w

and if I add a to v1 and v2, I’ll get the end points of the red line above.

I won’t bore you with the code for the actual crenellation faces. It’s just very tedious and slow.

Here is the result. I threw a wall in just to give it a castle “feel”.

You can see my shader does a good job of making the tower and the blocks on top look rounded, even though the tower only has 8 facets.

I can see some little things I’ll need to fix. The crenellation textures are streaky, and the tower textures have light and dark patches even though I haven’t added lighting yet.

I also need to add crenellations and a walking platform to the wall, clean up my wall code which is a complete mess, and add more walls and towers to complete the outside. Well, not quite complete. I need a gatehouse with a front door, portcullis and so on. A drawbridge would be nice too, but we’ll see.

Oh, and I forgot about the inside of the tower. There’s a lot of work there, too.

Advertisement
Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: