What the Functor can draw that?

I want to reduce the amount of code I write, and yet increase the power of the core system.

Here are three instances of a Bezier Surface.  What’s different about them?  Their geometry is the same, meaning the exact same control curve was used in all three cases.  Their coloring is obviously different though.

In the first case,  the code looks something like this:

color(“Yellow”)
addshape(lshape3)

I simply use the general purpose ‘color()’ function to give it a nice Crayola Yellow coloring.  Nice and uniform, no fuss no muss.

In the second case, the actual rendering part is exactly the same, but the setup is a bit different.  To setup the surface in the first place, I do the following:


local lshape1 = shape_bicubicsurface.new({
M=cubic_bezier_M(),
UMult=1,
Mesh = mesh,
Thickness = thickness,
USteps = usteps,
WSteps = wsteps,
ColorSampler = colorSampler1,
})
addshape(lshape1)

The various parameters here are all very interesting, but they all have reasonable defaults.  The key here is the ‘ColorSampler = colorSampler1’, so what is colorSampler1?
local colorSampler1 = checkerboard:new({Columns=usteps, Rows=wsteps})

In this case, the checkerboard ‘object’ is a “Functor”, which can procedurally generate a color, at a given point.  It has a function:

rgba GetColor(self, u, v)

This function will be called every time the underlying machinery wants to get a color value.  Those ‘u’ and ‘v’ values will vary from 0 to 1, across the entire surface being rendered.  So, the Checkerboard pattern just needs to determine what value it wants to show, based on the ‘uv’ combination.

This is normally called Procedural Texture Mapping, in the graphics world.  It’s a fairly powerful technique, which will allow you to quickly and easily create all sorts of textures for objects, without having to deal with bitmaps.  At least for textures that can be computed, rather than being static images.  It will get really interesting when the animation system is operative.

In this case, I am using the same checkerboard procedural texture, but it’s setup a bit differently.  I can specify a “HighColor” and a “LowColor”.


torus({Offset=offset,
Size=size,
USteps = usteps,
WSteps = wsteps,
ColorSampler = checkerboard:new({Columns=usteps, Rows=wsteps, LowColor={0,0,1,1}, HighColor={1,1,1,0}})
})

Here, the checkerboard procedural texture is setup with a LowColor == blue, and a HighColor, which is white, but transparent, so nothing shows.  Why would you want to do this?  Well, let’s consider the case where you are trying to print with multiple materials.  You could easily take the exact same mesh, render it twice.  The first instance would have the HighColor set to something, and lowcolor transparent.  The second instance would have things reversed.  Then, as you generate the .stl, you could look at the color, and drop out objects with transparency, or generate a file format that would actually support changing materials like that.

So, what is a function?  It’s just a small object, that typically contains some retained parameters, and can execute a simple function.  In the case of the checkerboard pattern, the retained data is the size of the grid, and the high and low colors.  The function is “GetColor”.

This is great because you can pass this function to a core object, like the BiParametric thing, and it will handily just call your function at the right times.  You don’t have to worry about doing any of the coding to come up with the individual vertices for your mesh.

In this final case, I am using the Image ImageSampler object.  You construct it, supplying a filename, and it will deal with handing out pixels based on the ‘uv’ parameters being passed into its ‘GetColor’ function.  So, great fun.  You could of course implement filters and all manner of things within this sampler.

So, that’s what a functor can do.  Execute a simple function.  When you have a base object like BiParametric, it becomes fairly easy to do everything from determining vertices, to normals, to coloring, using these simple functors.  That makes it extremely fast to experiment and extend without having to really mess with the base class.

 


Bicubic Surfaces

And finally, the kitchen sink!

After a whole bunch of the basic primitives, if you consider the SuperShape/Formula a “basic”, I have come to the bicubic surfaces.  I originally wrote the code for this in OpenScad.  Translating it over to work in FabuCad was pretty simple, and largely involves eliminating code, and merging things back together.

If you look at the example, it’s pretty straight forward to use.  In this particular case, I’m using the Bezier basis by default.  You could just as easily substitute the Catmull-Rom or the Hermite (they’re both built in).  It’s not quite splines or nurbs, but those will come along soon enough.  The intention here is that you can pretty easily create and play with all sorts of forms of things, and quickly see them rendered and print out samples on your 3D printer.

This is reasonably fast code.  In the picture, there are 16 of these bezier surfaces, and the rendering time is a matter of seconds, not minutes or hours.  And of course creating the .stl from there is just a menu click away.

…and even if you do 100 of them,  with a facet count of 1600 apiece, it still only takes about 20 seconds to render.

Well, that’s it.

Enough functions for phase I of this thing.  I guess it’s time to write up some documentation and actually release it.


OpenScad Texture Mapping

Up until recently, I was living in a very large house, that was out in the Suburbs.  The house was too big, and the neighborhood too lonely, so we’ve decided to move to a high rise apartment in the city.  Before making the move, I wanted to do one last thing on Thingiverse before packing up the computers.  Recently, I was reading some posts on the OpenScad mail alias, and someone mentioned lighting.  That got me to thinking, ‘why can’t I deal with my own lighting in OpenScad?’  Well, for one reason or another, it’s just not possible.  OpenScad does not really expose any of the rendering pipeline to the script interface, so all you can do is your basic CSG modeling, as the renderer is just a part of the display system.

OK, so I can’t really get into the rendering pipeline, or can I?…

One of the common aspects of any rendering pipeline is doing things with “textures”, which is nothing more than a fancy term for a picture.  In classic 3D rendering, the texture object is used to give some life and, well, texture to objects displayed in a scene.  Textures are most typically like decals.  You just paste them onto the surface of what you’re viewing.

So, I created this thing: http://www.thingiverse.com/thing:11616

OpenScad has no native ability to do much with images within the CSG environment, so I had to start from the ground up.

First, I’ve got a generalized technique for representing “objects” in the environment.  OpenScad does have arrays, and you can put anything into an array, even a mix of numbers, and strings.  The first thing I wanted was a way to represent an image.  I need the basic following information:

width, height – in pixels

maxvalue – the scale of the numbers used to represent the pixels

values – an array that contains the color values representing the image.  There should be width*height*cpe numbers in the array.

cpe – components per element.  How many of the numbers are used per pixel

Now that I know how I want to represent an image, I want a convenience routine to make it easy for me to use:

image(width, height, maxvalue, values, cpe) = [width, height, maxvalue, values, cpe];

So, if I had image data that looked like this:

values = [0,0,0, 255,255,255,  255,255,255,  0,0,0];

checker = image(2,2,255,values,3)

I would get the representation of a 2×2 checkerboard pattern.  That’s a great thing, but does not quite represent an ability to do texture mapping.

The next thing I have to do is get individual pixel values out of my image.  First, is simply getting pixel values:

image_getpixel(checker, 0,0);

This will return an array with the pixel value located at [0,0] (starting from 0), which so happens to be the color value:

[0,0,0]

similarly, image_getpixel(checker, 1,0), would return the value [1,1,1]

Note that the color values have been normalized.  That is, take the raw picture data value, and divide it by ‘maxvalue’ and you get numbers between [0..1].  This is what OpenScad can deal with, so it makes sense to just do it from the beginning.

That’s great.  This in and of itself is a good step towards allowing texture mapping to occur.  How would you use it?  Well, first, you need to be in control of the generation of your objects, down to the individual facets (triangles).  If you are, as I am when generating Bezier surfaces, then you can simply apply the color to each facet.  The easiest example would be generating a replication of the image, and creating a cube with the color for each pixel:

for (x=[0:width-1])

for(y=[0:height-1])

color(image_getpixel(image, x,y))

translate([x,y,0])

cube();

That’s nice.  Now you have a little picture where the ‘pixels’ are each 1mm in size, and each pixel in the image matches one of the little cubes.

But wait, we don’t want there to be a direct connection between the number of pixels in the image and the size of our object.  Also, I don’t want to have to know the actual size of the image.  I want to be able to write routines in such a way that I can assume a single size for all images, and magic will just happen.

Therefore we need ‘normalized’ pixel locations, which will be the subject of the next post.


Revolutionary Surfaces with OpenScad

I have spent quite a lot of time with OpenScad, adding functions and whatnot.  One of the lines of improvements that I’ve been pursuing has been surfaces in general, and more recently surfaces of revolution.

Starting from the work I started with Bezier surfaces, I had first constructed basic surfaces of revolution based on simple functions, and thus began the revoloids campaign.

Having remembered some basic high school math, I was looking to generalize the idea of surfaces of revolution, so I started down the path of using cubic curves to describe surfaces of revolution.  This was an interesting path to pursue because along the way I wanted to also simplify the Bezier calculations that I was using.  As it turns out, you can specify cubic curves (which represents a broad set of curves) utilizing a simple matrix representation.  Through consultation with my various old graphics books, I was able to come up with the generalized routines to represent cubic curves.  As a result, the surface of revolution based on cubic curves can represent any cubic curve.

I encapsulated the latest of this work into the revoloids library.

In the latest incarnation of the library, I added the ability to specify a starting and ending angle for the surface.  This is nice because although you could generate the whole surface, and then slice off a bit using CSG, sometimes you actually know exactly what you want, and using CSG operations is just a waste of time.

The general mechanism I am using to render these ‘solids’ is to construct a giant piecewise polyhedron one quad at a time.  The benefit of this method is that it can be used to represent any type of 3D object, on the fly.  The downside, with respect to OpenScad, is that these objects do not play well with other objects from a CSG perspective.  Rather than seeing a piecewise polyhedron, what OpenScad really wants is a single object, with all the vertices specified, and then the faces specified from that single vertex set.  The real challenge here is that OpenScad does not have any mechanism whereby you can specify a whole bunch of vertices on the fly.  You have to construct them up front, or generate a file.

This isn’t really a limitation though, it just shows the boundary of what you can do from within the context of the OpenScad editor.  Since my math routines are fairly generic, and don’t really rely on anything within OpenScad, it will be a fairly straightforward exercise to rewrite them in ‘C’, or even javascript.  By doing such, I could simply generate the correct polyhedron, and then export it as OpenScad.

This is a generic technique I want to pursue.  Basically, construct a series of simple executables which can be chained together, with OpenScript as the final outcome.  This is what happens with the font importer utility, as well as the polygon generation flash tool.

Through this experience I have contemplated a couple of things:

OpenScad is a few things.  A domain specific language, a wrapper of other libraries.

The actual CSG work is done in CGAL.

As much as I like the OpenScad language for ease, I prefer to have a stronger language

OpenScad can have an ‘extensions’ model whereby modules that are quite useful are created and disseminated.  Right now this happens with the ‘library’ directory, but there’s not much there.

But, these are just random thoughts.  What I’m really contemplating, and currently pursuing, is implementing my routines in JavaScript, and operating in the browser, or another host.  If in the browser, then it would be WebGL.  This seems to be a quite reasonable way to go.  WebGL and HTML 5 seem to be all the rage these days.  That would give any application the ultimate reach, without having to worry about libraries such as Qt.  The biggest challenge is dealing with the CSG routines that are implemented in CGAL.  If that can be cracked, then it becomes a relative no-brainer to create an OpenScad like experience in HTML.

Besides that, the other thought is, implementing these routines directly in the 3D printer.  There’s really no reason in the world why the printer (given sufficient processing power) could not take a .scad file description, and render directly from there.  That’s another line to pursue.

At any rate, for now, these surfaces of revolution are ‘feature complete’.  I will fold these routines into the Renderer and move on to the next set of routines, which have to do with surface intersections.


Reconsidering OpenScad Extensions

I have been putting quite a lot of work into OpenScad to get more interesting surfaces out of the thing.  Why bother?  At the current moment, the most common interchange format for hobby level 3D printers is .stl files.  These are simply triangle based representations of objects.  They are well understood, and easily turned into the appropriate tool paths needed by the 3D printer.

There are numerous tools available in the world which will allow you to do design, and export to .stl files.  Most of the serious design tools, such as SolidWorks, cost many thousands of dollars, and have a multi-year learning curve to gain expertise.  I recently purchased Alibre Software, which is only $99 to get started, but even that I find to be a challenge to get up and running with any sort of proficiency.

I know programming.  For me, it’s much easier to construct a simple to medium complexity by writing a few lines of code, rather than trying to move triangles around on a mesh, and thus my interest in OpenScad.  But, OpenScad has quite a few limitations as a language which make it very challenging, and downright difficult to get some easy things done.  I find myself having to rethink how I do programming to fit within the confines of what it is capable of.  One example is the lack of true variables within functions.  Another is the fact that functions are not true expressions, but rather like macros which return a single value, and cannot have side effects.

Even so, I’ve done some work to create some new solids in OpenScad.  I found myself wanting some ellipsoids, and toroids which OpenScad does not have natively.  You can in fact create a toroid by simply rotating a circle around an axis, but it takes a couple lines of code, which I always forget.  I want to be able to simply do this:

sor_torus(innerRadius = 15, size=[10,6]);

And generate the following picture:

That’s a toroid, with a cylinder unioned with it.  In this case, the toroid has a cross section which is an ellipse, rathen than a circle.  The Ellipse form is generalized, so it can be a straight circle if the two radii are the same.

This is good and usefule, and can be used in various designs for wheels, rings, bracelets, or what have you.  It’s precise, non-confusing, and in actuality, you can control the number of facets used as well, to make it as smooth as you like.

 

 

 

 

Then there’s the Ellipsoid:

The ellipse is the more generalized form of a sphere.  With an ellipse, you can specify two different radii to make that football shape.  In OpenScad, this is achievable by using an intersection of two spheres properly placed.  But, remembering how do do that intersection and doing it in such a way that you are sure you’ll get the exact dimensions you want might be a bit challenging for some.  In this particular case, it was easy enough to use the following:

sor_ellipsoid(10,7);

That’s very handy, and easy to remember.

 

 

These are known as surfaces of revolution.  They are formed by taking some planar curve, or surface, and rotating it around an axis.  I’ve created a library in OpenScad where I do a few surfaces of revolution.  I call these revolids.scad.  This reflects the fact that they are solids of revolution.

The cool shapes are not limited to toroids and ellipsoids.  Since I did the Bezier library, I wanted to get them into the picture as well.

In this case, I’ve taken a Bezier curve, and used it to create this nice Hershey’s Kiss, or Onion shape.  Pretty easy, just define the profile you want, and rotate it around the axis like this:

sor_bezier([[0,0,0], [0, 50,0], [20,10,0], [40, 0, 0]]);

The curve can be as fancy or as simple as you like.  You can already do much of this using the built in rotation_extrude… that comes with OpenScad.  It doesn’t support bezier curves though.

 

 

 

 

While doing these extensions has been fun, and made the things I can print much more interesting, I think it’s time to go in a different direction.

There is this new effort under way: http://www.rapcad.org  In this case, the OpenScad language is being extended to include some basic features that are sorely needed.  One is true variable support, and functions that are actually expressions, so can have full bodies.  RapCad intends to add the Bezier functionality to its core as well, over time.

This is a good thing as it will further extend the capabilities of the text based design tools.

Another thing that is interesting is considering the interchange format in the first place.  Using .stl files is great, because they’re easy to understand, and easy to turn into 3D shapes for a printer.  The downside of them is that you lose core design information.  If my machine knew I was trying to do a bezier surface, it might have a better way of commanding itself to render it than simply trying to trace out a tool path based on the triangle patches it got from the .stl file.

I believe it will be possible/desirable to send .scad to my machine directly.  I believe I can create a .scad parser on the machine which can make much better decisions about tool paths that other forms of translation from .stl files.

As such, I am going to focus my attentions on this path.  The language might be OpenScad based, or it might be JavaScript.  At this point, I simply know that my days of being limited by OpenScad are coming to an end.

 


Introduction to Granules

The ultimate usage of Bezier curves will be the ability to easily specify interesting surfaces by just using a couple of curves.  While I am busy implementing bezierSurface(), I thought about a little experiment.  What if I had a system whereby I could place individual molecules of a substance.  I use the term “molecule” loosely here.  A single Lego brick could be considered a ‘molecule’ of the element “Lego”.

If I had such a system, and I had the ability to layout nice curves, surfaces, and all the other modeling goodness I do in OpenScad right now, I’d be able to construct interesting objects with precise placement of molecules.  In the graphics world, there is a representation of this.  It’s called voxels.  Voxels are elements of a volume rendering system.  They are nice because they allow you to specify things like the internal patter of a tree, so that when you slice the tree, you see the growth lines, and not just a flat shade because the texture was only on the skin.

If that doesn’t make sense…

Let’s say I want to build a piece of artificial meat.  I need a couple of things.  First I need a machine that can make very precise placements of stuff.  It’s more on the lines of what an ink jet printer does when placing droplets of ink.  If I have this, then I need molecules of meat.  Then I can place them one by one, layer upon layer.  I need some sort of binder, and there you have it.

At any rate, I created a granular based rendering sytem in OpenScad.  The models are built up out of blocks, therefore, rather than looking really smooth like you typically see, they look kind of blocky:

A picture from this thing: http://www.thingiverse.com/thing:8525

I know this is rambling.  It’s a bit hard to explain why this is interesting or makes any sense, or solves any problems.  For the moment, it’s good enough to say that it’s becoming easier to make ‘organic’ shapes in OpenScad, utilizing Bezier curves.  Along the way, I might be creating the ideal system for a future molecular pick and place machine.