More Legos From 3D Meshes

Mushroom Thingy

I’ve been doing more Lego building from models. This time I made sort of an abstract mushroom tree forest thing. More photos are available on Flickr.

Here’s the original model (left) and the resulting cubeified model after running it through AddCells (right):

I realized of course that with everything grey, it was very difficult to determine which bricks of which color were needed where. So I un-joined the primitives in the original model and ran AddCells on each one individually. I used different colored “cell” blocks for each one, and the resulting models kept the color:

Each peice needed to be moved a little bit so that all the blocks lined up, but other than that it worked pretty well.

Because each piece is separate, I couldn’t use the hide tool to “slice” each layer. But I did find out something interesting: each “cube” in the new models is actually a vertex. I honestly don’t understand a ton about how that’s pulled off, but┬ábasically instead of being a point on a line, each vertex represents another object, the source cube.

In order to slice up the model, I wrote a script to delete all but a given layer, with layer 1 being the bottom layer, up to however many layers of cubes are in the model.

 

import Blender, BPyMessages, BPyMesh
from Blender import Scene, Mesh, NMesh, Window, sys, Group, Object, Draw
from Blender.Mathutils import \
	Matrix, Vector, ProjectVecs, AngleBetweenVecs, TranslationMatrix

def trimToLayer(selected,layerNumber, blockHeight,offset):
        toDelete= []

        mesh = selected.getData(mesh=1)
        tmesh = NMesh.GetRawFromObject(selected.name)
        tmesh.transform(selected.matrix)
        #Delete verticies above the current layer
        for v in tmesh.verts:
            if v.co[2] > blockHeight*layer:
                toDelete.append(v.index)
        if layerNumber > 1:
                #Delete verticies below the current layer
                for v in tmesh.verts:
                    if v.co[2] < blockHeight*layer-1:
                        toDelete.append(v.index)        
        toDelete = list(set(toDelete))

        mesh.verts.delete(toDelete)
        Window.Redraw()

##################3
if __name__ == "__main__":
    selection = Object.GetSelected();

    layer = Draw.PupIntInput("Layer",1,0,100)
    Blender.SaveUndoState('Kill Everything')  
    print "\nTrimming First Layer"
    for s in selection:
	bbox = s.getBoundBox(1)
	print bbox[0][2]
	trimToLayer(s,layer,1.2,bbox[0][2])

 

There are a couple problems with the script: primarily, I couldn’t find a way to get the software to save a screenshot (ctrl+F3 normally). Because of this, I couldn’t loop through the whole thing at once, I had to go through one layer at a time, running the script, hitting ctrl+f3, saving the image, lather rinse repeat. It was tedious, though not as tedious as manually cutting up each layer. But almost.

The resulting MRI-like were used to build the model. The exact placement of which bricks and where is left as an excercise to the reader. A few layers (from the bottom, middle, and towards the top) are shown below.

This is my first attempt at a Blender script, and admittedly one of my first times using blender, so any feedback on how to streamline this process would be appreciated.

Filed under: LEGO

Tags: , ,

12 thoughts on “More Legos From 3D Meshes

  1. ken says:

    Nifty!

    You could just set up a iso camera and render each frame out. Some stuff in Blender isn’t exposed in the API, kind of annoying.

  2. Postling says:

    Hm, the issue I’ve had with rendered images is that they don’t show the mesh wire frame (which I need in the image). Is there a way to get blender to render with the wireframe?

    1. ken says:

      There’s a “Wire” option in the Links and Pipeline panel of the material that might be what you want.

  3. matle says:

    it’s not ctrl+f3, but close:

    import os
    os.system(“scrot -u nice_screenshot.jpg”)
    # os.system(“import -window root nice_screenshot.jpg”) # works, too, but captures the whole screen (you’d have to look into the -window parameter, etc. pp.. ……. take scrot, if you can.)

    Of course either scrot or the imagemagick-toolbox have to be installed for this to work.

    (BTW (and that’s why I’m grateful): thanks to this post I understood plugin-writing. Thanks a lot! (:
    )

  4. matle says:

    and of course:

    for i in range(9):
    os.system(“scrot -u screenshot_%d.jpg”%(i))

  5. Postling says:

    I’m on windows, so no scrot, but I’ll see if I can get imagemagick to play nice. Generally it doesn’t like to… but we’ll see. Thanks for the suggestion!

  6. nvp says:

    good grief, I love EVERYTHING about this

  7. Nick says:

    Can you loop it and for each slice output to a new layer and offset the x/y position so that you end up with a series of slices next to each other in a row? That way you could view them all at once and if the offset is a nice whole number it should be trivial to keep the origin sorted out.

    1. Kellbot says:

      That’s an interesting idea, I hadn’t thought of that. I may play around with that some this weekend.

  8. Angelo says:

    Are you scripting this on Blender 2.49b or some flavor of 2.5 beta?

  9. Angelo says:

    … uh it seems I’m about 5 months late to the party, just got a post on nyc resistor microcontrollers mailgroup… wierd.

    1. Kellbot says:

      Ha, not late to the party, just that while I got lots of great suggestions the implementation of them didn’t go so well so I sought out MSG for help ­čśÇ

Leave a Reply

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