Bubbles Demo: Technical Details
This document describes technical details of the Bubbles Demo project, not directly connected to the simulation.
Compiling the source code
First you need to download the source code.
The source code is licensed under the Microsoft Public License (Ms-PL).
The project is for Microsoft Visual Studio 2008. There’s also a good chances the project will build with Visual Studio 2005: I’ve ported it only a few months ago. The project uses ATL, that’s why the freeware Express Edition won‘t work. Both 32-bit and 64-bit build targets are OK. Solely for historical reasons, the solution is named “VsTabsDemo”.
The bubbles settings dialog use WTL 8.0. To be able to build this project, please create folder named “WTL” somewhere in the include folder, e.g. in VC\atlmfc\include; then copy the .h files from the WTL’s include folder into the “WTL” folder.
The Microsoft DirectX SDK must be installed. The project uses only a small subset of Direct3D 9, so I think pretty much any version of DirectX SDK 9.0c or later will work. The DXSDK_DIR environment variable must be set to the SDK path; normally this is done automatically, during the DirectX setup.
The executable built by the release project configuration is compressed with the UPX packer. This is done by the custom build step defined in the project file. To build the release version, you must manually set the UPX_EXE environment variable to the file name & path of the UPX packer, e.g. C:\Soft\Utils\upx.exe. See the corresponding help article for more information on setting the environment variables.
Visualization
The Direct3D code is done on the top of my Direct3D 9 ATL Window class.
Point Sprites
The obvious way to output many soap bubbles that only differ in color and position is to use point sprite primitive, since drawing quads would quad the required CPU-GPU data stream. See the CBubblesWnd::SetupRenderStates function for the plumbing.
One unexpected problem I’ve encountered when I’ve implemented zoom functionality was the image scaling. If the texture image resembles the bubble used in Windows Vista screensaver, it looks OK while it’s big, and it’s almost invisible when it’s scaled down to 8x8 pixels. If however the border thickness is 1/4 of the bubble radius, the bubbles look ugly when they are large.
I’ve googled a lot, and then I’ve found the NVidia’s DDS Utilities. So first I saved the mipmapped DDS, than I used the detach.exe to split it into the set of individuals mip levels, then I edited the individual mip-levels manuallyso that on a 8x8 image the border is 1/4 of the bubble radius while the 256x256 image resembles the bubble from the screensaver, then I recombined the MIP levels into a single DDS file. The trilinear texture filtering implemented in the GPU hardware did the rest.
By the way, I’ve used the freeware paint.net software to draw the image: not only it’s good in painting, but it also saves and loads DDS files.
Coloring
There’re several possible things to visualize with bubble’s color.
Energy is defined as “the distance the bubble traveled since the previous frame”.
Structure is defined as “the number of bubbles touching the sides of this bubble”. For the infinite hexagon lattice, the “structure” value of every bubble is 6. For the alone bubble it’s zero.
I use some basic hue/saturation conversation to visualize both at the same time.
Tabbed Document Interface
I don’t like the Word 6.0-style MDI interface. I just don’t like the overall look when the document windows are overlapped. I usually have enough stuff on my table to practice my Z-ordering skill in the real life, each time I need a specific document.
Besides, the classic MDI UI reminds me my cheerless youth, with MFC 4.2, Visual C++ 5.0, and $300 monthly salary. Thanks to the Microsoft’s developer’s tools progress and the labor-market changes, now I’m much happier person then that time.
I like the tabbed multi-document interface, however.
I was able to google only one existing component that I liked. Its price tag is starting from $500, that’s why I’ve decided to implement my own one. One of my requirements was the remote desktop friendliness, that’s why I draw everything with pure GDI calls, instead of just operating memory bitmaps.
See the “VsTabs” project subfolder for the source code. To view tabs in action, run the application, and press Ctrl+D, Ctrl+G, Ctrl+I or Ctrl+M hotkeys to open new tabs with different document types, Ctrl+Tab / Ctrl + Shift + Tab to cycle around active tabs.
RGBA-Image View Class
This class does not relate with soap bubbles at all. However it’s a useful component, I’ve used it in 2 projects already. Press Ctrl+M to open the image viewer tab, filled with semi-random something.
It just displays the translucent RGBA image on the checkered background using the AlphaBlend Windows API, supports zooming across predefined levels with + / - keys or Ctrl+mouse wheel, and scrolling with left button drug.
The class is named “CImageWnd”, it’s implemented in the “Utils/ImageWnd.*” source files.
Template Vector Math Classes
The D3DX library already has a lot of mathematic routines operating on matrices, vectors, and such. However all the vectors are only single-precision floats, while sometimes the double precision arithmetic is more appropriate.
So I created my own set of template classes implementing that stuff. See the source files inside the “Math” subfolder.
Most of the code there is carefully unit-tested, which leads us to the next paragraph.
Unit-Testing Framework
If you’ll run my unit-tests on non-English windows OS, you’ll find out that some error messages are written in non-English language. Of course, you better do something with it. One way that I think might work at least with pre-Vista systems: load the English version of kernel32.dll (passing the LOAD_LIBRARY_AS_IMAGE_RESOURCE flag to LoadLibraryEx), then set the lpSource parameter of FormatMessage, and specify the FORMAT_MESSAGE_FROM_HMODULE flag.
I like the concept of unit testing.
Of course it only can be applied to the subset of the application’s code. For example, you can’t unit test your Direct3D output subsystem, as this would require grabbing and recognizing the frame buffer, which is obviously impractical to do for the sole reason of unit testing. Also you can’t unit test your UI code, as this would require simulating user clicks, and parsing the windows tree for the result, and many-many other functionality to implement and debug.
But when the subsystem is unit-testable, the unit testing is usually very good for the quality of the product being developed.
And, I didn’t like the CppUnit. Here’re my requirements for a C++ unit testing framework:
- Minimal amount of work needed to add new tests.
- Handles exceptions and crashes well.
- Template unit tests: when you have template stuff to test, you write a template unit test, and then you declare several tests that parameterize the template unit test with actual parameter types. I wanted to write single tests for both single-precision and double-precision routines.
- Two modes of execution: “Silent”, where you run all tests and get the complete report saved to your hard drive, and “Loud”, when failed test immediately traps to the debugger allowing you to fix broken things.
- The unit tests must be compiled into the same .EXE, the unit tests execution is triggered by the command-line switch. This way you’ll make your unit testing environment much more realistic. Just think about all possible differences: subsystem (win32 or console), subtle compiler or linker switches, the set of loaded DLLs, etc.
- Ability to completely wipe out all unit testing-related code from your project by changing single predefined constant, and recompiling.
I hope I’ve achieved those goals, with just ~200 lines of source code.