Brick rowlock in Blender

Not really a BIM question, more a Blender question. But I think the question suits more here than on a generic Blender forum. I am really struggling with this one, how would you model a brick rowlock like this in Blender?

On this blog someone someone successfully manages to make different brick rowlocks with Revit using adaptive components:

I really have no idea where to start. Drawing two straight curves on top of each other and divide points on both curves?

This was my attempt using a curve modifier:

Any suggestions/ideas are more than welcome. I think this should be easily possible in Blender.

Tagged:

Comments

  • It's not parametric but using that curve modifier and then deforming using a lattice? Like tthis:

    Coen
  • You can use the Simple Deform modifier set to taper. You might have to tweak the axis depending on your spanning direction.
    It's similar to the Shear Tool, in that geometry that is orthogonal to the deformation axis stays orthogonal after deformation.

    In order to create the dircular deformation, you can create an empty, add some geometry to the bricks with a subdivision modifier (if needed), and add a Cast modifier and play with the settings.

    CoenAce
  • edited September 2021

    @Gorgious

    Yes, thank you. Now I am going to think of way to make this parametric with a Python script. And test it with an export to IFC with BlenderBIM.

  • This method works great, it's exactly what I need. It even seems to warp the brick instead of the horizontal joints. Exactly what I need.
    The export to IFC also worked:

  • edited September 2021

    Glad to see it worked out :)
    Depending on your workflow a 2D lattice with shapekeys might also do the trick and be more usable.

    It's a bit convoluted to get/set a particular shape key value :

    import bpy    
    lattice = bpy.data.objects["Lattice"]
    lattice.data.shape_keys.key_blocks["Key 1"].value = 0.5
    

    Don't hesitate to crosspost these modeling problems on https://blender.stackexchange.com/ there are people there with a lot of experience in modeling, and there is a huge bank of existing solutions too.

    Coen
  • I made a python script which makes a single brick parametric rowlock.

    Here is the code, the basis is one single brick which I used to copy and modify.

    import bpy
    import mathutils
    from itertools import repeat
    
    mesh_name = "brick" 
    collection_name = bpy.data.collections.new("BrickCollection")
    bpy.context.scene.collection.children.link(collection_name)
    
    def add_single_brick(brick_width, brick_length, brick_height, horizontal_joint, amount_of_bricks):
        print ("add single brick")
    
        vertices_brick = [  (0,0,0),
                            (0,brick_width,0),
                            (brick_length,brick_width,0),
                            (brick_length,0,0),
    
                            (0,0,brick_height),
                            (0,brick_width,brick_height),
                            (brick_length,brick_width,brick_height),
                            (brick_length,0,brick_height)
                            ]
    
        edges = []
    
        faces = [(0,1,2,3),
                 (4,5,6,7),
                 (0,4,5,1), 
                 (1,5,6,2),
                 (2,6,7,3),
                 (3,7,4,0)
                 ]
    
    
        new_mesh = bpy.data.meshes.new('brick_mesh')
        new_mesh.from_pydata(vertices_brick, edges, faces)
        new_mesh.update()
    
    
        # make object from mesh
        new_object = bpy.data.objects.new(mesh_name, new_mesh)
        collection_name.objects.link(new_object) 
    
    
        x = 0.0
        y = 0.0
        #z = 0.0 
    
    
        for y_move in range(0, amount_of_bricks):
    
            y  += (brick_width+horizontal_joint)
    
            add_row(object=new_object, x=0, y=y, z=0)
    
    
    def add_row(object, x, y, z):      
    
    
        C = bpy.context
    
        new_object = object            
        new_obj = new_object.copy()
        new_obj.animation_data_clear()
        collection_name.objects.link(new_obj)  
    
    
        # one blender unit in x-direction
        vec = mathutils.Vector((x, y, z))
        inv = new_obj.matrix_world.copy()
        inv.invert()
    
        # vector aligned to local axis in Blender 2.8+
        vec_rot = vec @ inv
        new_obj.location = new_obj.location + vec_rot    
    
    
    def join_all_bricks():              
        scene = bpy.context.scene
    
        bricks_list = []
        for brick in scene.objects:
            if brick.type == 'MESH':
                bricks_list.append(brick)
    
    
        context = bpy.context.copy()
        context['active_object'] = bricks_list[0]
        context['selected_editable_objects'] = bricks_list
    
        bpy.ops.object.join(context)
    
        for obj in bpy.data.objects:
            if (obj.name).startswith(mesh_name):
    
                #select object and set geometry to origin 
                object = bpy.data.objects[str(obj.name)]
                object.select_set(True)
                bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='MEDIAN') 
    
                #return object
    
                add_simple_deform_modifier(object)
    
    
    def add_simple_deform_modifier(object):
    
        context = bpy.context
        scene = context.scene
    
        context.view_layer.objects.active = object
        object.select_set(True)
    
        bpy.ops.object.modifier_add(type='SIMPLE_DEFORM')
        bpy.context.object.modifiers["SimpleDeform"].deform_method = 'TAPER'
        bpy.context.object.modifiers["SimpleDeform"].deform_axis = 'Z'
        bpy.context.object.modifiers["SimpleDeform"].factor = 0.2    
    
    
    brick_length = 0.21
    brick_width = 0.1
    brick_height = 0.05    
    horizontal_joint = 0.01    
    amount_of_bricks = 10
    
    add_single_brick(brick_width=brick_height, 
                    brick_length=brick_width, 
                    brick_height=brick_length,
                    horizontal_joint=horizontal_joint,
                    amount_of_bricks=amount_of_bricks)
    
    join_all_bricks() 
    add_simple_deform_modifier(object)
    
    

    The script is far from perfect and it needs a lot of refactoring, but I think it's a good basis for all kind of variations of rowlocks or other brick detailing.

    Gorgious
  • You also may rely on a "surface deform" modifier, basically works like "lattice" but using a 2d surface.

  • edited September 2021

    @Coen Just as a heads-up and general advice for python scripting, there are a number of keywords that should not be overwritten unless you know what you are doing. object is not a keyword but it's a builtin base class in python so you should avoid using it. That's why you see obj or ob instead of the clearer object in most scripts.
    eg object = bpy.data.objects[str(obj.name)] redefines the object base class.
    In most cases it will work because python is smart enough to know when you're defining a local variable that happens to overwrite a gobal builtin, but it will cause headaches down the line. Do yourself a favor and try to avoid it ^^
    I'm saying that because your script gave me an error which is caused by this caveat :

    Traceback (most recent call last):
      File "\Text", line 132, in <module>
      File "\Text", line 110, in add_simple_deform_modifier
    TypeError: BPy_PropertyRNA - Attribute (setattr): LayerObjects.active expected a Object type, not type
    Error: Python script failed, check the message in the system console
    

    That's also why your last line doesn't throw an error when it tries to call an object that doesn't exist, it's actually passing the builtin class.

    Coen
  • edited September 2021

    @Gorgious said:
    unless you know what you are doing.

    Hehe, I am a hobbyist. Thank you for the explanation. Fixed it.

    EDIT: I think I should rewrite the entire script using the bmesh module.

  • I am starting to figure out how to program in Blender with updating and creating meshes within a collection.

    I made a little demo on youtube, it's in Dutch though:

    here is the code:
    https://github.com/C-Claus/02_Blender_Python_scripts/blob/master/add_rollaag_hanekam.py

    and several IFC results with BlenderBIM making this parametric rowlock:


    I think I could do some refactoring with creating and stacking the bricks, maybe also make arched rowlocks.

    Gorgious
  • Would you be interested in using Blender UI elements to streamline the test process (using a Panel in the interface, and dynamically update the mesh with sliders instead of having to re-run the script) ? I can give you pointers if you want.

  • @Gorgious said:
    Would you be interested in using Blender UI elements to streamline the test process (using a Panel in the interface, and dynamically update the mesh with sliders instead of having to re-run the script) ? I can give you pointers if you want.

    I would be very interested, and I think many people on this forum with me. :-)


  • Which modifier should I use to make the underside of the bricks arched?

  • Using a Cast modifier set to sphere and making it affect only the bottom row of vertices with a custom Vertex Group could do it. Although it's not that easy to set up in code.
    You could also use a different approach with a Lattice modifier and a single modifier. The behaviour is a lot more predictable than the simple deform or cast modifiers.
    See :

    You can do the same with the Surface deform modifier which takes a mesh instead of a lattice like Stephen suggested. It has its pros but I don't like having to click to "Bind" the mesh.

    However since you're mathematically initializing the vertices anyways you could also do it in your script. The equation will look like co = (x, y, sin(t) / b) with t the interpolated x over your row length remapped to [0;π] and b a value to "squash" the wave.

    Coen
  • How would I store/set the location of the object when it's moved? Because I delete and make new mesh every time in the script.

  • @Coen you shouldn't need to store / set anything - just reuse the existing object but update the mesh in place - no need to delete the old mesh.

    Coen
Sign In or Register to comment.