What: "virtual" flying through the clouds Hot points: - simple virtual reality "thing" - can use a user-specified elevation map - with the complete source and *lots* of comments/explanations - shows off a custom (private) event queue and the flexibility it gives - NO QuickDraw3D, all rendering/graphics is done by the code itself - includes source for a small class library to handle color Mac windows and draw images on off-screen GrafWorlds (with a _real_ optimization of the CopyBits performance if found possible) - animation NOT through null-events Keywords: voxel 3D rendering, visualization, animation, elevation map, panning Contents: Readme - this file Venus v3.5 - the application itself Venus.mu - a project to build it Venus.mu.rsrc - 'clut' resource *.cc - SOURCE view_3d.cc - the 3D projector window.h \ my own private very simple MacApp: classlib for SimpleWindow.cc / handling color Mac windows and offscreen GrafWorlds *.PPM - sample elevation maps (PPGM files) one can drop onto the 'Venus v3.5' application to fly through The source code contains (too) many comments to show what a particular piece of code does, as well as some tricks involved Language: CodeWarrior C++ v11 System: System 7.x; binaries are for a PowerMac Version: 3.5, May 1997 Note: Some ancillary code is provided in a binary form (as compiled libraries) for compactness. See http://pobox.com/~oleg/ftp/ for more details. Many-Thanks-To: Tim Clarke, tjc1005@hermes.cam.ac.uk (for inspiration) Explanation: Just fire it up, sit back and enjoy. Hope you'll get some feeling that you're hovering over, or flying through the clouds. If you quit the program and start it over again, you'll get different clouds (which might be much better and more interesting to fly in). If you want to take a more active role, hold the mouse button down while moving the mouse. Your flight then is in your own hand (the one that holds the mouse). You have to keep the mouse button down all the time to hold onto control: when the mouse button is up, the thing flies by itself. You can also use the keyboard: arrows left/right/up/down move you around, PgUp/PgDn changes your altitude (or height of the horizon if pressed with the "Option"); try also 'z'/'Z' for zooming in/out. All other keys quietly kill the program (you can also quit by clicking a close box of the window). After you're done flying in a small window, click on a "zoom out" box. Yes, it does what you might expect it to, but you still may be up for some surprise... The mouse-control works here too! The Venus window is not only draggable and zoomable, it is now fully resizable. Just click on the lower right corner of the window (where the resize box usually is: the box will show up when you click there). You can then resize the window as usual. Tip! Screen updates will be _much_ faster if your monitor is set to 256 colors (that is, an indexed color, depth 8). The program won't die (let alone crash) at other settings: still, when the code detects an 8-bit indexed-color monitor, it has QuickDraw draw immensely faster. I probably can make the thing blit just as fast on direct color (that is, 24-bit color) graphic devices, but I don't have one around.... Sorry... Venus can fly through _any_ cloud image that you "drop" onto it. The image must be in a PGM format ('PPGM' type, as assigned by the GraphicConverter). The image dimensions don't matter: the program would cut and fill in as necessary (assuming that the given map is periodic).The image file may contain a custom colormap: the code would try to load the first 'clut' resource it finds; if this clut is appropriate (contains 256 entries) it will be used to color the 3D view. See the comments to "ElevationMap.cc" for more details and justification. The distribution contains a few sample maps you can drop onto the Venus. Venus is now scriptable! Well, at the moment is supports only absolutely mandatory core events: Quit, OpenApplication (which is quietly ignored) and OpenDocument (which is used to handle dropped PPGM files). Still, it's a beginning... The application sports a nifty "custom" event queue that lets one "unget" an event, or push a new event into. The events pushed can be regular events, or "my events" (with eventKind = mykind), which are used to pass around requests for zooming, resizing, loading of the map, etc. Note for example, how resizing results in re-creation of a window. Once the code detects that the resize button was clicked, the code tracks the mouse, notes the new window dimensions, _closes_ the current window, changes the WIND template, but doesn't bother opening a new window: the code merely places an order to be fulfilled by the code that created the window the first time around. The custom event queue is also used by AEEvent handlers to place an "orders" to the main event loop. This structure (of a single dispatcher and multiple event producers and consumers) makes for a rather efficient and flexible system, with maximal code reuse, and as few global dependencies (global variables) as possible. This program is inspired by MARS.EXE and its description posted in rec.games.programmer. There, the author of Mars, Tim Clarke, explained its guts, though he didn't give detailed equations and there were a few typos in his post. Source file view_3d.cc in the present submission contains the fullest description (I could come up with) of a 3D rendering technique used _here_: with background, equations, pseudocode and the actual code (and tricks with the fixed-point arithmetics: hey, no floating-point numbers are in here). I have to mention that in the present form, the rendering engine in Venus v3 has nothing to do with that of Tim Clarke's... If you need further information or details, please mail me, oleg@pobox.com New in this version of Venus (version 3.5) - New custom icons, many thanks to Teddy Schatz (BiadeRunr@aol.com) - The Venus window is not only draggable and zoomable, it is now fully resizable. - mouse control is back! As long as you hold the mouse button down, you control where you go (where the clouds flow, that is). Also works in the full-screen mode! - The elevation map can be now loaded from a dropped 'PPGM' file; if the file has a compatible clut, it will be loaded too. - Venus supports now the absolutely mandatory core suite of AppleEvents (Quit, OpenApplication, OpenDocument) - Custom event queue (with an ability to unget an event, or push new events into the queue) New in version 3.0 - A 3D rendering engine is inherited from Venus v2 (circling-in-clouds), still Venus v3 looks like Venus v1 (that is, flying-_through_-clouds) The engine's abilities to do turns and twists aren't utilized yet - Arbitrary dimensions of a view window - New keys (added z/Z for zooming in/out, added changing of both the elevation and the horizon) - New ways of doing animation (without relying on null events), although it is a null event that triggers it... - Mind boggling (but more flexible) animation classes using templates; more reliance on caches and more cutting corners: when objects are far away, we don't have to actually project every darn point... we can skip the points and/or decrease the depth at a faster rate... - Faster drawing: we try to do everything to make CopyBits work at the top of its speed: if the program finds out that QD drawing can be optimized, it will: if an off-screen GWorld and screen's GDevice found "compatible", CopyBits will be heavily hinted at it right away. In favorable circumstances, screen updates are probably as fast as one can make them using only standard system tools. When drawing on the full screen, we cut the corners a bit: since our window is the only one on screen, we can load all the colors we need directly into the GDevice, not giving a darn for the other windows... We use ColorManager's function RestoreEntries() for that purpose; btw, the third argument of this function, ReqListRec isn't explained too much in IM (say, when IM said "size" one had to read "the number of elements"; when it said "offset" it really meant "index"). So I had to do a bit of disassembling and tracing through a few system calls... Yet to do - Overlay a 2D image of clouds on the top of the 3D picture - Better hiding of a menu bar - Make it scriptable: respond to start/stop animation, allow querying and setting of projection, position, etc. parameters via AppleEvents - Allow saving of the contents of the current window (as a PICT?): via cut, drag, or in response to an AppleEvent command... - A more advanced "flying" plan with twists and turns and tumbles... - Sound?.... - The color map definitely needs an artistic touch... help will be very appreciated!