Tutorial: How to create a nailboard – part 1 (creating the nails)

[toc]
In this Tutorialseries i’m going to show you how to create a nailboard, like in my animation keep on nailin’ and load a picture to it, so that it looks like this:
A nailboard example.
There will be two parts, one in which you will learn how to actually create the nailboard and one with the aim of loading a picture to it. Maybe there will be a third part about loading movies to it, but i’m not sure about this.

Introduction

Things that i assume:

  • you use an ubuntu (maybe i add windows later on, i’m not sure about this)
  • you’re have installed and are familiar with blender 2.5,
  • you know how to build a nail in blender (drawing a curve, convert it to mesh and spin it)
    a curve for the nail object
  • and have done it before starting the programming (important: give the object the name “nail”) or download the file at the end of the tutorial
  • you know what the programming language python is
  • you have installed the python-image package:
    • if you’re not sure try
      import Image

      at the python console

    • if you get an error type
      sudo apt-get install python-imaging

      to install it from a shell

    • if you get no error, the package is installed and works

Ok, let us begin! I divided the tutorial and the program into two parts after the old principle “divide and conquer”. The first thing to do is the creation of a nailboard where every single nail could get a several height value. Than one has only to load a image and convert the colour values into height values.

My first idea was the array modifier:
the array modifier
But it doesn’t support the generation of several objects with individual names, so i decided to write a script for this task (it was clear that the second part will need a script, so this choice was easy ūüėČ ). The complete script and a .blend file of my hires nail are at the end of this tutorial.

The basic idea

The underlying idea is to name the several nails with the base name followed by the coordinates in x and y of our array. I decided to separate the parts of the names with a underscore, so that it’s clearer that the name is a string. In this example the nail with the coordinates x=1 and y=0 is selected:
the naming conventions
The described script will generate a nailboard array of the size 102×76, so that we can easily scale down a 1024×768 image by scaling factor 10% and load it to our nailbaord.

Let us now go through the script! I will go topically from top to bottom, cause i like it more than asking myself “why i’m doing this right now?”.

The main function

The main function of the generation script is “createField”. At first i will give it to you and than discuss the details:

import bpy

scn  = bpy.context.scene
nail = bpy.data.objects["nail"]

...

def createField( object, x_start, width, y_start, depth, step ):
  unselectAll()
  object.select = 1
  moveToLayer( object, 0 )

  str_base = object.name
  str_sep = '_'

  y_cnt = y_start
  for y in floatRange( y_start * step, depth, step ):
    x_cnt = x_start
    for x in floatRange( x_start * step, width, step ):
      print( x_cnt,y_cnt )
      bpy.ops.object.duplicate( linked=True )

      name = str_base + str_sep + str(x_cnt) + str_sep + str(y_cnt)
      setObjectValues( scn.objects.active, name, x, y )

      x_cnt += 1
    y_cnt += 1
  moveToLayer( object, 1 )

createField( nail, 0, 102, 0, 76, 0.5 )

If you want to type it or just want to copy and paste it to your own file, than just open a “Text Editor” and fill it with the script parts. The later declared functions belong into the part where the “…” are!
a Text Editor

Let’s go into the details of this snippet. At first we look at the prefix:

import bpy

scn  = bpy.context.scene
nail = bpy.data.objects["nail"]

The code does the following:

  • with
    import bpy

    the blender library functionality is included into the python script,

  • scn  = bpy.context.scene

    gives us a shortcut to the scene object and

  • nail = bpy.data.objects["nail"]

    grabs the object with the name “nails”.

The function “createField” takes the following parameters:

  • a pointer to the object, which should be arrayed, called “object”,
  • starting points “x_start” and “y_start” where the naming of the nails should start,
  • dimensions “width” and “depth”, which declare how big the generated array will be, and
  • a value “step”, which defines how big the distance between every two neighbored nails is.

The first thing the function “createField” does, is to call a function “unselectAll”. Like the name says it unselects all objects of the scene. The code to do this is here (if you copy and paste it in your own file, put it above the function “createField”):

def unselectAll():
    bpy.ops.object.select_all( action = 'DESELECT' )

It walks through all objects and apllies the action “DESELECT” to each one.

The next two lines select the nailmesh and move it to the layer zero. I added this, cause the last step the function “createField” does, is to move the nail to the layer 1, so that the original object isn’t overlaying with the new nail at the first position.

  object.select = 1
  moveToLayer( object, 0 )

The function “moveToLayer” looks like this:

def moveToLayer( object, layer ):
    layers = [False]*20
    layers[layer] = True
    object.layers = layers

In blender python the layers, where an object is visible, are organized in an bool array. Cause blender has 20 layers the field has the length 20. All other layers are set to False and our wished layer gets the value True.

After this the distinct naming of every nail is prepared:

  str_base = object.name
  str_sep = '_'

We decide to use the name “nail” of our nail object as base and define the separator ‘_’.

The main loop

Having done all this arrangements we can go into the two-layered loop. It generates the two-dimensional array of nails. Therefore the outer loop walks through the y-axis and the inner loop through the x-axis. They both use the function “floatRange” to generate the values they traverse:

def floatRange( start, n, step ):
    val = start
    list = []
    for i in range(0,n):
        list.append( val )
        val += step
    return list

This function is a self written equivalent to the normal python function “range” and delivers a float range of values:

>>> floatRange(0,5,0.25)
[0, 0.25, 0.5, 0.75, 1.0]

The body of the inner loop looks like this:

  print( x_cnt,y_cnt )
  bpy.ops.object.duplicate( linked=True )
     
  name = str_base + str_sep + str(x_cnt) + str_sep + str(y_cnt)
  setObjectValues( scn.objects.active, name, x, y )

It does the following things:

  • it prints the actual generated nail coordinates of our nailboard (x,y),
  • then copies the nail as an linked object (important, so that every nail changes if you realize that the nailboard is getting to big for your architecture and saves much of disk space),
  • creates the name for the nail and finally
  • sets the calculated values to the actual generated nail in the function “setObjectValues”.

The last thing we will watch is the function “setObjectValues”:

def setObjectValues( object, name, x, y ):
    object.name = name
    object.location.x = x
    object.location.y = y

Its parameters are a pointer to the given object (our original nail), the name of the actual generated nail and the real coordinates for the nail.

The last step

After typing the whole text to your blender Text Editor or just copy pasting it, i recommend that you save your work and start it in a blender with an open console. Therefore open a console and type

blender

or move to your blender directory and call it.

Having done this, position the mouse cursor over the Text Editor and hit Alt+p. The generation takes a while and if you sit on an older computer you maybe have to simplify the geometry of the mesh. For the animation i did it too, cause it needed too much time for every frame. To watch the progress, lokk into the console window. If you want to stop the script, go to the console and hit Alt+C. My experience is, the more nails the blend file has, the slower every new nail gets created. It could take real long time – lean back and let it work :)!

Conclusion

After walking through the genration script i hope no questions are open and you understand what we’ve done here. If something is unclear, please leave a comment. The next part of the tutorial series will discover the loading of an image to our newly generated nailboard. The only things you have to do are the modelling of the rest of the scene and the nailboard (the glass, the feet and the bottom).

And know, as promised, the downloads for the lazy ones:

rgb colour selection system

In this video i show you a 3D-colourselection-tool i programmed for a project of my study of design informatics.
It is written in C++ using the Coin3D former OpenInventor library.

There are two opportunities to interact with the system:

  1. rotate a RGB-Colourcube,
  2. translate a cutplane (to influence the cutface – shown on the right) and
  3. pick a colour on the cutface.

I hope you like it.

The rgb colour picking system.