Nanoblocks

Nanoblocks are a bit of a phenomenon out in Japan at the moment, and they’re starting to get some traction in the UK. Nanoblocks are like lego blocks, but half the size, which allows you to build very detailed models. Have a look on amazon if you’re interested, I’ve already got the space shuttle and the empire state building. About 7-8 inches high, 600-800 bricks each.

Anyway, while building these models I started thinking that it’d be easy to construct the bricks out of procedural geometry, and within a day I’d got the big nanoblock duck rendering. This article’s going to go through the basics of building a nanoblock construction set in Wooscript, and if you’d like a copy of the full library I’ve implemented, it’ll be in the next distribution released sometime next week.

To start off lets build a basic 2×1 nanoblock. To make model building easier I’m going to scale the box as one unit big around the base. This means that whole numbers can be used to place each nanoblock. However, nanoblocks aren’t as tall as they are wide. By messing about with a few nanoblocks by eye, I reckon the height is ~78% of the width. This means the basic cube for a 2×1 nanoblock will be 2 x 0.78 x 1.

diff = vec(1, 0.5, 0)
scale = vec(2, 0.78, 1)
box

The next question we have is where to put this box. If I’m building a shape out of nanoblocks then I want a standardised way to place each block. A simple approach is to use the centre of the bottom left square as 0,0. So for a 2×1 block we need to move the box half a unit to the right.

i.e.

diff = vec(1, 0.5, 0)
pos += vec(0.5,0,0)
scale = vec(2, 0.78, 1)
box

Next up we’ll be needing some little cylinders to go along the top of the block. These are a very specific size for nanoblocks, and from a bit of messing around I’ve decided the appropriate size of a “nub” is vec(0.6, 0.39, 0.6). These will be added on top of the existing box. Lets define a new “nanocyl” rule for creating the little nub, and then we’ll stick two on top of the existing box. Note that we’ll use two braces around each rule to make them side-effect free. i.e. the program position won’t be changed by adding a nanoblock to a scene.

rule main {
diff = vec(1, 0.5, 0)
nanobox
}

rule nanobox {
{ pos += vec(0.5,0,0)
scale = vec(2, 0.78, 1)
box
pos.y += 1
scale = vec(1, 1, 1)
pos -= vec(0.5, 0,0)
nanocyl
pos.x += 1
nanocyl }
}

rule nanocyl {
{ scale = vec(0.6, 0.39, 0.6)
cylinder }
}
nanoblock render

Basic 2×1 building block

Brilliant. So we’ve got a 2×1 nanoblock that we can build objects out of, and to build a little strip of these objects all we need to do is move the pos variable between each brick and we’re away. Let’s start by making a little wall out of 5 blocks, 3 underneath, 2 on the top.

rule main {
pos.x -= 3
diff = vec(1, 0.5, 0)
nanobox
pos.x += 2
nanobox
pos.x += 2
nanobox
pos += vec(-3, 0.78, 0)
nanobox
pos.x += 2
nanobox
}
nanoblock wall with 5 blocks

nanoblock wall with 5 blocks

But hold on, this doesn’t really look like a wall of bricks. It just looks like a solid cube of orange stuff with a few cylinders on top. To make this look like it’s made of little blocks we need to add some gaps and a bit of randomness. Feel free to experiment with this, but for me I like adding some basic gaps of ~0.03 around the brick, and 0.005 between the rows. I also add a small amount of random rotation around the y axis to simulate amateur craftmanship.

Now we’re starting to get something that looks more like a wall…

Realistic wall made of blocks

Realistic wall made of blocks

So a little bit of randomness and we can start making passable models out of nanoblocks, but there are quite a few different sizes of nanoblock that standard models are made from. The easiest approach here is to take the nanoblock rule above and modify it to build 1×2, 4×2, 8×2, 2×8, etc. blocks. You’ll get bored of that pretty quickly though.

Instead, I’ve decided to build a single method that’s capable of building any size nanoblock. To do this you need to make use of the temporary vectors (v0,v1,etc.) to store the size of the block you’d like to build.

So for example, let’s build the base of the block using the size encoded in v0.

pos.z += v0.x/2
scale = vec(v0.x, 0.78, v0.y)
box

Now we need to add the right number of nubs on top. To do this we reuse the nanocyl rule from earlier, but generate a grid of nubs using a few repeat rules. Note the delicate use of additional curly braces to ensure state is reset following each repeat loop.

repeat(v0.x)
{
 { repeat(v0.y) {
  nanocyl
  pos.z+= 1
  } }
 pos.x+=1
}

And now we instantiate the method to build a 2×1 block using an explicit rule type. I’ve also added a few offset vectors to get everything to line up correctly.

rule nano2x1 {
v0 = vec(2, 1, 0) nanoblock
}

rule nanoblock {
{ pos.x += v0.x * 0.5 - 0.5
pos.z += v0.y * 0.5 - 0.5
scale = vec(v0.x - 0.03, 0.775, v0.y - 0.03)
box

pos.y += 1
scale = vec(1,1,1)
pos.x -= v0.x * 0.5 - 0.5
pos.z -= v0.y * 0.5 - 0.5

repeat(v0.x)
{
 { repeat(v0.y) {
  nanocyl
  pos.z+= 1
  } }
 pos.x+=1
}

} }

And now we’re back to simple 2×1 blocks, but we can also easily build a 10×10 block like this…

rule nano10x10 {
v0 = vec(10, 10, 0) nanoblock
}
10x10 and 2x1

10×10 and 2×1

There are a couple of other special brick types that need rules like the 1×1 cylinder, and the 2×1 single brick with a nub halfway down the box. I’ve added these rules to the nanoblock library too.

Finally there’s the issue of instantiating lots of these bricks to build models. So far we’ve talked about adding nanoblocks by setting the position for each brick.

pos = vec(1,0,1) nano10x10

The problem with this is that if I instantiate this brick by moving position, the position set moves everything back to the same location in the world.

So what I really need to do is add that vector, and then delete it again after adding the nanoblock. Something like this

pos += vec(1, 0, 1) nano10x10 pos -= vec(1, 0, 1)

This is going to get very tedious for large numbers of blocks, so I’m going to use another temporary vector to store the position, and then extend the generic nanoblock rule to add the position, and then remove it. This way the block can be instanced using this.

v1 = vec(1, 1, 0) nano10x10

Making it easy to instantiate large objects. So what did I choose to build first? Well the duck nanoblock models are pretty cool, so lets start with the adult duck.

nanoblock duck

nanoblock duck

And now for the baby duck (aww)…

Baby nanoblock duck

Baby nanoblock duck

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

Spam Protection *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>