Lua Modeling BasicsPosted: October 3, 2011
Recently, I pushed OpenScad to the limit with the texture mapping and height mapping stuff. These routines are not particularly challenging computationally. They essentially just walk through pixel arrays, and apply those values as either color, in the case of texture mapping, or as a Z value, for the height mapping.
What I was finding is that these models might take literally hours to render. Well, that simply did not make any sense, so I started wondering as to how OpenScad deals with its variables. I did notice that if the source image was particularly large, the thing would take an exponentially larger amount of time. Little tiny images were faster. So, it seemed the amount of time spent was due to the size of the source image, no matter how complex the actual polyhedron mesh was.
As it turns out, I store the image in an array. That array gets copied almost every time it is accessed. When you’re dealing with very small arrays, you’ll never really notice the difference. But, in my case, my arrays might be 64K of data. Well, passing arrays, by value from routine to routine just is not the way to go. I confirmed this by optimizing the routines to reduce the number of copies as much as possible, and things got dramatically better. The fundamental problem is the ‘pass by value’ nature of OpenScad. It’s just one of those limitations.
In steps Lua. I rewrote the core of the height mapping routine in Lua, and in the end generate a polyhedron in OpenScad format.
In this particular case, I used Lua to generate all the points, and then simply export. The vertex generation takes only a few seconds, as compared to minutes, or hours, as would be the case in OpenScad. But OpenScad still plays a role in this particular case. After I generate all the vertices, I write them out to a file in OpenScad Polynedron format. That way, you can open up the .scad file, and play with the generated polyhedron within OpenScad. Mash it up with other stuff, and the like. When you go to “Compile” the mesh, it will only take a few seconds to compile, because it’s not actually doing any calculations. It’s just rendering a mesh. It’s roughly the equivalent of importing a .stl file, except the format is .scad instead of .stl.
Well, this is pretty nice. It means a couple of things to me. First of all, the tool chain of Lua->OpenScad is perfectly reasonable. I use the SciTE editor for editing my Lua code. As this editor is fairly mature, and is used by many languages, it gives nice syntax highliting, compiler errors, and debugging. These are all things that I miss out on with the OpenScad editor.
As Lua code has only one real data type, the table, tables are optimized to the maximum. That means the challenge of passing arrays by value simply does not exist in my Lua code. I get very fast performance, so I can experiment a lot more with the types of things I want to create.
One example is I generated some metaballs using Lua as my modeling language:
Here, I simply ported my metaball code to Lua, and ran it there to generate a point cloud. From here, I can use a tool like MeshLab to turn the point cloud into an actual polyhedron mesh, and thus a 3D object that I can print. Here it becomes interesting, as I don’t actually need MeshLab either. Since Lua is perfectly capable of doing some computation, I could create the routine to turn the point cloud into a mesh directly from Lua.
One of the basic things that I have found I need for doing modeling is some form of representation of the Polyhedron Mesh. So, one of the first objects in my new Lua library is the PolyMesh class. “Objects” are not strictly a part of the Lua language, but it’s fairly easy to construct an object abstraction in the language, so I did. The PolyMesh object has three routines at the moment:
addvertex(vertex), addedge(vertex1, vertex2, face1, face2), addface(vertices)
Between these routines, I have the rudimentary beginnings of a modeling library. I can generate points, and faces. Once I can generate faces, I can create polyhedra, and since I can easily export those to OpenScad, the sky’s the limit.
.What’s the use of doing all this? Why go down this Lua rabbit hole? I have a dream, that one day, I can send some rendering code directly to my fabricator, and it will just do the right things, no matter whether it is a lathe, 3D FDM printer, or a CNC router. Lua is a light weight and fairly decently powered, free, language runtime that will easily run on just about any device I care to put it on. If that’s the ultimate outcome, then I’d like to ride that food chain all the way from the beginning, starting at the modeling program itself.
At any rate, I’m making progress on my little library, porting some, creating new stuff, and generally having fun.
And of course, all the code is readily available on GitHub: https://github.com/Wiladams/LuaModeling
So, if you want to follow along the madness, you can.