Adding Meshes

In this tutorial I’ll show you how to make a script that will let you actually add meshes to blender. We will create a little side panel that will have a basic setting, and a button to make the object. What you'll end up making

What you’ll end up making.

To start with, lets import all of the modules we need to get python working nicely with blender:

import bpy
import math
import mathutils
  • Bpy is short for “Blender Python”, and it contains all of the modules we need to interface with Blender.
  • Math is fairly self explanatory, it provides more advanced maths functions that you may need to use in your script.
  • MathUtils is a 3D modeling based set of math tools, and comes with Blender.

Ok, now we have all of the modules that we need, we have to give blender some information about the script we’re giving it. To do this, we declare a dictionary called bl_info, with some items that blender can use. It would probably be easiest to copy and paste mine, and change the names to whatever you’re using.

bl_info = {
    "name": "Object maker",
    "author": "Olly F-G",
    "version": (1, 0, 0),
    "blender": (2, 57, 0),
    "location": "View3D > Add > Mesh > Olly's object ",
    "description": "Adds an object making panel",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "",
    "category": "Add Mesh"}

This basically tells blender where it should put our addon in the menu. Now if you place this file in your blender addons folder (.blender/VERSION/scripts/addons on linux), fire up blender, switch to user preferences (the little button to the bottom right of the 3D view, then select ‘User Preferences’) and go to the addons tab, searching for your name, will bring up your script!

Unfortunately, blender can detect that your script isn’t finished yet, so you can’t check the checkbox yet.

So, next up, we need to tell blender how we want to interact with our script. In this case, I want to add a panel to the left hand bar with our script and settings in it. To do this, we need to create a new class called ObjectMakerPanel, we do this as follows.

class ObjectMakerPanel(bpy.types.Panel):
    # Tell blender where and when we want to see our panel.
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_context = "objectmode"
    bl_label = "Add object"

The bl_space_type variable defines when this panel will be seen, so we want it when we are looking at the 3D view. The bl_region_type simply tells blender that this is a tool, so you shouldn’t really ever need to change this as far as I know. bl_context defines more precisely when you want to see this. If you wanted the panel to only show up in edit mode, you would change this to “editmode”, but object mode is fine for this script. bl_label is the little label that is shown at the top of the panel, so you can change this to whatever you would like to call the panel.

Finally, we should tell the panel how to draw itself, which is pretty simple.

def draw(self, context):
    TheCol = self.layout.column(align = True)
    TheCol.prop(context.scene, "size")
    TheCol.operator("mesh.make_object", text = "Add object")

TheCol is a variable that defines the layout of the panel, in this case a column, with all the elements aligned. Then we add a property called “size”, this is our slider to define how big we want our new object to be. Next an operator, this is the big button that actually runs the mesh-creating part of our script, so we tell it the id of the function it will execute (mesh.make_object, which will be defined later), and the text on the button, “Add object”. And that’s it, you’ve created the panel! But we’re not done yet, we need to define the function that’s executed when we press the “Add object” button.

To do this, we declare a class that can be called anything you like, and then we give it a variable called bl_idname, which we set to mesh.make_object, so that our button calls it. We also set two more variables, one called bl_label, which is just another description of what this function does, and one called bl_options, which defines what options should be available to do on creation of this object. We’ll stick with letting people undo for now.

class MakeObject(bpy.types.Operator):
    bl_idname = "mesh.make_object"
    bl_label = "Add object"
    bl_options = {"UNDO"}

Now comes the really fun bit, where we can start actually making the object that we’re adding to the scene! Create a function inside the new class called invoke, which accepts self, context, and event.

def invoke(self, context, event) :
    # See what our user put in for the size of the object.
    size = context.scene.size

Now there are many ways of creating objects in blender, but most of them will simply add a cube. The way I will show you allows you to create any shape you want, and although it can be clunky to use, I find it to be the best way to construct meshes. The function we will be using is called NewMesh.from_pydata(), wich accepts a list of verticies, and then a list of edges and a list of faces. The function will only accept either the list of edges or faces, but not both so we won’t bother defining edges, and just give it the faces.

Let’s define the list of verticies and faces we’ll be using:

vList=[]
fList=[]

Verticies are defined by a tuple with three values, an X value, a Y value and a Z value. In this example I’ll make a simple plane object, so we’ll be using the following four base verticies - one ni each corner.

v1=(-1,1,0)
v2=(1,1,0)
v3=(-1,1,0)
v4=(-1,-1,0)

But wait! Before making a face, we should multiply each point of each vertex by the size the user has selected, so that the shape that’s generated is the size the user wants!

v1=(-1*size,1*size,0)
v2=(1*size,1*size,0)
v3=(1*size,-1*size,0)
v4=(-1*size,-1*size,0)

Now add these verticies to vList.

vList.update([v1,v2,v3,v4])

Onto the faces. Faces are defined as a tuple of three or four vertex indexes. What this means is that for each vertex that we want to be part of the face, we need to find where it is in vList. We do that for every vertex and then put that list in fList. In this case, we just have four verticies, so it’s easy enough to define a face.

fList.append((0,1,2,3))

0,1,2 and 3 are the indexes of vList that the verticies are stored. It’s worth noting that verticies are added in a clockwise direction to the face, so if you get the order wrong things will end up looking a little funny.

Now we have to make an empty object varaible called newMesh that will become our plane when we call NewMesh.from_pydata().

NewMesh = bpy.data.meshes.new("Object")

Great, now let’s pass these lists into NewMesh.from_pydata().

NewMesh.from_pydata(vList, (), fList)

Awesome! Now we have a mesh, we have to update NewMesh.

NewMesh.update()

Now, as you may know, a mesh in blender is not an object, so we can’t see it or render it and it’s not a lot of use. But, we can create an object out of this mesh using the following line.

NewObj = bpy.data.objects.new("Object", NewMesh)

Now we have a new object with our mesh data, called “Object”. Next we link this new object to the scene so we can see it:

context.scene.objects.link(NewObj)

Finally, we deselect everything and select the new object we just made, setting it as active.

bpy.ops.object.select_all(action = "DESELECT")
NewObj.select = True
context.scene.objects.active = NewObj

That’s it for adding the object, we just need to return {"FINISHED"}, so blender knows we’re done.

return {"FINISHED"}

Ok. Panel drawn, mesh created, object added to the scene. You would think that’s it wouldn’t you? Well you’d be wrong. There’s a little bit to go yet! You may have noticed that with the current file, you still can’t check the checkbox to enable it in blender. When you check that checkbox, and the script is loaded, it’s called registering it, and when you uncheck it, it’s called unregistering it. We still haven’t told blender how to do this, so we need to set out two functions:

def register():

and

def unregister():

Inside register, we must first register our class to make the object, so:

bpy.utils.register_class(MakeObject)

Then we need to tell blender about our size setting, so that it knows how to draw it and what limits it should have. To do this, copy in the following (and feel free to play with the options!):

bpy.types.Scene.size = bpy.props.IntProperty \
    (
        name = "Size",
        description = "How big you would like the object to be.",
        default = 1,
        min = 1,
        max = 200,
    )
bpy.utils.register_class(ObjectMakerPanel)

Great! Now, onto unregistering:

def unregister():

We unregister the ObjectMaker in much the same way as we registered it:

bpy.utils.unregister_class(MakeObject)

We delete the size setting variable:

del bpy.types.Scene.size

And then we can unregister the ObjectMakerPanel.

bpy.utils.unregister_class(ObjectMakerPanel)

Great, but you may notice that these functions aren’t actually run anywhere, so we have to add the following:

python if __name__ == "__main__": register()

Great! Fire up blender and enable the script, and when you return to the 3D view window, you should see a brand new panel on the left panel that says “Create object”. Clicking the button should create a plane at the cursor, nice! Now you can try playing with the size variable and you’ll see that it will change the size of the plane you generate.

Extra things to try:

  1. Instead of just having a size setting, make two, a width and a height. The result of this challenge
  2. Make a panel with two buttons, one that adds a plane, and the other that adds a triangle. The result of this challenge
  3. Combine the two above! You’ll have to do some maths to make the triangle scale nicely.

Tags: BlenderPythonTutorialSoftware