Class: Mesh I

Objectives

a In an object-oriented world, parts of the model are mapped into classes. This has many advantages and the most important rules are shown here. Here is a complex example of how to create a basic shape, which does not exist in Blender. It is a pyramid.

Instructions

Tasks:
  1. Repeat the sub-steps shown here to create a class until you have a working version.
  2. Create a class of its own »primitive«, eg. a wedge or the base form of a hex key.
  3. Add a material to the class, which is given to the new object.

Design data for a mesh

We start with the ground of a pyramid. The first step is defining the vertices an there location in a 3D scene. After that, then for each area, the index values ​​of each surface section summarizes (a face is defined). The latter determines whether an area is closed or remains open, if it is not defined.

def pyramid_values():
    """
    This function takes inputs and returns vertex and face arrays.
    no actual mesh data creation is done here.
    """
    verts =  [(-1, +1, 0),
              (+1, +1, 0),
              (+1, -1, 0),
              (-1, -1, 0)]

    faces = [(0, 1, 2, 3),]

 return verts, faces

The coordinates of each point are given by the focus of our future pyramid. The whole thing still possible in a clockwise sense.

Todo

Picture with coordinats

Class: AddPyramid

After the keyword class follows a self-selected class name AddPyramid.

As in the example with the simple class, our class inherits from a class in Blender: bpy.types.Operator. We need tree variable, for the correkt integration of our new class into Blender, its menues or lists for selection.



class AddPyramid(bpy.types.Operator):
    """Add a simple pyramid mesh"""

    bl_idname = "mesh.primitive_pyramid_add"
    bl_label = "Add Pyramid"
    bl_options = {'REGISTER', 'UNDO'}

Properties

Also tree parameters are nessesary to place a new pyramid in a 3D-World.

    """Add a simple pyramid mesh"""

    bl_idname = "mesh.primitive_pyramid_add"
    bl_label = "Add Pyramid"
    bl_options = {'REGISTER', 'UNDO'}

Method: execute

The methode execute is using the coordintate given by the function pyramid_values(). The values are transfered to locale variables: verts_loc and faces.

Now two new objects are created mit the operator new().

  • one Mesh for the coordinates
  • one bmesh for ...

Todo

bmash description

    def execute(self, context):

        verts_loc, faces = pyramid_values()
        mesh = bpy.data.meshes.new("Pyramid")
        bm = bmesh.new()

Coordinates second part

With two for loops the coordintes are added to the new objects.

        for v_co in verts_loc:
            bm.verts.new(v_co)

        for f_idx in faces:
            bm.faces.new([bm.verts[i] for i in f_idx])

Create objects

Afte the preparation, a new object can be created and placed on a given location.

        bm.to_mesh(mesh)
        mesh.update()
        self.location = (0, 0, 0)

Display the object

With object_utils the object gets visible in a szene. If all works fine, the return value {‘FINISHED’} is given back.

        # set the new object into the szene
        from bpy_extras import object_utils
        object_utils.object_data_add(context, mesh, operator=self)

        return {'FINISHED'}

Register/Unregister

Blender needs a registration and unregristreation command for the new class.

def register():
    bpy.utils.register_class(AddPyramid)


def unregister():
    bpy.utils.unregister_class(AddPyramid)

Test run

Lets test the creation of a new pyramid, so far we only have the base.

if __name__ == "__main__":
    register()

    # create a instanz of a pyramid
    bpy.ops.mesh.primitive_pyramid_add()

With the next step, we will finish the pyramid.

The code for the class

import bpy
import bmesh
from bpy.props import BoolProperty, FloatVectorProperty


def pyramid_values():
    """
    This function takes inputs and returns vertex and face arrays.
    no actual mesh data creation is done here.
    """
    verts = [(-1, +1, 0),
             (+1, +1, 0),
             (+1, -1, 0),
             (-1, -1, 0)]

    faces = [(0, 1, 2, 3), ]
    return verts, faces


class AddPyramid(bpy.types.Operator):
    """Add a simple pyramid mesh"""

    bl_idname = "mesh.primitive_pyramid_add"
    bl_label = "Add Pyramid"
    bl_options = {'REGISTER', 'UNDO'}

    # generic transform props
    view_align = BoolProperty(name="Align to View",
                              default=False)
    location = FloatVectorProperty(name="Location",
                                   subtype='TRANSLATION')
    rotation = FloatVectorProperty(name="Rotation",
                                   subtype='EULER')

    def execute(self, context):

        verts_loc, faces = pyramid_values()
        mesh = bpy.data.meshes.new("Pyramid")
        bm = bmesh.new()

        for v_co in verts_loc:
            bm.verts.new(v_co)

        for f_idx in faces:
            bm.faces.new([bm.verts[i] for i in f_idx])

        bm.to_mesh(mesh)
        mesh.update()
        self.location = (0, 0, 0)

        # set the new object into the szene
        from bpy_extras import object_utils
        object_utils.object_data_add(context, mesh, operator=self)

        return {'FINISHED'}


def register():
    bpy.utils.register_class(AddPyramid)


def unregister():
    bpy.utils.unregister_class(AddPyramid)

if __name__ == "__main__":
    register()

    # create a instanz of a pyramid
    bpy.ops.mesh.primitive_pyramid_add()