You can see some sample output of stuff we're playing with here.
These are periodic snapshots of the Cichlid source tree, without the RCS/CVS directories. Some of these have windows binaries available, most of which are compiled by Todd (see his Cichlid for Windows page for more details).
For the clinically anxious, hourly snapshots of the CVS tree are available for download. They're automatically generated five minutes past each hour; note that they're not guaranteed to be stable, or even compile, though they usually should.
Added per-renderer inter-element dependence handlers to the client, that force dependent parts of vertex/edge graphs to be updated when a given element is changed. This is necessary since the display list manager considers all elements independently. Thanks to Justin Fields for pointing out the symptoms of this bug: that labels whose text didn't change weren't moving with vertices correctly.
Increased the precision on the plane representation and calculation in the BSP tree, and tightened the tolerance on the plane classification. The looser tolerance was causing problems with the scene: in some camera orientations, the painter's algorithm ordering was just completely screwed up. However, with the tighter tolerance came numerical instability problems -- polygons split by a plane would themselves appear to be cutting through the plane because of round-off errors. Increasing the precision led to much higher memory usage; I did some space-time experimenting with the partition function because an excessive number of splits wastes memory, but the partition functions are still crude and stand to be improved a lot.
Fixed some memory leaks in the PostScript module; I still haven't
fixed the duplicate free(), and there may be a leak or
two left. The code base has been modified to allow the use of
alternate malloc()/free() implementations,
such as leak-detecting variants.
Changed the Renderer interface to allow figures to be drawn and queried for changes incrementally; implemented a separate "display list manager" module that manages display lists for different figures with various strategies. This replaces the old display-list management policies, which were implicit to each type of renderer, and pretty much boiled down to using one giant list for an entire figure -- and rebuilding it all if the figure changed. Currently two strategies for display lists are implemented: using 'N' lists for the entire figure, or using 'N' elements per list.
Now that display list handling is (mostly) centralized, I was able to do some performance experiments and discover that changing the order in which display lists were compiled and executed resulted in much better performance on "real graphics hardware" like the O2.
Fixed some long-standing, fairly inconspicuous bugs in the bit-vector module that were causing un-noticeable problems with the partial updates, but very distinct problems with the new display list manager.
Fixed the triangle-strip renderer bug where the X or Y size was 1. The problem was in the averaging code, I'd left some cases out since I hadn't realized they were all possible. (Duh)
Bug update: There was a pretty hilarious bug in the bit vector module, which caused the "set all" and "clear all" operations to potentially miss some bits near the logical 'end' of the vector on big-endian machines. This is fixed as of the next snapshot.
Bug update: wahoo, there's a memory leak in the PostScript output module. It's actually in the routine that splits n-sided polygons with n>3 into triangles; when it does so, it doesn't free the original n-sided polygon. For complicated scenes with polygons up into the hundreds of thousands after splitting, this can add up to a lot of memory. This is fixed in the current code tree, so the fill will be in the next snapshot. (The barchart bug mentioned on March 28th is also currently fixed for the next snapshot -- for triangle strips but not NURBS.)
Added code for the PostScript output to do hidden surface removal using a BSP (binary space partition) tree to order the polygons back-to-front, splitting them as necessary. Where the quick-sort-based polygon reordering failed, the BSP tree comes through like a champ. The BSP tree code still spews some debugging messages; and it uses a pretty naive method to do auto-partitioning. I may look into a smarter partition function later.
Removed libGLP and it's supporting "glue" code from the tree, now that our stuff is working well.
Bug update: Bar chart graphs with an X or Y dimension of 1 don't work right with the NURBS renderer, and die a horrible death with the triangle-strip renderers. This will be addressed.
Yanked libGLP usage; it will probably be removed from the tree in the next snapshot. I'm not sure whether I'll revert the C++ linker stuff to C or not.
Re-implemented PostScript output without libGLP; it wasn't really "doing it for me". I added some infrastructure for separating the feedback primitive to output primitive transformation from the calling code. libGLP's primitive transformation algorithm, even after lots of hacking, still screws up some cases it should do fine with. I used libGLP's PostScript code as a starting point, and added a nifty Gouraud-shaded triangle algorithm I found on the 'net. The current incarnation of PS output does not support output of polygons with more than three vertices; this won't be hard to add, but I'll try to find something that generates them to test it on.
So now, the PostScript code approximates hidden-surface removal by sorting the primitives back-to-front, ordering them linearly based on the average depth values across their vertices. This can cause some odd output, but does well in many cases. The code that does this is modular, so implementing something better -- perhaps a BSP Tree -- is not out of the question.
The PS output is pretty dirty at the moment; it almost surely will not print right, and may not import as EPS correctly. These things are just PostScript nits that need to be addressed.
Fixed bugs since March 23rd.
Added some test code to do PostScript output, using Mike Sweet's GL-to-PostScript library, libGLP (version 0.1) A copy of his original code is in the "contrib_g/libGLP.orig" directory; these files aren't used directly. Modified copies of the library (with lots of fixes!) itself are built in the "contrib_g" directory. libGLP is a C++ library, so Cichlid has been updated to use the C++ linker for the client. The keystroke command 'P' will write the scene to a PostScript file, "dump.ps".
While libGLP works, and after some debugging it works fairly well, I'm still not too happy with it. I'll probably implement my own vector-graphic output module, since it's not too complicated, particularly since I can look at Mike's PostScript functions for help.
Tweaked the "Fake vBNS" server to allow clients to change the color of the fake "packets" by pointing at a control vertex. Yeah, it's kind of crufty, but it's been convenient. If I do implement my own, I'll yank the libGLP stuff from the tree.
Bug update: Bwaaaah, hah. There is a bug in the sphere draw cache code for wire-frame spheres; instead of drawing the wire-frame spheres, an invalid list would be called because of a screw-up in the index calculation, resulting in nothing being drawn (if you're lucky).
Bug update: due to a silly bug in this snapshot, if
you open a menu over a graph and select "This Graph -> Fill shapes
on/off", you'll get a nice fat core. (I forgot a break
statement.)
I've added some pop-up menus using GLUT, woo! The menu API GLUT provides is simple, but perhaps a little too simple; for now, I'll make do with it. Almost all of the old keyboard-based commands have been converted over to using the pop-up menus. The mapping of the old keystrokes to functions is the same; they now serve as shortcuts to some of the menus.
There are a few things which haven't been converted to use the menus: all of the video capture stuff, the screen-shot stuff, graph auto-rotation rate adjustment, and stereo parameter adjustment. These things all either vary some continuous parameter, or require some user text input. (I can get away with converting subsets of their functionality to the menus, of course, but I haven't thought about how I want to handle this yet.) I need to come up with an entry dialog of sorts, and a status output of sorts. Stay tuned...
The pop-up menus are accessed with the right mouse button; the camera motion functions that used to be bound to the right button are now on the middle mouse button. The one function that used to be bound to the middle mouse button -- "slamming on the brakes" in flight mode -- is no longer accessible.
Since some platforms don't have a middle mouse button equivalent, and since mousing around can be annoying at times, I've made the arrow keys emulate mouse motion. By themselves, the arrow keys act as the mouse in the current mode with the left button down. Adding SHIFT makes them emulate the middle button instead. Adding CTRL forces the camera to be moved, bypassing the current mouse mode.
I've improved the client-server protocol and framing scheme a bit; now the client can sensibly reset a dataset without losing information forever, since it can request a full update from a server. Also, the framing protocol has been converted to binary, since those string operations were annoying me. These changes wreck backward compatibility with older binaries; you'll have to re-link them. (No big deal).
Fixed a really sneaky bug that was causing some data updates to be not drawn. The problem stemmed from the way GLUT was calling the idle function. That's where we do data collection; so GLUT was calling the idle function, which would collect data and set GLUT's "redisplay needed flag". But, as it turns out, GLUT would call the idle function again before re-displaying. Cichlid just assumed that the idle function was only called when nothing was outstanding, so it would get another data update before the actual redraw came around. I fixed this by just replacing that assumption with actual code to ensure that the right thing happens. This brought to light another bug, which was preventing data updates once a window was hidden and re-exposed. The aggressive idle-function calling had sort-of masked this in the past.
Added a new server, "seq_test", which produces a conspicuous visual sequence in the hopes that any future such bugs will be immediately obvious.
Fixed up the "triangle strip" bar chart renderer a bit, getting rid of a few bugs. Added a new drawing mode for bar charts, TRISNAP_AVG9, which averages each data point with it's neighbors. Also, I made the triangle strip renderer smart enough to use the user-specified colors, instead of just being purple like the NURBS renderer.
Finally implemented statistics collection on label transmission in servers.
Incorporated some improvements submitted by Tony McGregor, namely adding the option to have the server choose it's own port (by specifying port number zero), and having the server print out it's process ID number.
Other changes include the addition of the `-maxlife' option to the server command line, which will cause the server to terminate itself if a given lifetime (real time, in seconds) is exceeded. Also, the status text prefix with every line was changed to print the process ID number of the server, instead of the port number. Finally, the status messages now all go to the same file handle, which is currently standard output. The thinking is, if you don't want all the spam from the server, you'll use `-quiet' to suppress it; having even the error messages go to stdout makes for easy logging. (Invocation error messages still go to stderr.)
I just re-implemented picking in the new branch. It seems to work fine, so the next big event will be the merging of the two branches.
(an hour later...) Okay, wow, I just merged the two branches. Though the merge ended up producing some 6000+ lines of diffs, CVS did all of the hard work, and the process was painless. It was much easier then I expected. It'd be prudent to test this for a bit, just to make sure nothing odd snuck by me.
Whoa, it's been awhile. That's school for ya.
A few months back, I decided to toy with branching in CVS; I created a new branch in the Cichlid source for experimenting, while keeping the old branch maintained, and adding some new features for SC99 folks. The old branch looks pretty much the same as previous snapshots, having only incremental changes. The new branch, possibly less stable, has some major changes on the client side to support adding a user interface.
I figured I'd snapshot the two branches, since they're getting to the point where they're almost ready to merge. Both branches have a fix for a stupid partial-updates bug. The new branch snapshot _should_ support all of the features of the old code prior to the branch-off, with the exception of picking -- I haven't gotten to that yet. It also has some new gizmos.
In short: the old branch is more along the lines of what you're used to, while the new branch is what's coming around the corner. The new branch should be considered "beta" code.
Added some layout code to the "contrib" directory to generate points spaced out along a sphere -- courtesy of Joseph O'Rourke's cool algorithm. Added a new demo server, "fuzzball", which uses this to generate it's layout. Also, fuzzball uses spherical coordinates, verifying that they do in fact work. Added a new vertex-draw method, VD_CLOUD, that draws simple little clouds to represent things like networks.
Added support for partial data updates. Now, when it's time to update the client's copy of a data object, the server calculates if it would be more space-efficient to only send the changed elements, and if so, it sends only those. This can save a lot of bandwidth, particularly on large graphs. If the client receives an empty set of changes, it will consider the object unchanged and will be able to skip the re-render entirely. Also fixed a few potential instabilities in the client where bogus data from a corrupt server could lead to crashes and such.
No changes were made to the server API, so servers don't need to be changed to take advantage of this; only re-linked. However, while the library keeps track of what data was assigned to, it does not actually compare the assigned data to see if it's changing. So, if your server blindly re-assigns the entire data set on every pass, the library will waste bandwidth blindly mirroring your assignment remotely.