If those monkeys pound on those keyboards enough, eventually a masterpiece will emerge… Well, software development can be like that sometimes. I’ve been spending quite a lot of time on 2D graphics.
Part of doing 3D CAD is being able to create a surface of revolution (revoloid). Well, in order to create a revoloid, I need to be able to draw a curve, which will then be rotated around an axis. Well, in order to create a curve, I need to have a nice grid I can use as a guide, and I need control points, and mouse control of those points, etc.
So, I create those various bits and pieces. I think the grid thing is really cool. You can specify the distance between the light and dark lines. You can specify the colors as well. It becomes useful when you need a backdrop for drawing, or displaying stuff in general to scale.
There have been other graphics along the way as well. This arrow thing is useful in that the dark gray area can hold other graphics and controls. Perhaps it doesn’t make sense sitting there on its own, but it does when it’s combined with other things.
Of course, no UI toolkit these days would be complete without having tabbed views. So, there they are… Of course, since the tabs are created using the ShapeBuilder object, you can get rounded corners instead of those sharp corners if you like. Since these are just graphics objects, you can also fairly easily do drop shadows, glowing backgrounds, and the like. And, since they are “Actor” objects, they can respond to “Update” messages, and change with time, if that’s useful.
I recently purchased a BeagleBone. A nifty little piece of kit that one. It uses a TI AM3358 ARM Cortex-A8 based microprocessor. The board has ethernet and USB built in. One of the benefits of the little board is that you can run an Android distribution on it. Also, it has some graphics capabilities, including support for a VNC host, so you can see what’s on it’s “screen”.
I fully intend to put BanateCAD on this little device. The Beaglebone is good in that it represents a fairly constrained system. It has a 4Gb micro SD card, and 256Mb of RAM. It runs at 700Mhz. I’m thinking this should be a beefy enough spec to run a simple 3D CAD modeling program such as BanateCAD. Also, if I can run on this little device, then certainly I can run on any Android device. I’ll see how it goes.
At any rate, things progress. 2D UI, 3D shapes, monkeys on typewriters… Soon enough something interesting will pop out of this little exercise.
Trundling along, minding my own business, making the world safe for doing some graphics…
I have created a new package called “HeadsUp”. It is the 2D portion of the BanateCAD package. Programming within HeadsUp is very similar to programming in the “Processing” environment, but it’s all in Lua instead of Java of course.
You can find the download here: HeadsUp
Within the package, you will find many examples to play with. HeadsUp is named such because the relation to 3D graphics is that you can create a “Heads Up Display” if you will. You can easily create static images, or you can create dynamic animations as it has an integral animation clock. You load a .lua program, click the “Start” menu, and see what happens.
The other day, I went to the grocery store and got the groceries packed in a paper bag. On the back of the bag was this interesting chart about the growing seasons of various fruits and vegetables.
I looked at that and thought: “How hard would that be to replicate using HeadsUp?”
So, I set out to replicate the graph. Along the way, I discovered a few things. I cleaned up some of the text rendering, found a bug in setting the fill color, and made better text alignment. The basics of line, rectangle, and text rendering are obviously there, as well as the ellipse, and line thickness. It was also an experiment in data representation. For the raw data such as the various growing seasons per food item, should I represent it as a CSV file, an XML, JSON? The easiest, since I am using Lua, was to simply represent it as a Lua table. That way, there’s no conversion from one type/schema system to another. Also, I think the lua version of the data is just as easily readable as XML or JSON, so it could easily act as the exchange format as well.
This is all goodness. The other thing I rediscovered is that laying things out by hand is a real pain. I did use algorithms to do the layout, but I could go further. Doing layout in a more declarative way is much simpler. Of course we know this from decades of UI design, and the growth of HTML. I have the rudiments of layout, but it’s not used in any serious way as yet.
Another little bit that got worked on was the mouse interaction. There is a new mouse event thing, that gets passed around the system. Nothing special if you’re not programming down at that level, but there nonetheless.
This is an image of the mouse tracking test program. Basically, you move the mouse around on the screen, and the position is displayed in the center there. A nice cross-hairs will follow your mouse around, just so you can see it tracking correctly. That’s a bit nice because under your program’s control, you can simply turn off the system’s cursor, and create your own cursor to be whatever graphic you feel like rendering.
One more thing I discovered when doing this little bit was that the mouse tracking system does not have to be as complex or rigid as I was going to make it. I have been borrowing some code from a UI framework I did in C#. What I have typically done in the past is to make a core “Graphics” object, which any graphic would descend from in a class hierarchy. This graphic object would take care of hierarchy, grouping, mouse tracking, keyboard tracking, transform, style, etc.
Programming in Lua, I find there’s a much simpler way. For rendering, any ‘object’ simply implements the “Render(graphPort)” method. The object is handed the graph port, and it does whatever rendering it wants to do. It does not have to be in any class hierarchy. If the developer wants hierarchy, they can simply add what they want.
Similarly, for mouse tracking, an object can register itself with the system saying “yes, I participate in mouse and keyboard interactions”. This is kind of an observer/observed pattern. Again, you don’t have to subclass, just implement the “MouseActivity()” method. You’ll be handed the mouse activity object, and you can do whatever you want from there.
Of course, if you want to change the behavior of the system, that’s fairly straightforward. You have the source code, so you can do what you like. Or you could inject some functors here and there, and make small compact compatible changes.
I always have the goal of reducing the code size. Smaller is definitely better. In this case, I’ve managed to stay within my 256K budget, including code for the examples. So, it can only get smaller from here.
At any rate, a new toy to play with.